Merged in facebook-group-chat--sort-list (pull request #428)

Fri, 30 Nov 2018 02:50:38 +0000

author
Gary Kramlich <grim@reaperworld.com>
date
Fri, 30 Nov 2018 02:50:38 +0000
changeset 39338
7d4e3cd0bbf9
parent 39335
b357de550198 (diff)
parent 39337
8b53f4ffdc1b (current diff)
child 39339
c3977899ce84

Merged in facebook-group-chat--sort-list (pull request #428)

Sort the facebook contacts by name/alias in group chat.

Approved-by: Elliott Sales de Andrade
Approved-by: Gary Kramlich
Approved-by: Eion Robb

--- a/doc/reference/finch/finch-docs.xml	Thu Nov 22 11:25:59 2018 +0200
+++ b/doc/reference/finch/finch-docs.xml	Fri Nov 30 02:50:38 2018 +0000
@@ -26,7 +26,6 @@
       <xi:include href="xml/gntaccount.xml" />
       <xi:include href="xml/gntblist.xml" />
       <xi:include href="xml/gntpounce.xml" />
-      <xi:include href="xml/gntcertmgr.xml" />
       <xi:include href="xml/gntconn.xml" />
       <xi:include href="xml/gntconv.xml" />
       <xi:include href="xml/gntdebug.xml" />
--- a/doc/reference/libpurple/libpurple-docs.xml	Thu Nov 22 11:25:59 2018 +0200
+++ b/doc/reference/libpurple/libpurple-docs.xml	Fri Nov 30 02:50:38 2018 +0000
@@ -83,8 +83,6 @@
       <xi:include href="xml/theme.xml" />
       <xi:include href="xml/theme-loader.xml" />
       <xi:include href="xml/theme-manager.xml" />
-      <xi:include href="xml/tls-certificate-info.xml" />
-      <xi:include href="xml/tls-certificate.xml" />
       <xi:include href="xml/trie.xml" />
       <xi:include href="xml/sound-theme.xml" />
       <xi:include href="xml/sound-theme-loader.xml" />
--- a/doc/reference/pidgin/pidgin-docs.xml	Thu Nov 22 11:25:59 2018 +0200
+++ b/doc/reference/pidgin/pidgin-docs.xml	Fri Nov 30 02:50:38 2018 +0000
@@ -25,7 +25,6 @@
       <xi:include href="xml/gtkblist-theme-loader.xml" />
       <xi:include href="xml/gtkpounce.xml" />
       <xi:include href="xml/gtkcellrendererexpander.xml" />
-      <xi:include href="xml/gtkcertmgr.xml" />
       <xi:include href="xml/gtkconn.xml" />
       <xi:include href="xml/gtkconv.xml" />
       <xi:include href="xml/gtkconvwin.xml" />
--- a/finch/gntcertmgr.c	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,351 +0,0 @@
-/* finch
- *
- * Finch is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-
-#include <internal.h>
-#include "finch.h"
-
-#include "debug.h"
-#include "notify.h"
-#include "request.h"
-#include "tls-certificate.h"
-#include "tls-certificate-info.h"
-
-#include "gntcertmgr.h"
-
-#include "gntbutton.h"
-#include "gntlabel.h"
-#include "gnttree.h"
-#include "gntutils.h"
-#include "gntwindow.h"
-
-struct {
-	GntWidget *window;
-	GntWidget *tree;
-} certmgr;
-
-/* Pretty much Xerox of gtkcertmgr */
-
-/* Add certificate */
-static void
-tls_peers_mgmt_import_ok2_cb(gpointer data, const char *result)
-{
-	GTlsCertificate *crt = data;
-	const char *id = result;
-	GError *error = NULL;
-
-	/* TODO: Perhaps prompt if you're overwriting a cert? */
-
-	if (purple_tls_certificate_trust(id, crt, &error)) {
-		gnt_tree_add_row_last(GNT_TREE(certmgr.tree), g_strdup(id),
-				gnt_tree_create_row(GNT_TREE(certmgr.tree), id),
-				NULL);
-	} else {
-		purple_debug_error("gntcertmgr/tls_peers_mgmt",
-				"Failure trusting peer certificate '%s': %s",
-				id, error->message);
-		g_clear_error(&error);
-	}
-
-	g_object_unref(crt);
-}
-
-static void
-tls_peers_mgmt_import_ok_cb(gpointer data, const char *filename)
-{
-	GTlsCertificate *crt;
-	GError *error = NULL;
-
-	crt = g_tls_certificate_new_from_file(filename, &error);
-
-	if (crt != NULL) {
-		gchar *default_hostname;
-		PurpleTlsCertificateInfo *info;
-
-		info = purple_tls_certificate_get_info(crt);
-		default_hostname = purple_tls_certificate_info_get_subject_name(info);
-		purple_tls_certificate_info_free(info);
-
-		purple_request_input(NULL,
-				_("Certificate Import"),
-				_("Specify a hostname"),
-				_("Type the host name this certificate is for."),
-				default_hostname, FALSE, FALSE, NULL,
-				_("OK"), G_CALLBACK(tls_peers_mgmt_import_ok2_cb),
-				_("Cancel"), G_CALLBACK(g_object_unref),
-				NULL, crt);
-		g_free(default_hostname);
-	} else {
-		gchar * secondary;
-
-		purple_debug_error("gntcertmgr/tls_peers_mgmt",
-				"Failed to import certificate '%s': %s",
-				filename, error->message);
-		g_clear_error(&error);
-
-		secondary = g_strdup_printf(_("File %s could not be imported.\nMake sure that the file is readable and in PEM format.\n"), filename);
-		purple_notify_error(NULL,
-				_("Certificate Import Error"),
-				_("X.509 certificate import failed"),
-				secondary, NULL);
-		g_free(secondary);
-	}
-}
-
-static void
-add_cert_cb(GntWidget *button, gpointer null)
-{
-	purple_request_file(NULL,
-			_("Select a PEM certificate"),
-			"certificate.pem",
-			FALSE,
-			G_CALLBACK(tls_peers_mgmt_import_ok_cb),
-			NULL,
-			NULL, NULL );
-}
-
-/* Save certs in some file */
-static void
-tls_peers_mgmt_export_ok_cb(gpointer data, const char *filename)
-{
-	GTlsCertificate *crt = data;
-	gchar *pem = NULL;
-	GError *error = NULL;
-
-	g_object_get(crt, "certificate-pem", &pem, NULL);
-	g_return_if_fail(crt != NULL);
-
-	if (!g_file_set_contents(filename, pem, -1, &error)) {
-		gchar * secondary;
-
-		purple_debug_error("gntcertmgr/tls_peers_mgmt",
-				"Failed to export certificate '%s': %s",
-				filename, error->message);
-		g_clear_error(&error);
-
-		secondary = g_strdup_printf(_("Export to file %s failed.\nCheck that you have write permission to the target path\n"), filename);
-		purple_notify_error(NULL,
-				    _("Certificate Export Error"),
-				    _("X.509 certificate export failed"),
-				    secondary, NULL);
-		g_free(secondary);
-	}
-
-	g_free(pem);
-	g_object_unref(crt);
-}
-
-static void
-save_cert_cb(GntWidget *button, gpointer null)
-{
-	GTlsCertificate *crt;
-	const char *key;
-	GError *error = NULL;
-
-	if (!certmgr.window)
-		return;
-
-	key = gnt_tree_get_selection_data(GNT_TREE(certmgr.tree));
-	if (!key)
-		return;
-
-	crt = purple_tls_certificate_new_from_id(key, &error);
-
-	if (!crt) {
-		purple_debug_error("gntcertmgr/tls_peers_mgmt",
-				"Failed to fetch trusted certificate '%s': %s",
-				key, error->message);
-		g_clear_error(&error);
-		return;
-	}
-
-	purple_request_file((void*)key,
-			_("PEM X.509 Certificate Export"),
-			"certificate.pem", TRUE,
-			G_CALLBACK(tls_peers_mgmt_export_ok_cb),
-			G_CALLBACK(g_object_unref),
-			NULL, crt);
-}
-
-/* Show information about a cert */
-static void
-info_cert_cb(GntWidget *button, gpointer null)
-{
-	const char *key;
-	GTlsCertificate *crt;
-	PurpleTlsCertificateInfo *info;
-	gchar *subject;
-	GByteArray *fpr_sha1;
-	gchar *fpr_sha1_asc;
-	gchar *primary, *secondary;
-
-	if (!certmgr.window)
-		return;
-
-	key = gnt_tree_get_selection_data(GNT_TREE(certmgr.tree));
-	if (!key)
-		return;
-
-	crt = purple_tls_certificate_new_from_id(key, NULL);
-	g_return_if_fail(crt);
-
-	primary = g_strdup_printf(_("Certificate for %s"), key);
-
-	fpr_sha1 = purple_tls_certificate_get_fingerprint_sha1(crt);
-	fpr_sha1_asc = purple_base16_encode_chunked(fpr_sha1->data,
-						    fpr_sha1->len);
-
-	info = purple_tls_certificate_get_info(crt);
-	subject = purple_tls_certificate_info_get_subject_name(info);
-	purple_tls_certificate_info_free(info);
-
-	secondary = g_strdup_printf(_("Common name: %s\n\nSHA1 fingerprint:\n%s"), subject, fpr_sha1_asc);
-
-	purple_notify_info(NULL,
-			   _("SSL Host Certificate"), primary, secondary, NULL);
-
-	g_free(primary);
-	g_free(secondary);
-	g_byte_array_free(fpr_sha1, TRUE);
-	g_free(fpr_sha1_asc);
-	g_free(subject);
-	g_object_unref(crt);
-}
-
-/* Delete a cert */
-static void
-tls_peers_mgmt_delete_confirm_cb(gchar *id, gint dontcare)
-{
-	GError *error = NULL;
-
-	if (!purple_tls_certificate_distrust(id, &error)) {
-		purple_debug_warning("gntcertmgr/tls_peers_mgmt",
-				"Deletion failed on id '%s': %s\n",
-				id, error->message);
-		g_clear_error(&error);
-	};
-
-	purple_request_close_with_handle((void*)id);
-	gnt_tree_remove(GNT_TREE(certmgr.tree), (void*)id);
-
-	g_free(id);
-}
-
-static void
-delete_cert_cb(GntWidget *button, gpointer null)
-{
-	gchar *primary;
-	const char *key;
-
-	if (!certmgr.window)
-		return;
-
-	key = gnt_tree_get_selection_data(GNT_TREE(certmgr.tree));
-	if (!key)
-		return;
-
-	primary = g_strdup_printf(_("Really delete certificate for %s?"), key);
-
-	purple_request_close_with_handle((void *)key);
-	purple_request_yes_no((void *)key, _("Confirm certificate delete"),
-			primary, NULL,
-			0,
-			NULL,
-			g_strdup(key),
-			tls_peers_mgmt_delete_confirm_cb,
-			g_free);
-
-	g_free(primary);
-}
-
-/* populate the list */
-static void
-populate_cert_list(void)
-{
-	GList *idlist, *l;
-
-	if (!certmgr.window)
-		return;
-
-	gnt_tree_remove_all(GNT_TREE(certmgr.tree));
-
-	idlist = purple_tls_certificate_list_ids();
-	for (l = idlist; l; l = l->next) {
-		gnt_tree_add_row_last(GNT_TREE(certmgr.tree), g_strdup(l->data),
-				gnt_tree_create_row(GNT_TREE(certmgr.tree), l->data), NULL);
-	}
-	purple_tls_certificate_free_ids(idlist);
-}
-
-void finch_certmgr_show(void)
-{
-	GntWidget *win, *tree, *box, *button;
-
-	if (certmgr.window) {
-		gnt_window_present(certmgr.window);
-		return;
-	}
-
-	certmgr.window = win = gnt_vwindow_new(FALSE);
-	gnt_box_set_title(GNT_BOX(win), _("Certificate Manager"));
-	gnt_box_set_pad(GNT_BOX(win), 0);
-
-	certmgr.tree = tree = gnt_tree_new();
-	gnt_tree_set_hash_fns(GNT_TREE(tree), g_str_hash, g_str_equal, g_free);
-	gnt_tree_set_column_title(GNT_TREE(tree), 0, _("Hostname"));
-	gnt_tree_set_show_title(GNT_TREE(tree), TRUE);
-
-	gnt_box_add_widget(GNT_BOX(win), tree);
-
-	box = gnt_hbox_new(FALSE);
-	gnt_box_add_widget(GNT_BOX(win), box);
-
-	button = gnt_button_new(_("Add"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(add_cert_cb), NULL);
-	gnt_util_set_trigger_widget(GNT_WIDGET(tree), GNT_KEY_INS, button);
-
-	button = gnt_button_new(_("Save"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(save_cert_cb), NULL);
-
-	button = gnt_button_new(_("Info"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(info_cert_cb), NULL);
-
-	button = gnt_button_new(_("Delete"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(delete_cert_cb), NULL);
-	gnt_util_set_trigger_widget(GNT_WIDGET(tree), GNT_KEY_DEL, button);
-
-	button = gnt_button_new(_("Close"));
-	gnt_box_add_widget(GNT_BOX(box), button);
-	g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), win);
-
-	g_signal_connect_swapped(G_OBJECT(win), "destroy", G_CALLBACK(g_nullify_pointer), &certmgr.window);
-
-	populate_cert_list();
-
-	g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(purple_signals_disconnect_by_handle), NULL);
-
-	gnt_widget_show(certmgr.window);
-}
-
--- a/finch/gntcertmgr.h	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/* finch
- *
- * Finch is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-
-#ifndef _GNT_CERTMGR_H
-#define _GNT_CERTMGR_H
-/**
- * SECTION:gntcertmgr
- * @section_id: finch-gntcertmgr
- * @short_description: <filename>gntcertmgr.h</filename>
- * @title: Certificate Manager API
- */
-
-void finch_certmgr_show(void);
-
-#endif
--- a/finch/gntrequest.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/finch/gntrequest.c	Fri Nov 30 02:50:38 2018 +0000
@@ -34,7 +34,6 @@
 #include "finch.h"
 #include "gntrequest.h"
 #include "debug.h"
-#include "tls-certificate-info.h"
 #include "util.h"
 
 typedef struct
@@ -575,26 +574,6 @@
 	return combo;
 }
 
-static GntWidget*
-create_certificate_field(PurpleRequestField *field)
-{
-	GntWidget *w;
-	GTlsCertificate *cert;
-	PurpleTlsCertificateInfo *info;
-	char *str;
-
-	cert = purple_request_field_certificate_get_value(field);
-	info = purple_tls_certificate_get_info(cert);
-	str = purple_tls_certificate_info_get_display_string(info);
-	purple_tls_certificate_info_free(info);
-
-	w = gnt_label_new(str);
-
-	g_free(str);
-
-	return w;
-}
-
 static void
 multifield_extra_cb(GntWidget *button, PurpleRequestFields *allfields)
 {
@@ -695,10 +674,6 @@
 				accountlist = create_account_field(field);
 				purple_request_field_set_ui_data(field, accountlist);
 			}
-			else if (type == PURPLE_REQUEST_FIELD_CERTIFICATE)
-			{
-				purple_request_field_set_ui_data(field, create_certificate_field(field));
-			}
 			else
 			{
 				purple_request_field_set_ui_data(field, gnt_label_new_with_format(_("Not implemented yet."),
--- a/finch/gntui.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/finch/gntui.c	Fri Nov 30 02:50:38 2018 +0000
@@ -26,7 +26,6 @@
 
 #include "gntaccount.h"
 #include "gntblist.h"
-#include "gntcertmgr.h"
 #include "gntconn.h"
 #include "gntconv.h"
 #include "gntdebug.h"
@@ -103,7 +102,6 @@
 	gnt_register_action(_("Accounts"), finch_accounts_show_all);
 	gnt_register_action(_("Buddy List"), finch_blist_show);
 	gnt_register_action(_("Buddy Pounces"), finch_pounces_manager_show);
-	gnt_register_action(_("Certificates"), finch_certmgr_show);
 	gnt_register_action(_("Debug Window"), finch_debug_window_show);
 	gnt_register_action(_("File Transfers"), finch_xfer_dialog_show);
 	gnt_register_action(_("Plugins"), finch_plugins_show_all);
--- a/finch/meson.build	Thu Nov 22 11:25:59 2018 +0200
+++ b/finch/meson.build	Fri Nov 30 02:50:38 2018 +0000
@@ -16,7 +16,6 @@
 libfinch_SOURCES = [
 	'gntaccount.c',
 	'gntblist.c',
-	'gntcertmgr.c',
 	'gntconn.c',
 	'gntconv.c',
 	'gntdebug.c',
@@ -41,7 +40,6 @@
 libfinch_headers = [
 	'gntaccount.h',
 	'gntblist.h',
-	'gntcertmgr.h',
 	'gntconn.h',
 	'gntconv.h',
 	'gntdebug.h',
--- a/libpurple/http.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/http.c	Fri Nov 30 02:50:38 2018 +0000
@@ -30,14 +30,14 @@
 #include "purple-gio.h"
 
 #define PURPLE_HTTP_URL_CREDENTIALS_CHARS "a-z0-9.,~_/*!&%?=+\\^-"
-#define PURPLE_HTTP_MAX_RECV_BUFFER_LEN 10240
-#define PURPLE_HTTP_MAX_READ_BUFFER_LEN 10240
+#define PURPLE_HTTP_MAX_RECV_BUFFER_LEN 102400
+#define PURPLE_HTTP_MAX_READ_BUFFER_LEN 102400
 #define PURPLE_HTTP_GZ_BUFF_LEN 1024
 
 #define PURPLE_HTTP_REQUEST_DEFAULT_MAX_REDIRECTS 20
 #define PURPLE_HTTP_REQUEST_DEFAULT_TIMEOUT 30
 #define PURPLE_HTTP_REQUEST_DEFAULT_MAX_LENGTH 1048576
-#define PURPLE_HTTP_REQUEST_HARD_MAX_LENGTH G_MAXINT32-1
+#define PURPLE_HTTP_REQUEST_HARD_MAX_LENGTH (G_MAXINT32 - 1)
 
 #define PURPLE_HTTP_PROGRESS_WATCHER_DEFAULT_INTERVAL 250000
 
@@ -338,15 +338,17 @@
 		d_year, month, d_date, d_time);
 
 	g_free(d_date);
-	g_free(d_month);
 	g_free(d_year);
 	g_free(d_time);
 
 	if (month > 12) {
 		purple_debug_warning("http", "Invalid month: %s\n", d_month);
+		g_free(d_month);
 		g_free(iso_date);
 		return 0;
 	}
+	
+	g_free(d_month);
 
 	t = purple_str_to_time(iso_date, TRUE, NULL, NULL, NULL);
 
@@ -438,6 +440,7 @@
 				error->message);
 			g_clear_error(&error);
 			gzs->failed = TRUE;
+			g_string_free(ret, TRUE);
 			return NULL;
 		}
 	}
@@ -834,6 +837,17 @@
 	purple_http_conn_cancel(hc);
 }
 
+static void memset_zero(gpointer pnt, gsize len)
+{
+	volatile unsigned char *volatile pnt_ =
+		(volatile unsigned char *volatile) pnt;
+	size_t i = (size_t) 0U;
+
+	while (i < len) {
+		pnt_[i++] = 0U;
+	}
+}
+
 static void _purple_http_gen_headers(PurpleHttpConnection *hc)
 {
 	GString *h;
@@ -897,7 +911,7 @@
 		purple_http_request_is_method(req, "post")))
 	{
 		g_string_append_printf(h, "Content-Length: %u\r\n",
-			req->contents_length);
+			(guint) req->contents_length);
 	}
 
 	if (proxy_http)
@@ -915,7 +929,7 @@
 		tmp = g_strdup_printf("%s:%s", proxy_username, proxy_password);
 		len = strlen(tmp);
 		proxy_auth = g_base64_encode((const guchar *)tmp, len);
-		memset(tmp, 0, len);
+		memset_zero(tmp, len);
 		g_free(tmp);
 
 		ntlm_type1 = purple_http_ntlm_gen_type1(purple_get_host_name(),
@@ -927,7 +941,7 @@
 			ntlm_type1);
 		g_string_append(h, "Proxy-Connection: close\r\n"); /* TEST: proxy+KeepAlive */
 
-		memset(proxy_auth, 0, strlen(proxy_auth));
+		memset_zero(proxy_auth, strlen(proxy_auth));
 		g_free(proxy_auth);
 		g_free(ntlm_type1);
 	}
@@ -1307,7 +1321,11 @@
 			int buffer_len = hc->response_buffer->len;
 			gchar *buffer = g_string_free(hc->response_buffer, FALSE);
 			hc->response_buffer = NULL;
-			_purple_http_recv_body(hc, buffer, buffer_len);
+			if (!_purple_http_recv_body(hc, buffer, buffer_len))
+			{
+				g_free(buffer);
+				return FALSE;
+			}
 			g_free(buffer);
 		}
 		if (!hc->headers_got)
@@ -1578,6 +1596,10 @@
 	if (hc->response_buffer)
 		g_string_free(hc->response_buffer, TRUE);
 	hc->response_buffer = NULL;
+	
+	if (hc->gz_stream)
+		purple_http_gz_free(hc->gz_stream);
+	hc->gz_stream = NULL;
 
 	if (hc->socket_request)
 		purple_http_keepalive_pool_request_cancel(hc->socket_request);
@@ -1876,7 +1898,9 @@
 			http_conn);
 	}
 
-	http_conn->response->code = 0;
+	if (http_conn->response != NULL) {
+		http_conn->response->code = 0;
+	}
 	_purple_http_disconnect(http_conn, FALSE);
 	purple_http_connection_terminate(http_conn);
 }
@@ -1889,7 +1913,9 @@
 
 	purple_debug_info("http", "Retrying connection %p...\n", http_conn);
 
-	http_conn->response->code = 0;
+	if (http_conn->response != NULL) {
+		http_conn->response->code = 0;
+	}
 	_purple_http_disconnect(http_conn, FALSE);
 	_purple_http_reconnect(http_conn);
 }
@@ -1905,7 +1931,7 @@
 
 	gc_list = g_hash_table_lookup(purple_http_hc_by_gc, gc);
 
-	g_hash_table_insert(purple_http_cancelling_gc, gc, GINT_TO_POINTER(TRUE));
+	g_hash_table_insert(purple_http_cancelling_gc, gc, GINT_TO_POINTER(1));
 
 	while (gc_list) {
 		PurpleHttpConnection *hc = gc_list->data;
@@ -2590,7 +2616,7 @@
 		purple_http_connection_set_remove(http_conn->connection_set,
 			http_conn);
 	}
-	g_hash_table_insert(set->connections, http_conn, (gpointer)TRUE);
+	g_hash_table_insert(set->connections, http_conn, GINT_TO_POINTER(1));
 	http_conn->connection_set = set;
 }
 
@@ -3235,7 +3261,9 @@
 	if (parsed_url->username || parsed_url->password) {
 		if (parsed_url->username)
 			g_string_append(url, parsed_url->username);
-		g_string_append_printf(url, ":%s", parsed_url->password);
+		g_string_append_c(url, ':');
+		if (parsed_url->password)
+			g_string_append(url, parsed_url->password);
 		g_string_append(url, "@");
 		before_host_printed = TRUE;
 	}
@@ -3381,8 +3409,9 @@
 	g_regex_unref(purple_http_re_rfc1123);
 	purple_http_re_rfc1123 = NULL;
 
-	g_list_foreach(purple_http_hc_list, purple_http_foreach_conn_cancel,
-		NULL);
+	if (purple_http_hc_list != NULL) {
+		g_list_foreach(purple_http_hc_list, purple_http_foreach_conn_cancel, NULL);
+	}
 
 	if (purple_http_hc_list != NULL ||
 		0 != g_hash_table_size(purple_http_hc_by_ptr) ||
--- a/libpurple/meson.build	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/meson.build	Fri Nov 30 02:50:38 2018 +0000
@@ -71,8 +71,6 @@
 	'theme.c',
 	'theme-loader.c',
 	'theme-manager.c',
-	'tls-certificate.c',
-	'tls-certificate-info.c',
 	'trie.c',
 	'upnp.c',
 	'util.c',
@@ -153,8 +151,6 @@
 	'theme.h',
 	'theme-loader.h',
 	'theme-manager.h',
-	'tls-certificate.h',
-	'tls-certificate-info.h',
 	'trie.h',
 	'upnp.h',
 	'util.h',
--- a/libpurple/protocols/gg/gg.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/protocols/gg/gg.c	Fri Nov 30 02:50:38 2018 +0000
@@ -33,6 +33,7 @@
 #include "notify.h"
 #include "buddylist.h"
 #include "accountopt.h"
+#include "core.h"
 #include "debug.h"
 #include "util.h"
 #include "request.h"
@@ -591,6 +592,56 @@
 	gg_free_event(ev);
 }
 
+static gint
+gg_uri_handler_find_account(gconstpointer a, gconstpointer b)
+{
+	PurpleAccount *account = PURPLE_ACCOUNT(a);
+	const gchar *protocol_id;
+
+	protocol_id = purple_account_get_protocol_id(account);
+
+	if (purple_strequal(protocol_id, "prpl-gg") &&
+			purple_account_is_connected(account)) {
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+static gboolean
+gg_uri_handler(const gchar *scheme, const gchar *screenname,
+		GHashTable *params)
+{
+	GList *accounts;
+	GList *account_node;
+	PurpleIMConversation *im;
+
+	g_return_val_if_fail(screenname != NULL, FALSE);
+
+	if (!purple_strequal(scheme, "gg")) {
+		return FALSE;
+	}
+
+	if (screenname[0] == '\0') {
+		purple_debug_warning("gg", "Invalid empty screenname in URI");
+		return FALSE;
+	}
+
+	/* Find online Gadu-Gadu account */
+	accounts = purple_accounts_get_all();
+	account_node = g_list_find_custom(accounts, NULL,
+			gg_uri_handler_find_account);
+
+	if (account_node == NULL) {
+		return FALSE;
+	}
+
+	im = purple_im_conversation_new(account_node->data, screenname);
+	purple_conversation_present(PURPLE_CONVERSATION(im));
+
+	return TRUE;
+}
+
 /* ---------------------------------------------------------------------- */
 /* ----- PurpleProtocol ----------------------------------------- */
 /* ---------------------------------------------------------------------- */
@@ -1154,12 +1205,18 @@
 	ggp_html_setup();
 	ggp_message_setup_global();
 
+	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
+			PURPLE_CALLBACK(gg_uri_handler), NULL);
+
 	return TRUE;
 }
 
 static gboolean
 plugin_unload(PurplePlugin *plugin, GError **error)
 {
+	purple_signal_disconnect(purple_get_core(), "uri-handler", plugin,
+			PURPLE_CALLBACK(gg_uri_handler));
+
 	ggp_servconn_cleanup();
 	ggp_html_cleanup();
 	ggp_message_cleanup_global();
--- a/libpurple/protocols/irc/irc.h	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/protocols/irc/irc.h	Fri Nov 30 02:50:38 2018 +0000
@@ -34,7 +34,6 @@
 #include "xfer.h"
 #include "queuedoutputstream.h"
 #include "roomlist.h"
-#include "sslconn.h"
 
 #define IRC_TYPE_PROTOCOL             (irc_protocol_get_type())
 #define IRC_PROTOCOL(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), IRC_TYPE_PROTOCOL, IRCProtocol))
--- a/libpurple/protocols/jabber/jabber.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/protocols/jabber/jabber.c	Fri Nov 30 02:50:38 2018 +0000
@@ -3784,15 +3784,24 @@
 	return acct;
 }
 
-static gboolean xmpp_uri_handler(const char *proto, const char *user, GHashTable *params)
+static gboolean
+xmpp_uri_handler(const char *proto, const char *user, GHashTable *params,
+		gpointer user_data)
 {
-	char *acct_id = params ? g_hash_table_lookup(params, "account") : NULL;
+	PurpleProtocol *protocol = (PurpleProtocol *)user_data;
+	const gchar *acct_id = NULL;
 	PurpleAccount *acct;
 
+	g_return_val_if_fail(PURPLE_IS_PROTOCOL(protocol), FALSE);
+
 	if (g_ascii_strcasecmp(proto, "xmpp"))
 		return FALSE;
 
-	acct = find_acct(proto, acct_id);
+ 	if (params != NULL) {
+		acct_id = g_hash_table_lookup(params, "account");
+	}
+
+	acct = find_acct(protocol->id, acct_id);
 
 	if (!acct)
 		return FALSE;
@@ -3800,18 +3809,27 @@
 	/* xmpp:romeo@montague.net?message;subject=Test%20Message;body=Here%27s%20a%20test%20message */
 	/* params is NULL if the URI has no '?' (or anything after it) */
 	if (!params || g_hash_table_lookup_extended(params, "message", NULL, NULL)) {
-		char *body = g_hash_table_lookup(params, "body");
 		if (user && *user) {
 			PurpleIMConversation *im =
 					purple_im_conversation_new(acct, user);
+			const gchar *body = NULL;
+
 			purple_conversation_present(PURPLE_CONVERSATION(im));
+
+			if (params != NULL) {
+				body = g_hash_table_lookup(params, "body");
+			}
+
 			if (body && *body)
 				purple_conversation_send_confirm(PURPLE_CONVERSATION(im), body);
+			return TRUE;
 		}
 	} else if (g_hash_table_lookup_extended(params, "roster", NULL, NULL)) {
 		char *name = g_hash_table_lookup(params, "name");
-		if (user && *user)
+		if (user && *user) {
 			purple_blist_request_add_buddy(acct, user, NULL, name);
+			return TRUE;
+		}
 	} else if (g_hash_table_lookup_extended(params, "join", NULL, NULL)) {
 		PurpleConnection *gc = purple_account_get_connection(acct);
 		if (user && *user) {
@@ -4267,9 +4285,9 @@
 		return FALSE;
 
 	purple_signal_connect(purple_get_core(), "uri-handler", xmpp_protocol,
-		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
+		PURPLE_CALLBACK(xmpp_uri_handler), xmpp_protocol);
 	purple_signal_connect(purple_get_core(), "uri-handler", gtalk_protocol,
-		PURPLE_CALLBACK(xmpp_uri_handler), NULL);
+		PURPLE_CALLBACK(xmpp_uri_handler), gtalk_protocol);
 
 	jabber_init_protocol(xmpp_protocol);
 	jabber_init_protocol(gtalk_protocol);
@@ -4280,6 +4298,11 @@
 static gboolean
 plugin_unload(PurplePlugin *plugin, GError **error)
 {
+	purple_signal_disconnect(purple_get_core(), "uri-handler",
+			xmpp_protocol, PURPLE_CALLBACK(xmpp_uri_handler));
+	purple_signal_disconnect(purple_get_core(), "uri-handler",
+			gtalk_protocol, PURPLE_CALLBACK(xmpp_uri_handler));
+
 	jabber_uninit_protocol(gtalk_protocol);
 	jabber_uninit_protocol(xmpp_protocol);
 
--- a/libpurple/protocols/oscar/oscar.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/protocols/oscar/oscar.c	Fri Nov 30 02:50:38 2018 +0000
@@ -5529,13 +5529,21 @@
 
 gboolean oscar_uri_handler(const char *proto, const char *cmd, GHashTable *params)
 {
-	char *acct_id = g_hash_table_lookup(params, "account");
+	char *acct_id;
 	char prpl[11];
 	PurpleAccount *acct;
 
 	if (g_ascii_strcasecmp(proto, "aim") && g_ascii_strcasecmp(proto, "icq"))
 		return FALSE;
 
+	if (params == NULL) {
+		/* All Oscar URI actions require some parameters eventually */
+		purple_debug_warning("oscar",
+				"No required params for handling URI");
+		return FALSE;
+	}
+
+	acct_id = g_hash_table_lookup(params, "account");
 	g_snprintf(prpl, sizeof(prpl), "prpl-%s", proto);
 
 	acct = find_acct(proto, acct_id);
--- a/libpurple/protocols/simple/simple.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/protocols/simple/simple.c	Fri Nov 30 02:50:38 2018 +0000
@@ -29,6 +29,7 @@
 #include "accountopt.h"
 #include "buddylist.h"
 #include "conversation.h"
+#include "core.h"
 #include "debug.h"
 #include "notify.h"
 #include "protocol.h"
@@ -65,6 +66,57 @@
 	return "simple";
 }
 
+static gint
+simple_uri_handler_find_account(gconstpointer a, gconstpointer b)
+{
+	PurpleAccount *account = PURPLE_ACCOUNT(a);
+	const gchar *protocol_id;
+
+	protocol_id = purple_account_get_protocol_id(account);
+
+	if (purple_strequal(protocol_id, "prpl-simple") &&
+			purple_account_is_connected(account)) {
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+static gboolean
+simple_uri_handler(const gchar *scheme, const gchar *screenname,
+		GHashTable *params)
+{
+	GList *accounts;
+	GList *account_node;
+	PurpleIMConversation *im;
+
+	g_return_val_if_fail(screenname != NULL, FALSE);
+
+	if (!purple_strequal(scheme, "sip")) {
+		return FALSE;
+	}
+
+	if (screenname[0] == '\0') {
+		purple_debug_warning("simple",
+				"Invalid empty screenname in URI");
+		return FALSE;
+	}
+
+	/* Find online SIMPLE account */
+	accounts = purple_accounts_get_all();
+	account_node = g_list_find_custom(accounts, NULL,
+			simple_uri_handler_find_account);
+
+	if (account_node == NULL) {
+		return FALSE;
+	}
+
+	im = purple_im_conversation_new(account_node->data, screenname);
+	purple_conversation_present(PURPLE_CONVERSATION(im));
+
+	return TRUE;
+}
+
 static void simple_keep_alive(PurpleConnection *gc) {
 	struct simple_account_data *sip = purple_connection_get_protocol_data(gc);
 	if(sip->udp) { /* in case of UDP send a packet only with a 0 byte to
@@ -2192,12 +2244,18 @@
 	if (!my_protocol)
 		return FALSE;
 
+	purple_signal_connect(purple_get_core(), "uri-handler", plugin,
+			PURPLE_CALLBACK(simple_uri_handler), NULL);
+
 	return TRUE;
 }
 
 static gboolean
 plugin_unload(PurplePlugin *plugin, GError **error)
 {
+	purple_signal_disconnect(purple_get_core(), "uri-handler", plugin,
+			PURPLE_CALLBACK(simple_uri_handler));
+
 	if (!purple_protocols_remove(my_protocol, error))
 		return FALSE;
 
--- a/libpurple/purple-gio.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/purple-gio.c	Fri Nov 30 02:50:38 2018 +0000
@@ -24,7 +24,6 @@
 #include "internal.h"
 #include "proxy.h"
 #include "purple-gio.h"
-#include "tls-certificate.h"
 
 typedef struct {
 	GIOStream *stream;
@@ -127,9 +126,6 @@
 	g_socket_client_set_proxy_resolver(client, resolver);
 	g_object_unref(resolver);
 
-	/* Attach purple's tls certificate handler in case tls is used */
-	purple_tls_certificate_attach_to_socket_client(client);
-
 	return client;
 }
 
--- a/libpurple/purple.h.in	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/purple.h.in	Fri Nov 30 02:50:38 2018 +0000
@@ -92,7 +92,6 @@
 #include <theme.h>
 #include <theme-loader.h>
 #include <theme-manager.h>
-#include <tls-certificate.h>
 #include <upnp.h>
 #include <util.h>
 #include <version.h>
--- a/libpurple/request.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/request.c	Fri Nov 30 02:50:38 2018 +0000
@@ -125,11 +125,6 @@
 
 		struct
 		{
-			GTlsCertificate *cert;
-		} certificate;
-
-		struct
-		{
 			PurpleRequestDatasheet *sheet;
 		} datasheet;
 	} u;
@@ -1954,31 +1949,6 @@
 }
 
 PurpleRequestField *
-purple_request_field_certificate_new(const char *id, const char *text, GTlsCertificate *cert)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(id   != NULL, NULL);
-	g_return_val_if_fail(text != NULL, NULL);
-	g_return_val_if_fail(cert != NULL, NULL);
-
-	field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_CERTIFICATE);
-
-	field->u.certificate.cert = cert;
-
-	return field;
-}
-
-GTlsCertificate *
-purple_request_field_certificate_get_value(const PurpleRequestField *field)
-{
-	g_return_val_if_fail(field != NULL, NULL);
-	g_return_val_if_fail(field->type == PURPLE_REQUEST_FIELD_CERTIFICATE, NULL);
-
-	return field->u.certificate.cert;
-}
-
-PurpleRequestField *
 purple_request_field_datasheet_new(const char *id,
 	const gchar *text, PurpleRequestDatasheet *sheet)
 {
@@ -2472,29 +2442,6 @@
 	return NULL;
 }
 
-void *
-purple_request_certificate(void *handle, const char *title,
-                                  const char *primary, const char *secondary,
-                                  GTlsCertificate *cert,
-                                  const char *ok_text, GCallback ok_cb,
-                                  const char *cancel_text, GCallback cancel_cb,
-                                  void *user_data)
-{
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *group;
-	PurpleRequestField *field;
-
-	fields = purple_request_fields_new();
-	group = purple_request_field_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
-	field = purple_request_field_certificate_new("certificate", "Certificate", cert);
-	purple_request_field_group_add_field(group, field);
-
-	return purple_request_fields(handle, title, primary, secondary, fields,
-	                             ok_text, ok_cb, cancel_text, cancel_cb,
-	                             NULL, user_data);
-}
-
 gboolean
 purple_request_is_valid_ui_handle(void *ui_handle, PurpleRequestType *type)
 {
--- a/libpurple/request.h	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/request.h	Fri Nov 30 02:50:38 2018 +0000
@@ -29,7 +29,6 @@
  */
 
 #include <stdlib.h>
-#include <gio/gio.h>
 #include <glib-object.h>
 #include <glib.h>
 
@@ -112,7 +111,6 @@
 	PURPLE_REQUEST_FIELD_LABEL,
 	PURPLE_REQUEST_FIELD_IMAGE,
 	PURPLE_REQUEST_FIELD_ACCOUNT,
-	PURPLE_REQUEST_FIELD_CERTIFICATE,
 	PURPLE_REQUEST_FIELD_DATASHEET
 
 } PurpleRequestFieldType;
@@ -1776,35 +1774,6 @@
 		const PurpleRequestField *field);
 
 /**************************************************************************/
-/* Certificate Field API                                                  */
-/**************************************************************************/
-
-/**
- * purple_request_field_certificate_new:
- * @id:   The field ID.
- * @text: The label of the field.
- * @cert: The certificate of the field.
- *
- * Creates a certificate field.
- *
- * Returns: The new field.
- */
-PurpleRequestField *purple_request_field_certificate_new(const char *id,
-														 const char *text,
-														 GTlsCertificate *cert);
-
-/**
- * purple_request_field_certificate_get_value:
- * @field: The field.
- *
- * Returns the certificate in a certificate field.
- *
- * Returns: The certificate.
- */
-GTlsCertificate *purple_request_field_certificate_get_value(
-		const PurpleRequestField *field);
-
-/**************************************************************************/
 /* Datasheet Field API                                                    */
 /**************************************************************************/
 
@@ -2240,39 +2209,6 @@
 	GCallback ok_cb, GCallback cancel_cb,
 	PurpleRequestCommonParameters *cpar, void *user_data);
 
-/**
- * purple_request_certificate:
- * @handle:        The plugin or connection handle.  For some things this
- *                 is <emphasis>extremely</emphasis> important.  See the comments on
- *                 purple_request_input().
- * @title:         The title of the message, or %NULL if it should have
- *                 no title.
- * @primary:       The main point of the message, or %NULL if you're
- *                 feeling enigmatic.
- * @secondary:     Secondary information, or %NULL if there is none.
- * @cert:          The #GTlsCertificate associated with this request.
- * @ok_text:       The text for the <literal>OK</literal> button, which may not
- *                 be %NULL.
- * @ok_cb:         The callback for the <literal>OK</literal> button, which may
- *                 not be %NULL.
- * @cancel_text:   The text for the <literal>Cancel</literal> button, which may
- *                 not be %NULL.
- * @cancel_cb:     The callback for the <literal>Cancel</literal> button, which
- *                 may be %NULL.
- * @user_data:     The data to pass to the callback.
- *
- * Prompts the user for action over a certificate.
- *
- * This is often represented as a dialog with a button for each action.
- *
- * Returns: A UI-specific handle.
- */
-void *purple_request_certificate(void *handle, const char *title,
-	const char *primary, const char *secondary, GTlsCertificate *cert,
-	const char *ok_text, GCallback ok_cb,
-	const char *cancel_text, GCallback cancel_cb,
-	void *user_data);
-
 /**************************************************************************/
 /* UI Registration Functions                                              */
 /**************************************************************************/
--- a/libpurple/sslconn.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/sslconn.c	Fri Nov 30 02:50:38 2018 +0000
@@ -26,7 +26,6 @@
 #include "plugins.h"
 #include "request.h"
 #include "sslconn.h"
-#include "tls-certificate.h"
 
 #define CONNECTION_CLOSE_TIMEOUT 15
 
@@ -104,8 +103,6 @@
 	gsc->conn = G_TLS_CONNECTION(tls_conn);
 	gsc->cancellable = g_cancellable_new();
 
-	purple_tls_certificate_attach_to_tls_connection(gsc->conn);
-
 	g_tls_connection_handshake_async(gsc->conn, G_PRIORITY_DEFAULT,
 			gsc->cancellable, tls_handshake_cb, gsc);
 
--- a/libpurple/tls-certificate-info.c	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,815 +0,0 @@
-/*
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "tls-certificate-info.h"
-#include "debug.h"
-#include "util.h"
-
-#define DER_TYPE_CLASS(type)		(type & 0xc0)
-
-#define DER_TYPE_CLASS_UNIVERSAL	0x00
-#define DER_TYPE_CLASS_APPLICATION	0x40
-#define DER_TYPE_CLASS_CONTEXT_SPECIFIC	0x80
-#define DER_TYPE_CLASS_PRIVATE		0xc0
-
-#define DER_TYPE_TAG(type) (type & 0x1f)
-
-#define DER_TYPE_IS_CONSTRUCTED(type) ((type & 0x20) ? TRUE : FALSE)
-
-#define DER_TYPE_TAG_IS_LONG_FORM(type) (DER_TYPE_TAG(type) == 0x1f)
-
-#define DER_LENGTH_IS_LONG_FORM(byte) ((byte & 0x80) ? TRUE : FALSE)
-#define DER_LENGTH_LONG_FORM_SIZE(byte) (byte & 0x7f)
-
-typedef struct {
-	guint8 type_class;
-	gboolean constructed;
-	guint type;
-	GBytes *content;
-	GSList *children;
-} DerNodeData;
-
-static void der_node_data_children_list_free(GSList *children);
-
-static void
-der_node_data_free(DerNodeData *node_data)
-{
-	g_return_if_fail(node_data != NULL);
-
-	g_clear_pointer(&node_data->content, g_bytes_unref);
-	g_clear_pointer(&node_data->children,
-			der_node_data_children_list_free);
-
-	g_free(node_data);
-}
-
-static void
-der_node_data_children_list_free(GSList *children)
-{
-	g_return_if_fail(children != NULL);
-
-	g_slist_free_full(children, (GDestroyNotify)der_node_data_free);
-}
-
-/* Parses DER encoded data into a GSList of DerNodeData instances */
-static GSList *
-der_parse(GBytes *data_bytes)
-{
-	const guint8 *data;
-	gsize size = 0;
-	gsize offset = 0;
-	GSList *nodes = NULL;
-	DerNodeData *node = NULL;
-
-	data = g_bytes_get_data(data_bytes, &size);
-
-	/* Parse data */
-	while (offset < size) {
-		guint8 byte;
-		gsize length;
-
-		/* Parse type */
-
-		byte = *(data + offset++);
-		node = g_new0(DerNodeData, 1);
-		node->type_class = DER_TYPE_CLASS(byte);
-		node->constructed = DER_TYPE_IS_CONSTRUCTED(byte);
-
-		if (DER_TYPE_TAG_IS_LONG_FORM(byte)) {
-			/* Long-form type encoding */
-			/* TODO: Handle long-form encoding.
-			 * Maiku: The certificates I tested didn't do this.
-			 */
-			g_return_val_if_reached(NULL);
-		} else {
-			/* Short-form type encoding */
-			node->type = DER_TYPE_TAG(byte);
-		}
-
-		/* Parse content length */
-
-		if (offset >= size) {
-			purple_debug_error("tls-certificate",
-					"Not enough remaining data when "
-					"parsing DER chunk length byte: "
-					"read (%" G_GSIZE_FORMAT ") "
-					"available: ""(%" G_GSIZE_FORMAT ")",
-					offset, size);
-			break;
-		}
-
-		byte = *(data + offset++);
-
-		if (DER_LENGTH_IS_LONG_FORM(byte)) {
-			/* Long-form length encoding */
-			guint num_len_bytes = DER_LENGTH_LONG_FORM_SIZE(byte);
-			guint i;
-
-			/* Guard against overflowing the integer */
-			if (num_len_bytes > sizeof(guint)) {
-				purple_debug_error("tls-certificate",
-						"Number of long-form length "
-						"bytes greater than guint "
-						"size: %u > %" G_GSIZE_FORMAT,
-						num_len_bytes, sizeof(guint));
-				break;
-			}
-
-			/* Guard against reading past the end of the buffer */
-			if (offset + num_len_bytes > size) {
-				purple_debug_error("tls-certificate",
-						"Not enough remaining data "
-						"when parsing DER chunk "
-						"long-form length bytes: "
-						"read (%" G_GSIZE_FORMAT ") "
-						"available: ""(%"
-						G_GSIZE_FORMAT ")",
-						offset, size);
-				break;
-			}
-
-			length = 0;
-
-			for (i = 0; i < num_len_bytes; ++i) {
-				length = length << 8;
-				length |= *(data + offset++);
-			}
-		} else {
-			/* Short-form length encoding */
-			length = byte;
-		}
-		
-		/* Parse content */
-
-		if (offset + length > size) {
-			purple_debug_error("tls-certificate",
-					"Not enough remaining data when "
-					"parsing DER chunk content: "
-					"content size (%" G_GSIZE_FORMAT ") "
-					"available: ""(%" G_GSIZE_FORMAT ")",
-					length, size - offset);
-			break;
-		}
-
-		node->content = g_bytes_new_from_bytes(data_bytes,
-				offset, length);
-		offset += length;
-
-		/* Maybe recurse */
-		if (node->constructed) {
-			node->children = der_parse(node->content);
-
-			if (node->children == NULL) {
-				/* No children on a constructed type
-				 * should an error. If this happens, it
-				 * outputs debug info inside der_parse().
-				 */
-				break;
-			}
-		}
-
-		nodes = g_slist_append(nodes, node);
-		node = NULL;
-	}
-
-	if (node != NULL) {
-		/* There was an error. Free parsing data. */
-		der_node_data_free(node);
-		g_clear_pointer(&nodes, der_node_data_children_list_free);
-		/* FIXME: Report error to calling function ala GError? */
-	}
-
-	return nodes;
-}
-
-static gchar *
-der_parse_string(DerNodeData *node)
-{
-	const gchar *str;
-	gsize length = 0;
-
-	g_return_val_if_fail(node != NULL, NULL);
-	g_return_val_if_fail(node->content != NULL, NULL);
-
-	str = g_bytes_get_data(node->content, &length);
-	return g_strndup(str, length);
-}
-
-typedef struct {
-	gchar *oid;
-	gchar *value;
-} DerOIDValue;
-
-static DerOIDValue *
-der_oid_value_copy(DerOIDValue *data)
-{
-	DerOIDValue *ret;
-
-	g_return_val_if_fail(data != NULL, NULL);
-
-	ret = g_new0(DerOIDValue, 1);
-	ret->oid = g_strdup(data->oid);
-	ret->value = g_strdup(data->value);
-	return ret;
-}
-
-static void
-der_oid_value_free(DerOIDValue *data)
-{
-	g_return_if_fail(data != NULL);
-
-	g_clear_pointer(&data->oid, g_free);
-	g_clear_pointer(&data->value, g_free);
-
-	g_free(data);
-}
-
-static void
-der_oid_value_slist_free(GSList *list)
-{
-	g_return_if_fail(list != NULL);
-
-	g_slist_free_full(list, (GDestroyNotify)der_oid_value_free);
-}
-
-static const gchar *
-der_oid_value_slist_get_value_by_oid(GSList *list, const gchar *oid)
-{
-	for (; list != NULL; list = g_slist_next(list)) {
-		DerOIDValue *value = list->data;
-
-		if (!strcmp(oid, value->oid)) {
-			return value->value;
-		}
-	}
-
-	return NULL;
-}
-
-static gchar *
-der_parse_oid(DerNodeData *node)
-{
-	const gchar *oid_data;
-	gsize length = 0;
-	gsize offset = 0;
-	guint8 byte;
-	GString *ret;
-
-	g_return_val_if_fail(node != NULL, NULL);
-	g_return_val_if_fail(node->content != NULL, NULL);
-
-	oid_data = g_bytes_get_data(node->content, &length);
-	/* Most OIDs used for certificates aren't larger than 9 bytes */
-	ret = g_string_sized_new(9);
-
-	/* First byte is encoded as num1 * 40 + num2 */
-	if (length > 0) {
-		byte = *(oid_data + offset++);
-		g_string_append_printf(ret, "%u.%u", byte / 40, byte % 40);
-	}
-
-	/* Subsequent numbers are in base 128 format (the most
-	 * significant bit being set adds another 7 bits to the number)
-	 */
-	while (offset < length) {
-		guint value = 0;
-
-		do {
-			byte = *(oid_data + offset++);
-			value = (value << 7) + (byte & 0x7f);
-		} while (byte & 0x80 && offset < length);
-
-		g_string_append_printf(ret, ".%u", value);
-	}
-
-	return g_string_free(ret, FALSE);
-}
-
-/* Parses X.509 Issuer and Subject name structures
- * into a GSList of DerOIDValue.
- */
-static GSList *
-der_parse_name(DerNodeData *name_node)
-{
-	GSList *list;
-	GSList *ret = NULL;
-	DerOIDValue *value = NULL;
-
-	g_return_val_if_fail(name_node != NULL, NULL);
-
-	/* Iterate over items in the name sequence */
-	list = name_node->children;
-
-	while (list != NULL) {
-		DerNodeData *child_node;
-		GSList *child_list;
-
-		value = g_new(DerOIDValue, 1);
-
-		/* Each item in the name sequence is a set containing
-		 * a sequence of an ObjectID and a String-like value
-		 */
-
-		/* Get the DerNode containing set data */
-		if ((child_node = g_slist_nth_data(list, 0)) == NULL) {
-			break;
-		}
-
-		/* Get the DerNode containing its sequence data */
-		if (child_node == NULL ||
-				(child_node = g_slist_nth_data(
-				child_node->children, 0)) == NULL) {
-			break;
-		}
-
-		/* Get the GSList item containing the ObjectID DerNode  */
-		if ((child_list = child_node->children) == NULL) {
-			break;
-		}
-
-		/* Get the DerNode containing the ObjectID */
-		if ((child_node = child_list->data) == NULL) {
-			break;
-		}
-
-		/* Parse ObjectID */
-		value->oid = der_parse_oid(child_node);
-
-		/* Get the GSList item containing the String-like value */
-		if ((child_list = g_slist_next(child_list)) == NULL) {
-			break;
-		}
-
-		/* Get the DerNode containing the String-like value */
-		if ((child_node = child_list->data) == NULL) {
-			break;
-		}
-
-		/* Parse String-like value */
-		value->value = der_parse_string(child_node);
-
-		ret = g_slist_prepend(ret, value);
-		list = g_slist_next(list);
-		value = NULL;
-	}
-
-	if (value != NULL) {
-		der_oid_value_free(value);
-		der_oid_value_slist_free(ret);
-	}
-
-	return g_slist_reverse(ret);
-}
-
-static GDateTime *
-der_parse_time(DerNodeData *node)
-{
-	gchar *time;
-	gchar *c;
-	gint time_parts[7];
-	gint time_part_idx = 0;
-	int length;
-
-	g_return_val_if_fail(node != NULL, NULL);
-	g_return_val_if_fail(node->content != NULL, NULL);
-
-	memset(time_parts, 0, sizeof(time_parts));
-
-	time = der_parse_string(node);
-
-	/* For the purposes of X.509
-	 * UTCTime format is "YYMMDDhhmmssZ" (YY >= 50 ? 19YY : 20YY) and
-	 * GeneralizedTime format is "YYYYMMDDhhmmssZ"
-	 * According to RFC2459, they both are GMT, which is weird
-	 * considering one is named UTC, but for the purposes of display,
-	 * for which this is used, it shouldn't matter.
-	 */
-
-	length = strlen(time);
-	if (length == 13) {
-		/* UTCTime: Skip the first part as it's calculated later */
-		time_part_idx = 1;
-	} else if (length == 15) {
-		/* Generalized Time */
-		/* TODO: Handle generalized time
-		 * Maiku: None of the certificates I tested used this
-		 */
-		g_free(time);
-		g_return_val_if_reached(NULL);
-	} else {
-		purple_debug_error("tls-certificate",
-				"Unrecognized time format (length: %i)",
-				length);
-		g_free(time);
-		return NULL;
-	}
-
-	c = time;
-
-	while (c - time < length) {
-		if (*c == 'Z') {
-			break;
-		}
-
-		if (!g_ascii_isdigit(*c) || !g_ascii_isdigit(*(c + 1))) {
-			purple_debug_error("tls-certificate",
-					"Error parsing time. next characters "
-					"aren't both digits: '%c%c'",
-					*c, *(c + 1));
-			break;
-		}
-
-		time_parts[time_part_idx++] =
-				g_ascii_digit_value(*c) * 10 +
-				g_ascii_digit_value(*(c + 1));
-		c += 2;
-	}
-
-	if (length == 13) {
-		if (time_parts[1] >= 50) {
-			time_parts[0] = 19;
-		} else {
-			time_parts[0] = 20;
-		}
-	}
-
-	return g_date_time_new_utc(
-			time_parts[0] * 100 + time_parts[1],	/* year */
-			time_parts[2],				/* month */
-			time_parts[3],				/* day */
-			time_parts[4],				/* hour */	
-			time_parts[5],				/* minute */
-			time_parts[6]);				/* seconds */
-}
-
-/* This structure contains the data which is in an X.509 certificate.
- * Only the values actually parsed/used are here. The remaining commented
- * out values are informative placeholders for the remaining data that
- * could be in a standard certificate.
- */
-struct _PurpleTlsCertificateInfo {
-	GTlsCertificate *cert;
-
-	/* version (Optional, defaults to version 1 (version = value + 1)) */
-	/* serialNumber */
-	/* signature */
-	GSList *issuer;
-	GDateTime *notBefore;
-	GDateTime *notAfter;
-	GSList *subject;
-	/* subjectPublicKeyInfo */
-	/* issuerUniqueIdentifier (Optional, requires version 2 or 3) */
-	/* subjectUniqueIdentifier (Optional, requires version 2 or 3) */
-	/* extensions (Optional, requires version 3) */
-};
-
-/* TODO: Make better API for this? */
-PurpleTlsCertificateInfo *
-purple_tls_certificate_get_info(GTlsCertificate *certificate)
-{
-	GByteArray *der_array = NULL;
-	GBytes *root;
-	GSList *nodes;
-	DerNodeData *node;
-	DerNodeData *cert_node;
-	DerNodeData *valid_node;
-	PurpleTlsCertificateInfo *info;
-
-	g_return_val_if_fail(G_IS_TLS_CERTIFICATE(certificate), NULL);
-
-	/* Get raw bytes from DER formatted certificate */
-	g_object_get(certificate, "certificate", &der_array, NULL);
-
-	/* Parse raw bytes into DerNode tree */
-	root = g_byte_array_free_to_bytes(der_array);
-	nodes = der_parse(root);
-	g_bytes_unref(root);
-
-	if (nodes == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error parsing certificate");
-		return NULL;
-	}
-
-	/* Set up PurpleTlsCertificateInfo struct with initial data */
-	info = g_new0(PurpleTlsCertificateInfo, 1);
-	info->cert = g_object_ref(certificate);
-
-	/* Get certificate root sequence GSList item */
-	node = g_slist_nth_data(nodes, 0);
-	if (node == NULL || node->children == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error parsing certificate root node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	/* Get certificate sequence GSList DerNode */
-	cert_node = g_slist_nth_data(node->children, 0);
-	if (cert_node == NULL || cert_node->children == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error to parsing certificate node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	/* Check for optional certificate version */
-
-	node = g_slist_nth_data(cert_node->children, 0);
-	if (node == NULL || node->children == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error to parsing certificate version node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	if (node->type_class != DER_TYPE_CLASS_CONTEXT_SPECIFIC) {
-		/* Include optional version so indices work right */
-		/* TODO: Actually set default version value? */
-		cert_node->children =
-				g_slist_prepend(cert_node->children, NULL);
-	}
-
-	/* Get certificate issuer */
-
-	node = g_slist_nth_data(cert_node->children, 3);
-	if (node == NULL || node->children == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error to parsing certificate issuer node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	info->issuer = der_parse_name(node);
-
-	/* Get certificate validity */
-
-	valid_node = g_slist_nth_data(cert_node->children, 4);
-	if (valid_node == NULL || valid_node->children == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error to parsing certificate validity node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	/* Get certificate validity (notBefore) */
-	node = g_slist_nth_data(valid_node->children, 0);
-	if (node == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error to parsing certificate valid "
-				"notBefore node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	info->notBefore = der_parse_time(node);
-
-	/* Get certificate validity (notAfter) */
-	node = g_slist_nth_data(valid_node->children, 1);
-	if (node == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error to parsing certificate valid "
-				"notAfter node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	info->notAfter = der_parse_time(node);
-
-	/* Get certificate subject */
-
-	node = g_slist_nth_data(cert_node->children, 5);
-	if (node == NULL || node->children == NULL) {
-		purple_debug_warning("tls-certificate",
-				"Error to parsing certificate subject node");
-		purple_tls_certificate_info_free(info);
-		return NULL;
-	}
-
-	info->subject = der_parse_name(node);
-
-	/* Clean up */
-	der_node_data_children_list_free(nodes);
-
-	return info;
-}
-
-static PurpleTlsCertificateInfo *
-purple_tls_certificate_info_copy(PurpleTlsCertificateInfo *info)
-{
-	PurpleTlsCertificateInfo *ret;
-
-	g_return_val_if_fail(info != NULL, NULL);
-
-	ret = g_new0(PurpleTlsCertificateInfo, 1);
-	ret->issuer = g_slist_copy_deep(info->issuer,
-			(GCopyFunc)der_oid_value_copy, NULL);
-	ret->notBefore = g_date_time_ref(info->notBefore);
-	ret->notAfter = g_date_time_ref(info->notAfter);
-	ret->subject = g_slist_copy_deep(info->subject,
-			(GCopyFunc)der_oid_value_copy, NULL);
-
-	return ret;
-}
-
-void
-purple_tls_certificate_info_free(PurpleTlsCertificateInfo *info)
-{
-	g_return_if_fail(info != NULL);
-
-	g_clear_object(&info->cert);
-
-	g_clear_pointer(&info->issuer, der_oid_value_slist_free);
-	g_clear_pointer(&info->notBefore, g_date_time_unref);
-	g_clear_pointer(&info->notAfter, g_date_time_unref);
-	g_clear_pointer(&info->subject, der_oid_value_slist_free);
-
-	g_free(info);
-}
-
-G_DEFINE_BOXED_TYPE(PurpleTlsCertificateInfo, purple_tls_certificate_info,
-		purple_tls_certificate_info_copy,
-		purple_tls_certificate_info_free);
-
-/* Looks up the relative distinguished name (RDN) from an ObjectID */
-static const gchar *
-lookup_rdn_name_by_oid(const gchar *oid)
-{
-	static GHashTable *ht = NULL;
-
-	if (G_UNLIKELY(ht == NULL)) {
-		ht = g_hash_table_new_full(g_str_hash, g_str_equal,
-				NULL, NULL);
-
-		/* commonName */
-		g_hash_table_insert(ht, "2.5.4.3", "CN");
-		/* countryName */
-		g_hash_table_insert(ht, "2.5.4.6", "C");
-		/* localityName */
-		g_hash_table_insert(ht, "2.5.4.7", "L");
-		/* stateOrProvinceName */
-		g_hash_table_insert(ht, "2.5.4.8", "ST");
-		/* organizationName */
-		g_hash_table_insert(ht, "2.5.4.10", "O");
-		/* organizationalUnitName */
-		g_hash_table_insert(ht, "2.5.4.11", "OU");
-	}
-
-	return g_hash_table_lookup(ht, oid);
-}
-
-/* Makes a distinguished name (DN) from
- * a list of relative distinguished names (RDN).
- * Order matters.
- */
-static gchar *
-make_dn_from_oid_value_slist(GSList *list)
-{
-	GString *str = g_string_new(NULL);
-
-	for (; list != NULL; list = g_slist_next(list)) {
-		DerOIDValue *value = list->data;
-		const gchar *name;
-		gchar *new_value;
-
-		if (value == NULL) {
-			purple_debug_error("tls-certificate",
-					"DerOIDValue data missing from GSList");
-			continue;
-		}
-
-		name = lookup_rdn_name_by_oid(value->oid);
-		/* Escape commas in value as that's the DN separator */
-		new_value = purple_strreplace(value->value, ",", "\\,");
-		g_string_append_printf(str, "%s=%s,", name, new_value);
-		g_free(new_value);
-	}
-
-	/* Remove trailing comma */
-	g_string_truncate(str, str->len - 1);
-
-	return g_string_free(str, FALSE);
-}
-
-static gchar *
-purple_tls_certificate_info_get_issuer_dn(PurpleTlsCertificateInfo *info)
-{
-	g_return_val_if_fail(info != NULL, NULL);
-	g_return_val_if_fail(info->issuer != NULL, NULL);
-
-	return make_dn_from_oid_value_slist(info->issuer);
-}
-
-gchar *
-purple_tls_certificate_info_get_display_string(PurpleTlsCertificateInfo *info)
-{
-	gchar *subject_name;
-	gchar *issuer_name = NULL;
-	GByteArray *sha1_bytes;
-	gchar *sha1_str = NULL;
-	gchar *activation_time;
-	gchar *expiration_time;
-	gchar *ret;
-
-	g_return_val_if_fail(info != NULL, NULL);
-
-	/* Getting the commonName of a CA supposedly doesn't work, but we
-	 * shouldn't be dealing with those here anyway.
-	 */
-	subject_name = purple_tls_certificate_info_get_subject_name(info);
-
-	issuer_name = purple_tls_certificate_info_get_issuer_dn(info);
-
-	sha1_bytes = purple_tls_certificate_get_fingerprint_sha1(info->cert);
-	if (sha1_bytes != NULL) {
-		sha1_str = purple_base16_encode_chunked(sha1_bytes->data,
-				sha1_bytes->len);
-		g_byte_array_unref(sha1_bytes);
-	}
-
-	activation_time = g_date_time_format(info->notBefore, "%c");
-	expiration_time = g_date_time_format(info->notAfter, "%c");
-
-	ret = g_strdup_printf(
-			_("Common name: %s\n\n"
-			  "Issued by: %s\n\n"
-			  "Fingerprint (SHA1): %s\n\n"
-			  "Activation date: %s\n"
-			  "Expiriation date: %s\n"),
-			subject_name,
-			issuer_name,
-			sha1_str,
-			activation_time,
-			expiration_time);
-
-	g_free(subject_name);
-	g_free(issuer_name);
-	g_free(sha1_str);
-	g_free(activation_time);
-	g_free(expiration_time);
-
-	return ret;
-}
-
-/* TODO: Make better API for this? */
-gchar *
-purple_tls_certificate_info_get_subject_name(PurpleTlsCertificateInfo *info)
-{
-	g_return_val_if_fail(info != NULL, NULL);
-	g_return_val_if_fail(info->subject != NULL, NULL);
-
-	/* commonName component of the subject */
-	return g_strdup(der_oid_value_slist_get_value_by_oid(info->subject,
-			"2.5.4.3"));
-}
-
-/* TODO: Make better API for this? */
-GByteArray *
-purple_tls_certificate_get_fingerprint_sha1(GTlsCertificate *certificate)
-{
-	GChecksum *hash;
-	GByteArray *der = NULL;
-	guint8 *data = NULL;
-	gsize buf_size = 0;
-
-	g_return_val_if_fail(G_IS_TLS_CERTIFICATE(certificate), NULL);
-
-	g_object_get(certificate, "certificate", &der, NULL);
-
-	g_return_val_if_fail(der != NULL, NULL);
-
-	hash = g_checksum_new(G_CHECKSUM_SHA1);
-
-	buf_size = g_checksum_type_get_length(G_CHECKSUM_SHA1);
-	data = g_malloc(buf_size);
-
-	g_checksum_update(hash, der->data, der->len);
-	g_byte_array_unref(der);
-
-	g_checksum_get_digest(hash, data, &buf_size);
-	g_checksum_free(hash);
-
-	return g_byte_array_new_take(data, buf_size);
-}
-
--- a/libpurple/tls-certificate-info.h	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef _PURPLE_TLS_CERTIFICATE_INFO_H
-#define _PURPLE_TLS_CERTIFICATE_INFO_H
-/**
- * SECTION:tls-certificate-info
- * @section_id: libpurple-tls-certificate-info
- * @short_description: TLS certificate information parsing
- * @title: TLS Certificate Info API
- *
- * The TLS certificate info API provides information parsing functions
- * for #GTlsCertificate's. This information can then be presented to the
- * user, usually to help them decide whether or not to trust a given
- * certificate.
- */
-
-#include <gio/gio.h>
-
-/**
- * PurpleTlsCertificateInfo
- *
- * An opaque structure to contain parsed certificate info, which
- * can subsequently be accessed by purple_tls_certificate_info_*
- * functions.
- */
-typedef struct _PurpleTlsCertificateInfo PurpleTlsCertificateInfo;
-
-#define PURPLE_TYPE_TLS_CERTIFICATE_INFO \
-		(purple_tls_certificate_info_get_type())
-
-/**
- * purple_tls_certificate_info_get_type:
- *
- * Returns: The #GType for the #PurpleTlsCertificateInfo boxed structure.
- */
-GType purple_tls_certificate_info_get_type(void);
-
-/**
- * purple_tls_certificate_get_info:
- * @certificate: Certificate from which to parse the info
- *
- * Returns a #PurpleTlsCertificateInfo containing parsed information
- * of the certificate.
- *
- * Returns: #PurpleTlsCertificateInfo parsed from the certificate
- */
-PurpleTlsCertificateInfo *
-purple_tls_certificate_get_info(GTlsCertificate *certificate);
-
-/**
- * purple_tls_certificate_info_free:
- * @info: #PurpleTlsCertificateInfo object to free
- *
- * Frees @info.
- */
-void
-purple_tls_certificate_info_free(PurpleTlsCertificateInfo *info);
-
-/**
- * purple_tls_certificate_info_get_display_string:
- * @info: #PurpleTlsCertificateInfo from which to generate a display string
- *
- * Generates a user readable string to display information from @info
- *
- * Returns: A user readable string suitable to display to the user
- */
-gchar *
-purple_tls_certificate_info_get_display_string(PurpleTlsCertificateInfo *info);
-
-/**
- * purple_tls_certificate_get_subject_name:
- * @certificate: Certificate from which to get the subject name
- *
- * Returns the common subject name of the cert
- *
- * Returns: The subject name of the cert
- */
-gchar *
-purple_tls_certificate_info_get_subject_name(PurpleTlsCertificateInfo *info);
-
-/**
- * purple_tls_certificate_get_fingerprint_sha1:
- * @certificate: Certificate from which to get the SHA1 fingerprint
- *
- * Returns the SHA1 fingerprint of the cert
- *
- * Returns: (transfer full): The SHA1 fingerprint of the cert
- */
-GByteArray *
-purple_tls_certificate_get_fingerprint_sha1(GTlsCertificate *certificate);
-
-G_END_DECLS
-
-#endif /* _PURPLE_TLS_CERTIFICATE_INFO_H */
--- a/libpurple/tls-certificate.c	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,390 +0,0 @@
-/*
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include "internal.h"
-#include "tls-certificate.h"
-#include "debug.h"
-#include "util.h"
-
-/* Makes a filename path for a certificate. If id is NULL,
- * just return the directory
- */
-static gchar *
-make_certificate_path(const gchar *id)
-{
-	return g_build_filename(purple_data_dir(),
-				"certificates", "tls",
-				id != NULL ? purple_escape_filename(id) : NULL,
-				NULL);
-}
-
-/* Creates the certificate directory if it doesn't exist,
- * returns TRUE if it's successful or it already exists,
- * returns FALSE if there was an error.
- */
-static gboolean
-ensure_certificate_dir(GError **error)
-{
-	gchar *dir = make_certificate_path(NULL);
-	gboolean ret = TRUE;
-
-	if (purple_build_dir(dir, 0700) != 0) {
-		g_set_error_literal(error, G_FILE_ERROR,
-				g_file_error_from_errno(errno),
-				g_strerror(errno));
-		ret = FALSE;
-	}
-
-	g_free(dir);
-	return ret;
-}
-
-GList *
-purple_tls_certificate_list_ids()
-{
-	gchar *dir_path;
-	GDir *dir;
-	const gchar *entry;
-	GList *idlist = NULL;
-	GError *error = NULL;
-
-	/* Ensure certificate directory exists */
-
-	if (!ensure_certificate_dir(&error)) {
-		purple_debug_error("tls-certificate",
-				"Error creating certificate directory: %s",
-				error->message);
-		g_clear_error(&error);
-		return NULL;
-	}
-
-	/* Open certificate directory */
-
-	dir_path = make_certificate_path(NULL);
-	dir = g_dir_open(dir_path, 0, &error);
-
-	if (dir == NULL) {
-		purple_debug_error("tls-certificate",
-				"Error opening certificate directory (%s): %s",
-				dir_path, error->message);
-		g_free(dir_path);
-		g_clear_error(&error);
-		return NULL;
-	}
-
-	g_free(dir_path);
-
-	/* Traverse the directory listing and create an idlist */
-
-	while ((entry = g_dir_read_name(dir)) != NULL) {
-		/* Unescape the filename
-		 * (GLib owns original string)
-		 */
-		const char *unescaped = purple_unescape_filename(entry);
-
-		/* Copy the entry name into our list
-		 * (Purple own the escaped string)
-		 */
-		idlist = g_list_prepend(idlist, g_strdup(unescaped));
-	}
-
-	g_dir_close(dir);
-
-	return idlist;
-}
-
-void
-purple_tls_certificate_free_ids(GList *ids)
-{
-	g_list_free_full(ids, g_free);
-}
-
-GTlsCertificate *
-purple_tls_certificate_new_from_id(const gchar *id, GError **error)
-{
-	GTlsCertificate *cert;
-	gchar *path;
-
-	g_return_val_if_fail(id != NULL && id[0] != '\0', NULL);
-
-	/* Load certificate from file if it exists */
-
-	path = make_certificate_path(id);
-	cert = g_tls_certificate_new_from_file(path, error);
-	g_free(path);
-
-	return cert;
-}
-
-gboolean
-purple_tls_certificate_trust(const gchar *id, GTlsCertificate *certificate,
-		GError **error)
-{
-	gchar *path;
-	gchar *pem = NULL;
-	gboolean ret;
-
-	g_return_val_if_fail(id != NULL && id[0] != '\0', FALSE);
-	g_return_val_if_fail(G_IS_TLS_CERTIFICATE(certificate), FALSE);
-
-	/* Ensure certificate directory exists */
-
-	if (!ensure_certificate_dir(error)) {
-		return FALSE;
-	}
-
-	/* Get the text representation of the certificate */
-
-	g_object_get(certificate, "certificate-pem", &pem, NULL);
-	g_return_val_if_fail(pem != NULL, FALSE);
-
-	/* Save certificate text to a fail */
-
-	path = make_certificate_path(id);
-	ret = g_file_set_contents(path, pem, -1, error);
-	g_free(path);
-	g_free(pem);
-
-	return ret;
-}
-
-gboolean
-purple_tls_certificate_distrust(const gchar *id, GError **error)
-{
-	gchar *path;
-	gboolean ret = TRUE;
-
-	g_return_val_if_fail(id != NULL && id[0] != '\0', FALSE);
-
-	/* Delete certificate file if it exists */
-
-	path = make_certificate_path(id);
-
-	if (g_unlink(path) != 0) {
-		g_set_error_literal(error, G_FILE_ERROR,
-				g_file_error_from_errno(errno),
-				g_strerror(errno));
-		ret = FALSE;
-	}
-
-	g_free(path);
-
-	return ret;
-}
-
-/* Converts GTlsCertificateFlags to a translated string representation
- * of the first set error flag in the order checked
- */
-static const gchar *
-tls_certificate_flags_to_reason(GTlsCertificateFlags flags)
-{
-	if (flags & G_TLS_CERTIFICATE_UNKNOWN_CA) {
-		return _("The certificate is not trusted because no "
-				"certificate that can verify it is "
-				"currently trusted.");
-	} else if (flags & G_TLS_CERTIFICATE_BAD_IDENTITY) {
-		/* Translators: "domain" refers to a DNS domain
-		 * (e.g. talk.google.com)
-		 */
-		return _("The certificate presented is not issued to "
-				"this domain.");
-	} else if (flags & G_TLS_CERTIFICATE_NOT_ACTIVATED) {
-		return _("The certificate is not valid yet.  Check that your "
-				"computer's date and time are accurate.");
-	} else if (flags & G_TLS_CERTIFICATE_EXPIRED) {
-		return _("The certificate has expired and should not be "
-				"considered valid.  Check that your "
-				"computer's date and time are accurate.");
-	} else if (flags & G_TLS_CERTIFICATE_REVOKED) {
-		return _("The certificate has been revoked.");
-	} else if (flags & G_TLS_CERTIFICATE_INSECURE) {
-		return _("The certificate's algorithm is considered insecure.");
-	} else {
-		/* Also catches G_TLS_CERTIFICATE_GENERIC_ERROR here */
-		return _("An unknown certificate error occurred.");
-	}
-}
-
-/* Holds data for requesting the user to accept a given certificate */
-typedef struct {
-	gchar *identity;
-	GTlsCertificate *cert;
-} UserCertRequestData;
-
-static void
-user_cert_request_data_free(UserCertRequestData *data)
-{
-	g_return_if_fail(data != NULL);
-
-	g_free(data->identity);
-	g_object_unref(data->cert);
-
-	g_free(data);
-}
-
-static void
-user_cert_request_accept_cb(UserCertRequestData *data)
-{
-	GError *error = NULL;
-
-	g_return_if_fail(data != NULL);
-
-	/* User accepted. Trust this certificate */
-	if(!purple_tls_certificate_trust(data->identity, data->cert, &error)) {
-		purple_debug_error("tls-certificate",
-				"Error trusting certificate '%s': %s",
-				data->identity, error->message);
-		g_clear_error(&error);
-	}
-
-	user_cert_request_data_free(data);
-}
-
-static void
-user_cert_request_deny_cb(UserCertRequestData *data)
-{
-	/* User denied. Free data related to the requst */
-	user_cert_request_data_free(data);
-}
-
-/* Prompts the user to accept the certificate as it failed due to the
- * passed errors.
- */
-static void
-request_accept_certificate(const gchar *identity, GTlsCertificate *peer_cert,
-		GTlsCertificateFlags errors)
-{
-	UserCertRequestData *data;
-	gchar *primary;
-
-	g_return_if_fail(identity != NULL && identity[0] != '\0');
-	g_return_if_fail(G_IS_TLS_CERTIFICATE(peer_cert));
-	g_return_if_fail(errors != 0);
-
-	data = g_new(UserCertRequestData, 1);
-	data->identity = g_strdup(identity);
-	data->cert = g_object_ref(peer_cert);
-
-	primary = g_strdup_printf(_("Accept certificate for %s?"), identity);
-	purple_request_certificate(data,
-			_("TLS Certificate Verification"),
-			primary,
-			tls_certificate_flags_to_reason(errors),
-			data->cert,
-			_("Accept"), G_CALLBACK(user_cert_request_accept_cb),
-			_("Reject"), G_CALLBACK(user_cert_request_deny_cb),
-			data);
-	g_free(primary);
-}
-
-/* Called when a GTlsConnection (which this handler has been connected to)
- *   has an error validating its certificate.
- * Returns TRUE if the certificate is already trusted, so the connection
- *   can continue.
- * Returns FALSE if the certificate is not trusted, causing the
- *   connection's handshake to fail, and then prompts the user to accept
- *   the certificate.
- */
-static gboolean
-accept_certificate_cb(GTlsConnection *conn, GTlsCertificate *peer_cert,
-		GTlsCertificateFlags errors, gpointer user_data)
-{
-	GTlsCertificate *trusted_cert;
-	GSocketConnectable *connectable;
-	const gchar *identity;
-
-	g_return_val_if_fail(G_IS_TLS_CLIENT_CONNECTION(conn), FALSE);
-	g_return_val_if_fail(G_IS_TLS_CERTIFICATE(peer_cert), FALSE);
-
-	/* Get the certificate identity from the GTlsClientConnection */
-
-	connectable = g_tls_client_connection_get_server_identity(
-			G_TLS_CLIENT_CONNECTION(conn));
-
-	g_return_val_if_fail(G_IS_SOCKET_CONNECTABLE(connectable), FALSE);
-
-	/* identity is owned by the connectable */
-	if (G_IS_NETWORK_ADDRESS(connectable)) {
-		identity = g_network_address_get_hostname(
-				G_NETWORK_ADDRESS(connectable));
-	} else if (G_IS_NETWORK_SERVICE(connectable)) {
-		identity = g_network_service_get_domain(
-				G_NETWORK_SERVICE(connectable));
-	} else {
-		g_return_val_if_reached(FALSE);
-	}
-
-	/* See if a trusted certificate matching the peer certificate exists */
-
-	trusted_cert = purple_tls_certificate_new_from_id(identity, NULL);
-
-	if (trusted_cert != NULL &&
-			g_tls_certificate_is_same(peer_cert, trusted_cert)) {
-		/* It's manually trusted. Accept certificate */
-		g_object_unref(trusted_cert);
-		return TRUE;
-	}
-
-	g_clear_object(&trusted_cert);
-
-	/* Certificate failed and isn't trusted.
-	 * Fail certificate and prompt user.
-	 */
-
-	request_accept_certificate(identity, peer_cert, errors);
-
-	return FALSE;
-}
-
-gpointer
-purple_tls_certificate_attach_to_tls_connection(GTlsConnection *conn)
-{
-	return g_object_connect(conn, "signal::accept-certificate",
-			accept_certificate_cb, NULL, NULL);
-}
-
-/* Called when GSocketClient signals an event.
- * Calls purple_tls_certificate_attach_to_tls_connection() on the client's
- * connection when it's about to handshake.
- */
-static void
-socket_client_event_cb(GSocketClient *client, GSocketClientEvent event,
-		GSocketConnectable *connectable, GIOStream *connection,
-		gpointer user_data)
-{
-	if (event == G_SOCKET_CLIENT_TLS_HANDSHAKING) {
-		/* Attach libpurple's certificate subsystem to the
-		 * GTlsConnection right before it starts the handshake
-		 */
-		purple_tls_certificate_attach_to_tls_connection(
-				G_TLS_CONNECTION(connection));
-	}
-}
-
-gpointer
-purple_tls_certificate_attach_to_socket_client(GSocketClient *client)
-{
-	return g_object_connect(client, "signal::event",
-			socket_client_event_cb, NULL, NULL);
-}
-
--- a/libpurple/tls-certificate.h	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- *
- * purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#ifndef _PURPLE_TLS_CERTIFICATE_H
-#define _PURPLE_TLS_CERTIFICATE_H
-/**
- * SECTION:tls-certificate
- * @section_id: libpurple-tls-certificate
- * @short_description: TLS certificate trust and storage API
- * @title: TLS Certificate API
- *
- * The TLS Certificate API provides functions for trusting and storing
- * certificates for use with TLS/SSL connections. This allows certificates,
- * which aren't considered valid by the TLS implementation, to be manually
- * trusted by the user, distrusted at a later time, and queried by the UI.
- * It also provides functions to simply wire this system into Gio.
- */
-
-#include <gio/gio.h>
-
-/**
- * purple_tls_certificate_list_ids:
- *
- * Returns a list of the IDs for certificates trusted with
- * purple_tls_certificate_trust() and friends. These IDs can then be passed
- * to purple_tls_certificate_new_from_id() or used directly, if desired.
- *
- * Returns: (transfer full) (element-type utf8): #GList of IDs described above
- *          Free with purple_tls_certificate_free_ids()
- */
-GList *
-purple_tls_certificate_list_ids(void);
-
-/**
- * purple_tls_certificate_free_ids:
- * @ids: (transfer full) (element-type utf8): List of ids retrieved from
- *       purple_tls_certificate_list_ids()
- *
- * Frees the list of IDs returned from purple_tls_certificate_list_ids().
- */
-void
-purple_tls_certificate_free_ids(GList *ids);
-
-/**
- * purple_tls_certificate_new_from_id:
- * @id: ID of certificate to load
- * @error: A GError location to store the error occurring, or NULL to ignore
- *
- * Loads the certificate referenced by ID into a #GTlsCertificate object.
- *
- * Returns: (transfer full): #GTlsCertificate loaded from ID
- */
-GTlsCertificate *
-purple_tls_certificate_new_from_id(const gchar *id, GError **error);
-
-/**
- * purple_tls_certificate_trust:
- * @id: ID to associate with the certificate
- * @certificate: Certificate to trust for TLS operations
- * @error: A GError location to store the error occurring, or NULL to ignore
- *
- * Trusts the certificate to be allowed for TLS operations even if
- * it would otherwise fail.
- *
- * Returns: #TRUE on success, #FALSE otherwise
- */
-gboolean
-purple_tls_certificate_trust(const gchar *id, GTlsCertificate *certificate,
-		GError **error);
-
-/**
- * purple_tls_certificate_distrust:
- * @id: ID associated with the certificate to distrust
- * @error: A GError location to store the error occurring, or NULL to ignore
- *
- * Revokes full trust of certificate. The certificate will be accepted
- * in TLS operations only if it passes normal validation.
- *
- * Returns: #TRUE on success, #FALSE otherwise
- */
-gboolean
-purple_tls_certificate_distrust(const gchar *id, GError **error);
-
-
-/**
- * purple_tls_certificate_attach_to_tls_connection:
- * @conn: #GTlsConnection to connect to
- *
- * Connects the Purple TLS certificate subsystem to @conn so it will accept
- * certificates trusted by purple_tls_certificate_trust() and friends.
- *
- * Returns: (transfer none) (type GObject.Object): @conn, similar to
- *          g_object_connect()
- */
-gpointer
-purple_tls_certificate_attach_to_tls_connection(GTlsConnection *conn);
-
-/**
- * purple_tls_certificate_attach_to_socket_client:
- * @client: #GSocketClient to connect to
- *
- * Connects the Purple TLS certificate subsystem to @client so any TLS
- * connections it creates will accept certificates trusted by
- * purple_tls_certificate_trust() and friends.
- *
- * Returns: (transfer none) (type GObject.Object): @client, similar to
- *          g_object_connect()
- */
-gpointer
-purple_tls_certificate_attach_to_socket_client(GSocketClient *client);
-
-G_END_DECLS
-
-#endif /* _PURPLE_TLS_CERTIFICATE_H */
--- a/libpurple/util.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/util.c	Fri Nov 30 02:50:38 2018 +0000
@@ -3333,12 +3333,6 @@
 /**************************************************************************
  * String Functions
  **************************************************************************/
-gboolean
-purple_strequal(const gchar *left, const gchar *right)
-{
-	return (g_strcmp0(left, right) == 0);
-}
-
 const char *
 purple_normalize(const PurpleAccount *account, const char *str)
 {
--- a/libpurple/util.h	Thu Nov 22 11:25:59 2018 +0200
+++ b/libpurple/util.h	Fri Nov 30 02:50:38 2018 +0000
@@ -1107,7 +1107,11 @@
  *
  * Returns: %TRUE if the strings are the same, else %FALSE.
  */
-gboolean purple_strequal(const gchar *left, const gchar *right);
+static inline gboolean
+purple_strequal(const gchar *left, const gchar *right)
+{
+	return (g_strcmp0(left, right) == 0);
+}
 
 /**
  * purple_normalize:
--- a/meson.build	Thu Nov 22 11:25:59 2018 +0200
+++ b/meson.build	Fri Nov 30 02:50:38 2018 +0000
@@ -295,7 +295,6 @@
 # # Check for GTK+ 2.18 and other things used by the GTK UI
 # #######################################################################
 enable_gestures = get_option('gestures')
-enable_gcr = get_option('gcr')
 
 # #######################################################################
 # Check Pidgin dependencies
@@ -322,24 +321,7 @@
 	else
 		enchant = []
 	endif
-
-	#######################################################################
-	# Check for GCR for its certificate widgets
-	#######################################################################
-	if enable_gcr
-		GCR = dependency('gcr-3', required : force_deps)
-		if GCR.found()
-			conf.set('ENABLE_GCR', true)
-		else
-			enable_gcr = false
-		endif
-	else
-		GCR = []
-	endif
-
-
 else	# GTK
-	enable_gcr = false
 	enable_enchant = false
 endif	# GTK
 
@@ -1104,7 +1086,6 @@
 message('Has you....................... : yes')
 message('')
 message('Build with Enchant support.... : ' + enable_enchant.to_string())
-message('Build with GCR widgets........ : ' + enable_gcr.to_string())
 message('Build Unity integration plugin.: ' + enable_unity.to_string())
 message('')
 message('Build with KWallet............ : ' + enable_kwallet.to_string())
--- a/meson_options.txt	Thu Nov 22 11:25:59 2018 +0200
+++ b/meson_options.txt	Fri Nov 30 02:50:38 2018 +0000
@@ -29,9 +29,6 @@
 option('gestures', type : 'boolean', value : true,
        description : 'compile with the gestures plugin')
 
-option('gcr', type : 'boolean', value : false,
-       description : 'compile with GCR certificate widgets')
-
 option('gstreamer', type : 'boolean', value : true,
        description : 'compile with GStreamer audio support')
 
--- a/pidgin/gtkaccount.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/pidgin/gtkaccount.c	Fri Nov 30 02:50:38 2018 +0000
@@ -1350,7 +1350,11 @@
 
 		if (purple_accounts_get_all() == NULL) {
 			/* We're adding our first account.  Be polite and show the buddy list */
-			purple_blist_set_visible(TRUE);
+			PidginBuddyList *blist =
+					pidgin_blist_get_default_gtk_blist();
+			if (blist != NULL && blist->window != NULL) {
+				gtk_window_present(GTK_WINDOW(blist->window));
+			}
 		}
 
 		account = purple_account_new(username, dialog->protocol_id);
--- a/pidgin/gtkblist.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/pidgin/gtkblist.c	Fri Nov 30 02:50:38 2018 +0000
@@ -40,7 +40,6 @@
 #include "gtkaccount.h"
 #include "gtkblist.h"
 #include "gtkcellrendererexpander.h"
-#include "gtkcertmgr.h"
 #include "gtkconv.h"
 #include "gtkdialogs.h"
 #include "gtkxfer.h"
@@ -246,59 +245,37 @@
 	return TRUE;
 }
 
-static gboolean gtk_blist_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data)
-{
-	/* unfortunately GdkEventConfigure ignores the window gravity, but  *
-	 * the only way we have of setting the position doesn't. we have to *
-	 * call get_position because it does pay attention to the gravity.  *
-	 * this is inefficient and I agree it sucks, but it's more likely   *
-	 * to work correctly.                                    - Robot101 */
-	gint x, y;
-
-	/* check for visibility because when we aren't visible, this will   *
-	 * give us bogus (0,0) coordinates.                      - xOr      */
-	if (gtk_widget_get_visible(w))
-		gtk_window_get_position(GTK_WINDOW(w), &x, &y);
-	else
-		return FALSE; /* carry on normally */
-
-#ifdef _WIN32
-	/* Workaround for GTK+ bug # 169811 - "configure_event" is fired
-	 * when the window is being maximized */
-	if (PIDGIN_WINDOW_MAXIMIZED(w))
-		return FALSE;
-#endif
-
-	/* don't save if nothing changed */
-	if (x == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/x") &&
-		y == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/y") &&
-		event->width  == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width") &&
-		event->height == purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/height")) {
-
-		return FALSE; /* carry on normally */
-	}
-
-	/* don't save off-screen positioning */
-	if (x + event->width < 0 ||
-		y + event->height < 0 ||
-		x > gdk_screen_width() ||
-		y > gdk_screen_height()) {
-
-		return FALSE; /* carry on normally */
-	}
+static void
+gtk_blist_hide_cb(GtkWidget *widget, gpointer data)
+{
+	purple_signal_emit(pidgin_blist_get_handle(),
+			"gtkblist-hiding", gtkblist);
+}
+
+static void
+gtk_blist_show_cb(GtkWidget *widget, gpointer data)
+{
+	purple_signal_emit(pidgin_blist_get_handle(),
+			"gtkblist-unhiding", gtkblist);
+}
+
+static void
+gtk_blist_size_allocate_cb(GtkWidget *widget, GtkAllocation *allocation,
+		gpointer data)
+{
+	int new_width;
+	int new_height;
 
 	/* ignore changes when maximized */
-	if(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized"))
-		return FALSE;
-
-	/* store the position */
-	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/x",      x);
-	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/y",      y);
-	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/width",  event->width);
-	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/height", event->height);
-
-	/* continue to handle event normally */
-	return FALSE;
+	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized")) {
+		return;
+	}
+
+	gtk_window_get_size(GTK_WINDOW(widget), &new_width, &new_height);
+
+	/* store the size */
+	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/width",  new_width);
+	purple_prefs_set_int(PIDGIN_PREFS_ROOT "/blist/height", new_height);
 }
 
 static void gtk_blist_menu_info_cb(GtkWidget *w, PurpleBuddy *b)
@@ -3651,7 +3628,6 @@
 	/* Tools */
 	{ "ToolsMenu", NULL, N_("_Tools"), NULL, NULL, NULL },
 	{ "BuddyPounces", NULL, N_("Buddy _Pounces"), NULL, NULL, pidgin_pounces_manager_show },
-	{ "Certificates", NULL, N_("_Certificates"), NULL, NULL, pidgin_certmgr_show },
 	{ "CustomSmileys", PIDGIN_STOCK_TOOLBAR_SMILEY, N_("Custom Smile_ys"), "<control>Y", NULL, pidgin_smiley_manager_show },
 	{ "Plugins", PIDGIN_STOCK_TOOLBAR_PLUGINS, N_("Plu_gins"), "<control>U", NULL, pidgin_plugin_dialog_show },
 	{ "Preferences", GTK_STOCK_PREFERENCES, N_("Pr_eferences"), "<control>P", NULL, pidgin_prefs_show },
@@ -3711,7 +3687,6 @@
 		"</menu>"
 		"<menu action='ToolsMenu'>"
 			"<menuitem action='BuddyPounces'/>"
-			"<menuitem action='Certificates'/>"
 			"<menuitem action='CustomSmileys'/>"
 			"<menuitem action='Plugins'/>"
 			"<menuitem action='Preferences'/>"
@@ -4464,35 +4439,21 @@
 	return text;
 }
 
-static void pidgin_blist_restore_position(void)
-{
-	int blist_x, blist_y, blist_width, blist_height;
+static void pidgin_blist_restore_window_state(void)
+{
+	int blist_width, blist_height;
 
 	blist_width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/width");
 
-	/* if the window exists, is hidden, we're saving positions, and the
-	 * position is sane... */
+	/* if the window exists, is hidden, we're saving sizes, and the
+	 * size is sane... */
 	if (gtkblist && gtkblist->window &&
 		!gtk_widget_get_visible(gtkblist->window) && blist_width != 0) {
 
-		blist_x      = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/x");
-		blist_y      = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/y");
 		blist_height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/blist/height");
 
-		/* ...check position is on screen... */
-		if (blist_x >= gdk_screen_width())
-			blist_x = gdk_screen_width() - 100;
-		else if (blist_x + blist_width < 0)
-			blist_x = 100;
-
-		if (blist_y >= gdk_screen_height())
-			blist_y = gdk_screen_height() - 100;
-		else if (blist_y + blist_height < 0)
-			blist_y = 100;
-
-		/* ...and move it back. */
-		gtk_window_move(GTK_WINDOW(gtkblist->window), blist_x, blist_y);
-		gtk_window_resize(GTK_WINDOW(gtkblist->window), blist_width, blist_height);
+		gtk_window_set_default_size(GTK_WINDOW(gtkblist->window),
+				blist_width, blist_height);
 		if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized"))
 			gtk_window_maximize(GTK_WINDOW(gtkblist->window));
 	}
@@ -5808,7 +5769,12 @@
 	gtk_container_add(GTK_CONTAINER(gtkblist->window), gtkblist->main_vbox);
 
 	g_signal_connect(G_OBJECT(gtkblist->window), "delete_event", G_CALLBACK(gtk_blist_delete_cb), NULL);
-	g_signal_connect(G_OBJECT(gtkblist->window), "configure_event", G_CALLBACK(gtk_blist_configure_cb), NULL);
+	g_signal_connect(G_OBJECT(gtkblist->window), "hide",
+			G_CALLBACK(gtk_blist_hide_cb), NULL);
+	g_signal_connect(G_OBJECT(gtkblist->window), "show",
+			G_CALLBACK(gtk_blist_show_cb), NULL);
+	g_signal_connect(G_OBJECT(gtkblist->window), "size-allocate",
+			G_CALLBACK(gtk_blist_size_allocate_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->window), "visibility_notify_event", G_CALLBACK(gtk_blist_visibility_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->window), "window_state_event", G_CALLBACK(gtk_blist_window_state_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->window), "key_press_event", G_CALLBACK(gtk_blist_window_key_press_cb), gtkblist);
@@ -6051,7 +6017,7 @@
 
 	/* OK... let's show this bad boy. */
 	pidgin_blist_refresh(list);
-	pidgin_blist_restore_position();
+	pidgin_blist_restore_window_state();
 	gtk_widget_show_all(GTK_WIDGET(gtkblist->vbox));
 	gtk_widget_realize(GTK_WIDGET(gtkblist->window));
 	purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible"));
@@ -6935,14 +6901,9 @@
 		return;
 
 	if (show) {
-		if(!PIDGIN_WINDOW_ICONIFIED(gtkblist->window) &&
-		   !gtk_widget_get_visible(gtkblist->window))
-			purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-unhiding", gtkblist);
-		pidgin_blist_restore_position();
-		gtk_window_present(GTK_WINDOW(gtkblist->window));
+		gtk_widget_show(gtkblist->window);
 	} else {
 		if(visibility_manager_count) {
-			purple_signal_emit(pidgin_blist_get_handle(), "gtkblist-hiding", gtkblist);
 			gtk_widget_hide(gtkblist->window);
 		} else {
 			if (!gtk_widget_get_visible(gtkblist->window))
@@ -7567,8 +7528,6 @@
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/blist/list_visible", FALSE);
 	purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/blist/list_maximized", FALSE);
 	purple_prefs_add_string(PIDGIN_PREFS_ROOT "/blist/sort_type", "alphabetical");
-	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/blist/x", 0);
-	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/blist/y", 0);
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/blist/width", 250); /* Golden ratio, baby */
 	purple_prefs_add_int(PIDGIN_PREFS_ROOT "/blist/height", 405); /* Golden ratio, baby */
 	purple_prefs_add_string(PIDGIN_PREFS_ROOT "/blist/theme", "");
--- a/pidgin/gtkcertmgr.c	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,663 +0,0 @@
-/* pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-
-#include "internal.h"
-#include "core.h"
-#include "pidgin.h"
-#include "pidginstock.h"
-
-#include "debug.h"
-#include "notify.h"
-#include "request.h"
-#include "tls-certificate.h"
-#include "tls-certificate-info.h"
-
-#include "gtk3compat.h"
-#include "gtkblist.h"
-#include "gtkutils.h"
-
-#include "gtkcertmgr.h"
-
-/*****************************************************************************
- * X.509 certificate management interface                                    *
- *****************************************************************************/
-
-typedef struct {
-	GtkWidget *mgmt_widget;
-	GtkTreeView *listview;
-	GtkTreeSelection *listselect;
-	GtkWidget *importbutton;
-	GtkWidget *exportbutton;
-	GtkWidget *infobutton;
-	GtkWidget *deletebutton;
-} tls_peers_mgmt_data;
-
-tls_peers_mgmt_data *tpm_dat = NULL;
-
-/* Columns
-   See http://developer.gnome.org/doc/API/2.0/gtk/TreeWidget.html */
-enum
-{
-	TPM_HOSTNAME_COLUMN,
-	TPM_N_COLUMNS
-};
-
-static void
-tls_peers_mgmt_destroy(GtkWidget *mgmt_widget, gpointer data)
-{
-	purple_debug_info("certmgr",
-			  "tls peers self-destructs\n");
-
-	purple_signals_disconnect_by_handle(tpm_dat);
-	purple_request_close_with_handle(tpm_dat);
-	g_free(tpm_dat); tpm_dat = NULL;
-}
-
-static void
-tls_peers_mgmt_repopulate_list(void)
-{
-	GtkTreeView *listview = tpm_dat->listview;
-	GList *idlist, *l;
-
-	GtkListStore *store = GTK_LIST_STORE(
-		gtk_tree_view_get_model(GTK_TREE_VIEW(listview)));
-
-	/* First, delete everything in the list */
-	gtk_list_store_clear(store);
-
-	/* Grab the available certificates */
-	idlist = purple_tls_certificate_list_ids();
-
-	/* Populate the listview */
-	for (l = idlist; l; l = l->next) {
-		GtkTreeIter iter;
-		gtk_list_store_append(store, &iter);
-
-		gtk_list_store_set(GTK_LIST_STORE(store), &iter,
-				   TPM_HOSTNAME_COLUMN, l->data,
-				   -1);
-	}
-
-	purple_tls_certificate_free_ids(idlist);
-}
-
-static void
-tls_peers_mgmt_select_chg_cb(GtkTreeSelection *ignored, gpointer data)
-{
-	GtkTreeSelection *select = tpm_dat->listselect;
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-
-	/* See if things are selected */
-	if (gtk_tree_selection_get_selected(select, &model, &iter)) {
-		/* Enable buttons if something is selected */
-		gtk_widget_set_sensitive(GTK_WIDGET(tpm_dat->exportbutton), TRUE);
-		gtk_widget_set_sensitive(GTK_WIDGET(tpm_dat->infobutton), TRUE);
-		gtk_widget_set_sensitive(GTK_WIDGET(tpm_dat->deletebutton), TRUE);
-	} else {
-		/* Otherwise, disable them */
-		gtk_widget_set_sensitive(GTK_WIDGET(tpm_dat->exportbutton), FALSE);
-		gtk_widget_set_sensitive(GTK_WIDGET(tpm_dat->infobutton), FALSE);
-		gtk_widget_set_sensitive(GTK_WIDGET(tpm_dat->deletebutton), FALSE);
-
-	}
-}
-
-static void
-tls_peers_mgmt_import_ok2_cb(gpointer data, const char *result)
-{
-	GTlsCertificate *crt = data;
-	GError *error = NULL;
-
-	/* TODO: Perhaps prompt if you're overwriting a cert? */
-
-	/* Trust the certificate */
-	if (result && *result) {
-		if(!purple_tls_certificate_trust(result, crt, &error)) {
-			purple_debug_error("gtkcertmgr/tls_peers_mgmt",
-					"Error trusting certificate '%s': %s",
-					result, error->message);
-			g_clear_error(&error);
-		}
-
-		tls_peers_mgmt_repopulate_list();
-	}
-
-	/* And this certificate is not needed any more */
-	g_object_unref(crt);
-}
-
-static void
-tls_peers_mgmt_import_cancel2_cb(gpointer data, const char *result)
-{
-	GTlsCertificate *crt = data;
-	g_object_unref(crt);
-}
-
-static void
-tls_peers_mgmt_import_ok_cb(gpointer data, const char *filename)
-{
-	GTlsCertificate *crt;
-	GError *error = NULL;
-
-	/* Now load the certificate from disk */
-	crt = g_tls_certificate_new_from_file(filename, &error);
-
-	/* Did it work? */
-	if (crt != NULL) {
-		gchar *default_hostname;
-		PurpleTlsCertificateInfo *info;
-
-		/* Get name to add trust as */
-		/* Make a guess about what the hostname should be */
-		info = purple_tls_certificate_get_info(crt);
-		default_hostname = purple_tls_certificate_info_get_subject_name(info);
-		purple_tls_certificate_info_free(info);
-
-		/* TODO: Find a way to make sure that crt gets destroyed
-		   if the window gets closed unusually, such as by handle
-		   deletion */
-		/* TODO: Display some more information on the certificate? */
-		purple_request_input(tpm_dat,
-				     _("Certificate Import"),
-				     _("Specify a hostname"),
-				     _("Type the host name for this certificate."),
-				     default_hostname,
-				     FALSE, /* Not multiline */
-				     FALSE, /* Not masked? */
-				     NULL,  /* No hints? */
-				     _("OK"),
-				     G_CALLBACK(tls_peers_mgmt_import_ok2_cb),
-				     _("Cancel"),
-				     G_CALLBACK(tls_peers_mgmt_import_cancel2_cb),
-				     NULL,  /* No additional parameters */
-				     crt    /* Pass cert instance to callback*/
-				     );
-
-		g_free(default_hostname);
-	} else {
-		/* Errors! Oh no! */
-		/* TODO: Perhaps find a way to be specific about what just
-		   went wrong? */
-		gchar * secondary;
-
-		purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
-				"File %s couldn't be imported: %s",
-				filename, error->message);
-		g_clear_error(&error);
-
-		secondary = g_strdup_printf(_("File %s could not be imported.\nMake sure that the file is readable and in PEM format.\n"), filename);
-		purple_notify_error(NULL,
-				    _("Certificate Import Error"),
-				    _("X.509 certificate import failed"),
-				    secondary, NULL);
-		g_free(secondary);
-	}
-}
-
-static void
-tls_peers_mgmt_import_cb(GtkWidget *button, gpointer data)
-{
-	/* TODO: need to tell the user that we want a .PEM file! */
-	purple_request_file(tpm_dat,
-			    _("Select a PEM certificate"),
-			    "certificate.pem",
-			    FALSE, /* Not a save dialog */
-			    G_CALLBACK(tls_peers_mgmt_import_ok_cb),
-			    NULL,  /* Do nothing if cancelled */
-			    NULL, NULL); /* No extra parameters */
-}
-
-static void
-tls_peers_mgmt_export_ok_cb(gpointer data, const char *filename)
-{
-	GTlsCertificate *crt = data;
-	gchar *pem = NULL;
-	GError *error = NULL;
-
-	g_assert(filename);
-
-	g_object_get(crt, "certificate-pem", &pem, NULL);
-
-	if (!g_file_set_contents(filename, pem, -1, &error)) {
-		/* Errors! Oh no! */
-		/* TODO: Perhaps find a way to be specific about what just
-		   went wrong? */
-		gchar * secondary;
-
-		purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
-				"File %s couldn't be exported: %s",
-				filename, error->message);
-		g_clear_error(&error);
-
-		secondary = g_strdup_printf(_("Export to file %s failed.\nCheck that you have write permission to the target path\n"), filename);
-		purple_notify_error(NULL,
-				    _("Certificate Export Error"),
-				    _("X.509 certificate export failed"),
-				    secondary, NULL);
-		g_free(secondary);
-	} else {
-		tls_peers_mgmt_repopulate_list();
-	}
-
-	g_free(pem);
-	g_object_unref(crt);
-}
-
-static void
-tls_peers_mgmt_export_cb(GtkWidget *button, gpointer data)
-{
-	GTlsCertificate *crt;
-	GtkTreeSelection *select = tpm_dat->listselect;
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-	gchar *id;
-	GError *error = NULL;
-
-	/* See if things are selected */
-	if (!gtk_tree_selection_get_selected(select, &model, &iter)) {
-		purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
-				     "Export clicked with no selection?\n");
-		return;
-	}
-
-	/* Retrieve the selected hostname */
-	gtk_tree_model_get(model, &iter, TPM_HOSTNAME_COLUMN, &id, -1);
-
-	/* Extract the certificate from the pool now to make sure it doesn't
-	   get deleted out from under us */
-	crt = purple_tls_certificate_new_from_id(id, &error);
-
-	if (NULL == crt) {
-		purple_debug_error("gtkcertmgr/tls_peers_mgmt",
-				   "Error fetching trusted cert '%s': %s\n",
-				   id, error->message);
-		g_clear_error(&error);
-		g_free(id);
-		return;
-	}
-	g_free(id);
-
-	/* TODO: inform user that it will be a PEM? */
-	purple_request_file(tpm_dat,
-			    _("PEM X.509 Certificate Export"),
-			    "certificate.pem",
-			    TRUE, /* Is a save dialog */
-			    G_CALLBACK(tls_peers_mgmt_export_ok_cb),
-			    G_CALLBACK(g_object_unref),
-			    NULL, /* No extra parameters */
-			    crt); /* Pass the certificate on to the callback */
-}
-
-static void
-tls_peers_mgmt_info_cb(GtkWidget *button, gpointer data)
-{
-	GtkTreeSelection *select = tpm_dat->listselect;
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-	gchar *id;
-	GTlsCertificate *crt;
-	gchar *title;
-	GError *error = NULL;
-
-	/* See if things are selected */
-	if (!gtk_tree_selection_get_selected(select, &model, &iter)) {
-		purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
-				     "Info clicked with no selection?\n");
-		return;
-	}
-
-	/* Retrieve the selected hostname */
-	gtk_tree_model_get(model, &iter, TPM_HOSTNAME_COLUMN, &id, -1);
-
-	/* Now retrieve the certificate */
-	crt = purple_tls_certificate_new_from_id(id, &error);
-
-	if (crt == NULL) {
-		purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
-				"Unable to fetch certificate '%s': %s",
-				id, error ? error->message : "unknown error");
-		g_clear_error(&error);
-		g_free(id);
-	}
-
-	/* Fire the notification */
-	title = g_strdup_printf(_("Certificate Information for %s"), id);
-	purple_request_certificate(tpm_dat, title, NULL, NULL, crt,
-	                           _("OK"), G_CALLBACK(g_object_unref),
-	                           _("Cancel"), G_CALLBACK(g_object_unref),
-	                           crt);
-
-	g_free(id);
-	g_free(title);
-}
-
-static void
-tls_peers_mgmt_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
-{
-	tls_peers_mgmt_info_cb(NULL, NULL);
-}
-
-static void
-tls_peers_mgmt_delete_confirm_cb(gchar *id, gint choice)
-{
-	GError *error = NULL;
-
-	if (1 == choice) {
-		/* Yes, distrust was confirmed */
-		/* Now distrust the thing */
-		if (!purple_tls_certificate_distrust(id, &error)) {
-			purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
-					     "Deletion failed on id %s: %s\n",
-					     id, error->message);
-			g_clear_error(&error);
-		} else {
-			tls_peers_mgmt_repopulate_list();
-		}
-	}
-
-	g_free(id);
-}
-
-static void
-tls_peers_mgmt_delete_cb(GtkWidget *button, gpointer data)
-{
-	GtkTreeSelection *select = tpm_dat->listselect;
-	GtkTreeIter iter;
-	GtkTreeModel *model;
-
-	/* See if things are selected */
-	if (gtk_tree_selection_get_selected(select, &model, &iter)) {
-
-		gchar *id;
-		gchar *primary;
-
-		/* Retrieve the selected hostname */
-		gtk_tree_model_get(model, &iter, TPM_HOSTNAME_COLUMN, &id, -1);
-
-		/* Prompt to confirm deletion */
-		primary = g_strdup_printf(
-			_("Really delete certificate for %s?"), id );
-
-		purple_request_yes_no(tpm_dat, _("Confirm certificate delete"),
-				      primary, NULL, /* Can this be NULL? */
-				      0, /* "yes" is the default action */
-				      NULL,
-				      id, /* id ownership passed to callback */
-				      tls_peers_mgmt_delete_confirm_cb,
-				      tls_peers_mgmt_delete_confirm_cb );
-
-		g_free(primary);
-
-	} else {
-		purple_debug_warning("gtkcertmgr/tls_peers_mgmt",
-				     "Delete clicked with no selection?\n");
-		return;
-	}
-}
-
-static GtkWidget *
-tls_peers_mgmt_build(void)
-{
-	GtkWidget *bbox;
-	GtkListStore *store;
-
-	/* This block of variables will end up in tpm_dat */
-	GtkTreeView *listview;
-	GtkTreeSelection *select;
-	GtkWidget *importbutton;
-	GtkWidget *exportbutton;
-	GtkWidget *infobutton;
-	GtkWidget *deletebutton;
-	/** Element to return to the Certmgr window to put in the Notebook */
-	GtkWidget *mgmt_widget;
-
-	/* Create a struct to store context information about this window */
-	tpm_dat = g_new0(tls_peers_mgmt_data, 1);
-
-	tpm_dat->mgmt_widget = mgmt_widget = gtk_box_new(
-		GTK_ORIENTATION_HORIZONTAL, PIDGIN_HIG_BOX_SPACE);
-	gtk_container_set_border_width(GTK_CONTAINER(mgmt_widget),
-		PIDGIN_HIG_BOX_SPACE);
-	gtk_widget_show(mgmt_widget);
-
-	/* Ensure that everything gets cleaned up when the dialog box
-	   is closed */
-	g_signal_connect(G_OBJECT(mgmt_widget), "destroy",
-			 G_CALLBACK(tls_peers_mgmt_destroy), NULL);
-
-	/* List view */
-	store = gtk_list_store_new(TPM_N_COLUMNS, G_TYPE_STRING);
-
-	tpm_dat->listview = listview =
-		GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)));
-	g_object_unref(G_OBJECT(store));
-
-	{
-		GtkCellRenderer *renderer;
-		GtkTreeViewColumn *column;
-
-		/* Set up the display columns */
-		renderer = gtk_cell_renderer_text_new();
-		column = gtk_tree_view_column_new_with_attributes(
-			_("Hostname"),
-			renderer,
-			"text", TPM_HOSTNAME_COLUMN,
-			NULL);
-		gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column);
-
-		gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store),
-				TPM_HOSTNAME_COLUMN, GTK_SORT_ASCENDING);
-	}
-
-	/* Get the treeview selector into the struct */
-	tpm_dat->listselect = select =
-		gtk_tree_view_get_selection(GTK_TREE_VIEW(listview));
-
-	/* Force the selection mode */
-	gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
-
-	/* Use a callback to enable/disable the buttons based on whether
-	   something is selected */
-	g_signal_connect(G_OBJECT(select), "changed",
-			 G_CALLBACK(tls_peers_mgmt_select_chg_cb), NULL);
-
-	g_signal_connect(G_OBJECT(listview), "row-activated",
-			 G_CALLBACK(tls_peers_mgmt_activated_cb), NULL);
-
-	gtk_box_pack_start(GTK_BOX(mgmt_widget), 
-			pidgin_make_scrollable(GTK_WIDGET(listview), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1),
-			TRUE, TRUE, /* Take up lots of space */
-			0);
-	gtk_widget_show(GTK_WIDGET(listview));
-
-	/* Fill the list for the first time */
-	tls_peers_mgmt_repopulate_list();
-
-	/* Right-hand side controls box */
-	bbox = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
-	gtk_box_pack_end(GTK_BOX(mgmt_widget), bbox,
-			 FALSE, FALSE, /* Do not take up space */
-			 0);
-	gtk_box_set_spacing(GTK_BOX(bbox), PIDGIN_HIG_BOX_SPACE);
-	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
-	gtk_widget_show(bbox);
-
-	/* Import button */
-	tpm_dat->importbutton = importbutton =
-		gtk_button_new_with_mnemonic(_("_Import..."));
-	gtk_box_pack_start(GTK_BOX(bbox), importbutton, FALSE, FALSE, 0);
-	gtk_widget_show(importbutton);
-	g_signal_connect(G_OBJECT(importbutton), "clicked",
-			 G_CALLBACK(tls_peers_mgmt_import_cb), NULL);
-
-
-	/* Export button */
-	tpm_dat->exportbutton = exportbutton =
-		gtk_button_new_with_mnemonic(_("_Export..."));
-	gtk_box_pack_start(GTK_BOX(bbox), exportbutton, FALSE, FALSE, 0);
-	gtk_widget_show(exportbutton);
-	g_signal_connect(G_OBJECT(exportbutton), "clicked",
-			 G_CALLBACK(tls_peers_mgmt_export_cb), NULL);
-
-
-	/* Info button */
-	tpm_dat->infobutton = infobutton =
-		gtk_button_new_with_mnemonic(_("_Get Info"));
-	gtk_box_pack_start(GTK_BOX(bbox), infobutton, FALSE, FALSE, 0);
-	gtk_widget_show(infobutton);
-	g_signal_connect(G_OBJECT(infobutton), "clicked",
-			 G_CALLBACK(tls_peers_mgmt_info_cb), NULL);
-
-
-	/* Delete button */
-	tpm_dat->deletebutton = deletebutton =
-		gtk_button_new_with_mnemonic(_("_Delete"));
-	gtk_box_pack_start(GTK_BOX(bbox), deletebutton, FALSE, FALSE, 0);
-	gtk_widget_show(deletebutton);
-	g_signal_connect(G_OBJECT(deletebutton), "clicked",
-			 G_CALLBACK(tls_peers_mgmt_delete_cb), NULL);
-
-	/* Call the "selection changed" callback, which will probably disable
-	   all the buttons since nothing is selected yet */
-	tls_peers_mgmt_select_chg_cb(select, NULL);
-
-	return mgmt_widget;
-}
-
-const PidginCertificateManager tls_peers_mgmt = {
-	tls_peers_mgmt_build, /* Widget creation function */
-	N_("SSL Servers")
-};
-
-/*****************************************************************************
- * GTK+ main certificate manager                                             *
- *****************************************************************************/
-typedef struct
-{
-	GtkWidget *window;
-	GtkWidget *notebook;
-
-	GtkWidget *closebutton;
-} CertMgrDialog;
-
-/* If a certificate manager window is open, this will point to it.
-   So if it is set, don't open another one! */
-CertMgrDialog *certmgr_dialog = NULL;
-
-static gboolean
-certmgr_close_cb(GtkWidget *w, CertMgrDialog *dlg)
-{
-	/* TODO: Ignoring the arguments to this function may not be ideal,
-	   but there *should* only be "one dialog to rule them all" at a time*/
-	pidgin_certmgr_hide();
-	return FALSE;
-}
-
-void
-pidgin_certmgr_show(void)
-{
-	CertMgrDialog *dlg;
-	GtkWidget *win;
-	GtkWidget *vbox;
-
-	/* Enumerate all the certificates on file */
-	{
-		GList *idlist;
-		GList *l;
-
-		purple_debug_info("gtkcertmgr",
-				  "Enumerating X.509 certificates:\n");
-
-		idlist = purple_tls_certificate_list_ids();
-
-		for (l=idlist; l; l = l->next) {
-			purple_debug_info("gtkcertmgr",
-					  "- %s\n",
-					  l->data ? (gchar *) l->data : "(null)");
-		} /* idlist */
-
-		purple_tls_certificate_free_ids(idlist);
-	}
-
-
-	/* If the manager is already open, bring it to the front */
-	if (certmgr_dialog != NULL) {
-		gtk_window_present(GTK_WINDOW(certmgr_dialog->window));
-		return;
-	}
-
-	/* Create the dialog, and set certmgr_dialog so we never create
-	   more than one at a time */
-	dlg = certmgr_dialog = g_new0(CertMgrDialog, 1);
-
-	win = dlg->window =
-		pidgin_create_dialog(_("Certificate Manager"),/* Title */
-				     0, /*Window border*/
-				     "certmgr",         /* Role */
-				     TRUE); /* Allow resizing */
-	g_signal_connect(G_OBJECT(win), "delete_event",
-			 G_CALLBACK(certmgr_close_cb), dlg);
-
-
-	/* TODO: Retrieve the user-set window size and use it */
-	gtk_window_set_default_size(GTK_WINDOW(win), 400, 400);
-
-	/* Main vbox */
-	vbox = pidgin_dialog_get_vbox_with_properties(GTK_DIALOG(win), FALSE, PIDGIN_HIG_BORDER);
-
-	/* Notebook of various certificate managers */
-	dlg->notebook = gtk_notebook_new();
-	gtk_box_pack_start(GTK_BOX(vbox), dlg->notebook,
-			   TRUE, TRUE, /* Notebook should take extra space */
-			   0);
-	gtk_widget_show(dlg->notebook);
-
-	/* Close button */
-	dlg->closebutton = pidgin_dialog_add_button(GTK_DIALOG(win),
-			_("_Close"), G_CALLBACK(certmgr_close_cb), dlg);
-
-	/* Add the defined certificate managers */
-	/* TODO: Find a way of determining whether each is shown or not */
-	/* TODO: Implement this correctly */
-	gtk_notebook_append_page(GTK_NOTEBOOK (dlg->notebook),
-				 (tls_peers_mgmt.build)(),
-				 gtk_label_new(_(tls_peers_mgmt.label)) );
-
-	gtk_widget_show(win);
-}
-
-void
-pidgin_certmgr_hide(void)
-{
-	/* If it isn't open, do nothing */
-	if (certmgr_dialog == NULL) {
-		return;
-	}
-
-	purple_signals_disconnect_by_handle(certmgr_dialog);
-	purple_prefs_disconnect_by_handle(certmgr_dialog);
-
-	gtk_widget_destroy(certmgr_dialog->window);
-	g_free(certmgr_dialog);
-	certmgr_dialog = NULL;
-}
--- a/pidgin/gtkcertmgr.h	Thu Nov 22 11:25:59 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- *
- */
-
-#ifndef _PIDGINCERTMGR_H_
-#define _PIDGINCERTMGR_H_
-/**
- * SECTION:gtkcertmgr
- * @section_id: pidgin-gtkcertmgr
- * @short_description: <filename>gtkcertmgr.h</filename>
- * @title: Certificate Manager API
- */
-
-/**************************************************************************
- * Structures                                                             *
- **************************************************************************/
-typedef struct _PidginCertificateManager PidginCertificateManager;
-
-/**
- * PidginCertificateManager:
- *
- * GTK+ Certificate Manager subwidget
- */
-struct _PidginCertificateManager {
-	/* Create, configure, show, and return the management interface */
-	GtkWidget * (* build)(void);
-	/* Notebook label to use in the CertMgr dialog */
-	gchar *label;
-};
-
-G_BEGIN_DECLS
-
-/**************************************************************************/
-/* Certificate Manager API                                                */
-/**************************************************************************/
-
-/**
- * pidgin_certmgr_show:
- *
- * Show the certificate manager window
- */
-void pidgin_certmgr_show(void);
-
-/**
- * pidgin_certmgr_hide:
- *
- * Hide the certificate manager window
- */
-void pidgin_certmgr_hide(void);
-
-G_END_DECLS
-
-#endif /* _PIDGINCERTMGR_H_ */
--- a/pidgin/gtkprefs.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/pidgin/gtkprefs.c	Fri Nov 30 02:50:38 2018 +0000
@@ -4202,6 +4202,8 @@
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/show_group_count");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/show_warning_level");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/tooltip_delay");
+	purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/x");
+	purple_prefs_remove(PIDGIN_PREFS_ROOT "/blist/y");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/button_type");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/ctrl_enter_sends");
 	purple_prefs_remove(PIDGIN_PREFS_ROOT "/conversations/enter_sends");
--- a/pidgin/gtkrequest.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/pidgin/gtkrequest.c	Fri Nov 30 02:50:38 2018 +0000
@@ -26,7 +26,6 @@
 
 #include "debug.h"
 #include "prefs.h"
-#include "tls-certificate-info.h"
 #include "util.h"
 
 #include "gtkrequest.h"
@@ -37,11 +36,6 @@
 
 #include <gdk/gdkkeysyms.h>
 
-#ifdef ENABLE_GCR
-#define GCR_API_SUBJECT_TO_CHANGE
-#include <gcr/gcr.h>
-#endif
-
 #include "gtk3compat.h"
 
 typedef struct
@@ -1485,56 +1479,6 @@
 	return pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_IN, -1, -1);
 }
 
-static GtkWidget *
-create_certificate_field(PurpleRequestField *field)
-{
-	GTlsCertificate *cert;
-#ifdef ENABLE_GCR
-	GByteArray *der = NULL;
-	GcrCertificateBasicsWidget *cert_widget;
-	GcrCertificate *gcrt;
-#else
-	PurpleTlsCertificateInfo *info;
-	GtkWidget *cert_label;
-	char *str;
-	char *escaped;
-#endif
-
-	cert = purple_request_field_certificate_get_value(field);
-
-#ifdef ENABLE_GCR
-	g_object_get(cert, "certificate", &der, NULL);
-	g_return_val_if_fail(der, NULL);
-
-	gcrt = gcr_simple_certificate_new(der->data, der->len);
-	g_return_val_if_fail(gcrt, NULL);
-
-	cert_widget = gcr_certificate_basics_widget_new(gcrt);
-
-	g_byte_array_free(der, TRUE);
-	g_object_unref(G_OBJECT(gcrt));
-
-	return GTK_WIDGET(cert_widget);
-#else
-	info = purple_tls_certificate_get_info(cert);
-	str = purple_tls_certificate_info_get_display_string(info);
-	purple_tls_certificate_info_free(info);
-
-	escaped = g_markup_escape_text(str, -1);
-
-	cert_label = gtk_label_new(NULL);
-	gtk_label_set_markup(GTK_LABEL(cert_label), escaped);
-	gtk_label_set_line_wrap(GTK_LABEL(cert_label), TRUE);
-	gtk_label_set_xalign(GTK_LABEL(cert_label), 0);
-	gtk_label_set_yalign(GTK_LABEL(cert_label), 0);
-
-	g_free(str);
-	g_free(escaped);
-
-	return cert_label;
-#endif
-}
-
 static GdkPixbuf*
 _pidgin_datasheet_stock_icon_get(const gchar *stock_name)
 {
@@ -2331,8 +2275,6 @@
 						widget = create_image_field(field);
 					else if (type == PURPLE_REQUEST_FIELD_ACCOUNT)
 						widget = create_account_field(field);
-					else if (type == PURPLE_REQUEST_FIELD_CERTIFICATE)
-						widget = create_certificate_field(field);
 					else if (type == PURPLE_REQUEST_FIELD_DATASHEET)
 						widget = create_datasheet_field(field, datasheet_buttons_sg);
 					else
--- a/pidgin/libpidgin.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/pidgin/libpidgin.c	Fri Nov 30 02:50:38 2018 +0000
@@ -366,7 +366,36 @@
 static void
 pidgin_activate_cb(GApplication *application, gpointer user_data)
 {
-	purple_blist_set_visible(TRUE);
+	PidginBuddyList *blist = pidgin_blist_get_default_gtk_blist();
+
+	if (blist != NULL && blist->window != NULL) {
+		gtk_window_present(GTK_WINDOW(blist->window));
+	}
+}
+
+static gint
+pidgin_command_line_cb(GApplication *application,
+		GApplicationCommandLine *cmdline, gpointer user_data)
+{
+	gchar **argv;
+	int argc;
+	int i;
+
+	argv = g_application_command_line_get_arguments(cmdline, &argc);
+
+	if (argc == 1) {
+		/* No arguments, just activate */
+		g_application_activate(application);
+	}
+
+	/* Start at 1 to skip the executable name */
+	for (i = 1; i < argc; ++i) {
+		purple_got_protocol_handler_uri(argv[i]);
+	}
+
+	g_strfreev(argv);
+
+	return 0;
 }
 
 static gchar *opt_config_dir_arg = NULL;
@@ -703,11 +732,9 @@
 
 	app = G_APPLICATION(gtk_application_new("im.pidgin.Pidgin",
 #if GLIB_CHECK_VERSION(2, 48, 0)
-				G_APPLICATION_CAN_OVERRIDE_APP_ID
-#else
-				G_APPLICATION_FLAGS_NONE
+				G_APPLICATION_CAN_OVERRIDE_APP_ID |
 #endif
-				));
+				G_APPLICATION_HANDLES_COMMAND_LINE));
 
 	summary = g_strdup_printf("%s %s", PIDGIN_NAME, DISPLAY_VERSION);
 	g_application_set_option_context_summary(app, summary);
@@ -727,6 +754,8 @@
 			G_CALLBACK(pidgin_startup_cb), NULL);
 	g_signal_connect(app, "activate",
 			G_CALLBACK(pidgin_activate_cb), NULL);
+	g_signal_connect(app, "command-line",
+			G_CALLBACK(pidgin_command_line_cb), NULL);
 
 	ret = g_application_run(app, argc, argv);
 
--- a/pidgin/meson.build	Thu Nov 22 11:25:59 2018 +0200
+++ b/pidgin/meson.build	Fri Nov 30 02:50:38 2018 +0000
@@ -5,7 +5,6 @@
 	'gtkblist-theme.c',
 	'gtkblist-theme-loader.c',
 	'gtkcellrendererexpander.c',
-	'gtkcertmgr.c',
 	'gtkconn.c',
 	'gtkconv.c',
 	'gtkconv-theme.c',
@@ -54,7 +53,6 @@
 	'gtkblist-theme.h',
 	'gtkblist-theme-loader.h',
 	'gtkcellrendererexpander.h',
-	'gtkcertmgr.h',
 	'gtkconn.h',
 	'gtkconv.h',
 	'gtkconvwin.h',
@@ -162,7 +160,6 @@
 	    dependencies : [
 	    	dbus,
 	    	enchant,
-	    	GCR,
 	    	glib,
 	    	gstreamer_video,
 	    	gtk,
--- a/pidgin/win32/gtkwin32dep.c	Thu Nov 22 11:25:59 2018 +0200
+++ b/pidgin/win32/gtkwin32dep.c	Fri Nov 30 02:50:38 2018 +0000
@@ -39,6 +39,7 @@
 #include "untar.h"
 
 #include "gtkwin32dep.h"
+#include "gtkblist.h"
 #include "gtkconv.h"
 #include "gtkconn.h"
 #include "util.h"
@@ -237,8 +238,12 @@
 static LRESULT CALLBACK message_window_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
 
 	if (msg == PIDGIN_WM_FOCUS_REQUEST) {
+		PidginBuddyList *blist;
 		purple_debug_info("winpidgin", "Got external Buddy List focus request.");
-		purple_blist_set_visible(TRUE);
+		blist = pidgin_blist_get_default_gtk_blist();
+		if (blist != NULL && blist->window != NULL) {
+			gtk_window_present(GTK_WINDOW(blist->window));
+		}
 		return TRUE;
 	} else if (msg == PIDGIN_WM_PROTOCOL_HANDLE) {
 		char *proto_msg = (char *) lparam;
--- a/po/POTFILES.in	Thu Nov 22 11:25:59 2018 +0200
+++ b/po/POTFILES.in	Fri Nov 30 02:50:38 2018 +0000
@@ -2,7 +2,6 @@
 finch/finch.c
 finch/gntaccount.c
 finch/gntblist.c
-finch/gntcertmgr.c
 finch/gntconn.c
 finch/gntconv.c
 finch/gntdebug.c
@@ -162,8 +161,6 @@
 libpurple/smiley.c
 libpurple/sslconn.c
 libpurple/status.c
-libpurple/tls-certificate-info.c
-libpurple/tls-certificate.c
 libpurple/util.c
 libpurple/win32/libc_interface.c
 libpurple/xfer.c
@@ -175,7 +172,6 @@
 pidgin/gtkaccount.c
 pidgin/gtkblist-theme.c
 pidgin/gtkblist.c
-pidgin/gtkcertmgr.c
 pidgin/gtkconn.c
 pidgin/gtkconv.c
 pidgin/gtkdebug.c

mercurial