Remove the SILC protocol plugin

Wed, 26 Oct 2022 01:22:53 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Wed, 26 Oct 2022 01:22:53 -0500
changeset 41832
63f39d354a73
parent 41831
596940e90c68
child 41833
a6a511564c1b

Remove the SILC protocol plugin

We've done a lot to try to keep this protocol plugin alive, but it crashes when
you try to connect to silcnet and most distros don't even have the dependency
anymore.

Therefore, I declare it's time that we drop our support for it.

Testing Done:
Ran a full build and `ninja pidgin-pot`

Reviewed at https://reviews.imfreedom.org/r/1970/

libpurple/protocols/meson.build file | annotate | diff | comparison | revisions
libpurple/protocols/silc/README file | annotate | diff | comparison | revisions
libpurple/protocols/silc/TODO file | annotate | diff | comparison | revisions
libpurple/protocols/silc/buddy.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/chat.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/ft.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/ft.h file | annotate | diff | comparison | revisions
libpurple/protocols/silc/meson.build file | annotate | diff | comparison | revisions
libpurple/protocols/silc/ops.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/pk.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/resources/icons/16x16/apps/im-silc.png file | annotate | diff | comparison | revisions
libpurple/protocols/silc/resources/icons/16x16/apps/scalable/im-silc.svg file | annotate | diff | comparison | revisions
libpurple/protocols/silc/resources/icons/22x22/apps/im-silc.png file | annotate | diff | comparison | revisions
libpurple/protocols/silc/resources/icons/22x22/apps/scalable/im-silc.svg file | annotate | diff | comparison | revisions
libpurple/protocols/silc/resources/icons/48x48/apps/im-silc.png file | annotate | diff | comparison | revisions
libpurple/protocols/silc/resources/icons/scalable/apps/im-silc.svg file | annotate | diff | comparison | revisions
libpurple/protocols/silc/resources/silc.gresource.xml file | annotate | diff | comparison | revisions
libpurple/protocols/silc/silc.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/silcpurple.h file | annotate | diff | comparison | revisions
libpurple/protocols/silc/util.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/wb.c file | annotate | diff | comparison | revisions
libpurple/protocols/silc/wb.h file | annotate | diff | comparison | revisions
meson.build file | annotate | diff | comparison | revisions
meson_options.txt file | annotate | diff | comparison | revisions
pidgin/data/im.pidgin.Pidgin3.desktop.in.in file | annotate | diff | comparison | revisions
po/POTFILES.in file | annotate | diff | comparison | revisions
--- a/libpurple/protocols/meson.build	Wed Oct 26 01:13:45 2022 -0500
+++ b/libpurple/protocols/meson.build	Wed Oct 26 01:22:53 2022 -0500
@@ -7,5 +7,4 @@
 subdir('jabber')
 subdir('novell')
 subdir('sametime')
-subdir('silc')
 subdir('zephyr')
--- a/libpurple/protocols/silc/README	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-SILC Purple Plugin
-==================
-
-This is the Purple protocol plugin of the protocol called Secure Internet
-Live Conferencing (SILC).  The implementation will use the SILC Toolkit,
-freely available from the http://silcnet.org/ site, for the actual SILC
-protocol implementation.
-
-To include SILC into Purple, one needs to first compile and install
-the SILC Toolkit.  It is done as follows:
-
-	./configure
-	make
-	make install
-
-This will compile shared libraries of the SILC Toolkit.  If the --prefix
-is not given to ./configure, the binaries are installed into the
-/usr/local/silc directory.
-
-Once the Toolkit is installed one needs to tell Purple's ./configure
-script where the SILC Toolkit is located.  It is done as simply as:
-
-	./configure
-
-if pkg-config is installed in your system.  If it is isn't it's done as:
-
-	./configure --with-silc-libs=/path/to/silc/lib
-		    --with-silc-includes=/path/to/silc/include
-
-If the SILC Toolkit cannot be found then the SILC protocol plugin will
-not be compiled.
--- a/libpurple/protocols/silc/TODO	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-Features TODO (maybe)
-=====================
-
-Preferences
-	- Add joined channels to buddy list automatically (during
-	  session)
--- a/libpurple/protocols/silc/buddy.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1749 +0,0 @@
-/*
-
-  silcpurple_buddy.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include <glib/gi18n-lib.h>
-#include <glib/gstdio.h>
-
-#include "libpurple/glibcompat.h"
-
-#include "silcpurple.h"
-#include "wb.h"
-
-/***************************** Key Agreement *********************************/
-
-static void
-silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data);
-
-static void
-silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
-			   gboolean force_local);
-
-static void
-silcpurple_buddy_keyagr_resolved(SilcClient client,
-				 SilcClientConnection conn,
-				 SilcStatus status,
-				 SilcDList clients,
-				 void *context)
-{
-	PurpleConnection *gc = client->application;
-	char *nick = context;
-
-	if (!clients) {
-		char tmp[256];
-
-		g_snprintf(tmp, sizeof(tmp),
-		           _("User %s is not present in the network"), nick);
-		purple_notify_error(gc, _("Key Agreement"),
-			_("Cannot perform the key agreement"), tmp,
-			purple_request_cpar_from_connection(gc));
-	} else {
-		silcpurple_buddy_keyagr_do(gc, nick, FALSE);
-	}
-
-	g_free(nick);
-}
-
-static void
-silcpurple_buddy_keyagr_cb(SilcClient client,
-			   SilcClientConnection conn,
-			   SilcClientEntry client_entry,
-			   SilcKeyAgreementStatus status,
-			   SilcSKEKeyMaterial key,
-			   void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-
-	if (!sg->conn)
-		return;
-
-	switch (status) {
-	case SILC_KEY_AGREEMENT_OK:
-		{
-			PurpleConversation *im;
-			PurpleConversationManager *manager;
-			char tmp[128];
-
-			/* Set the private key for this client */
-			silc_client_del_private_message_key(client, conn, client_entry);
-			silc_client_add_private_message_key_ske(client, conn, client_entry,
-								NULL, NULL, key);
-			silc_ske_free_key_material(key);
-
-			manager = purple_conversation_manager_get_default();
-
-			/* Open IM window */
-			im = purple_conversation_manager_find_im(manager, sg->account,
-			                                         client_entry->nickname);
-			if (im) {
-				/* we don't have windows in the core anymore...but we may want to
-				 * provide some method for asking the UI to show the window
-				purple_conversation_window_show(purple_conversation_get_window(im));
-				 */
-			} else {
-				im = purple_im_conversation_new(sg->account,
-								client_entry->nickname);
-			}
-			g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname);
-			purple_conversation_set_title(im, tmp);
-		}
-		break;
-
-	case SILC_KEY_AGREEMENT_ERROR:
-		purple_notify_error(gc, _("Key Agreement"),
-			_("Error occurred during key agreement"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	case SILC_KEY_AGREEMENT_FAILURE:
-		purple_notify_error(gc, _("Key Agreement"),
-			_("Key Agreement failed"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	case SILC_KEY_AGREEMENT_TIMEOUT:
-		purple_notify_error(gc, _("Key Agreement"),
-			_("Timeout during key agreement"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	case SILC_KEY_AGREEMENT_ABORTED:
-		purple_notify_error(gc, _("Key Agreement"),
-			_("Key agreement was aborted"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	case SILC_KEY_AGREEMENT_ALREADY_STARTED:
-		purple_notify_error(gc, _("Key Agreement"), _("Key agreement is"
-			" already started"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	case SILC_KEY_AGREEMENT_SELF_DENIED:
-		purple_notify_error(gc, _("Key Agreement"), _("Key agreement "
-			"cannot be started with yourself"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	default:
-		break;
-	}
-}
-
-static void
-silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name,
-			   gboolean force_local)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcDList clients;
-	SilcClientEntry client_entry;
-	SilcClientConnectionParams params;
-	char *local_ip = NULL, *remote_ip = NULL;
-	gboolean local = TRUE;
-	SilcSocket sock;
-
-	if (!sg->conn || !name)
-		return;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(sg->client, sg->conn, name,
-						FALSE);
-	if (!clients) {
-		/* Resolve unknown user */
-		silc_client_get_clients(sg->client, sg->conn, name, NULL,
-		                        silcpurple_buddy_keyagr_resolved, g_strdup(name));
-		return;
-	}
-
-	silc_socket_stream_get_info(silc_packet_stream_get_stream(sg->conn->stream),
-				    &sock, NULL, NULL, NULL);
-
-	/* Resolve the local IP from the outgoing socket connection.  We resolve
-	   it to check whether we have a private range IP address or public IP
-	   address.  If we have public then we will assume that we are not behind
-	   NAT and will provide automatically the point of connection to the
-	   agreement.  If we have private range address we assume that we are
-	   behind NAT and we let the responder provide the point of connection.
-
-	   The algorithm also checks the remote IP address of server connection.
-	   If it is private range address and we have private range address we
-	   assume that we are chatting in LAN and will provide the point of
-	   connection.
-
-	   Naturally this algorithm does not always get things right. */
-
-	if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) {
-		/* Check if the IP is private */
-		if (!force_local && silcpurple_ip_is_private(local_ip)) {
-			local = FALSE;
-
-			/* Local IP is private, resolve the remote server IP to see whether
-			   we are talking to Internet or just on LAN. */
-			if (silc_net_check_host_by_sock(sock, NULL,
-							&remote_ip))
-				if (silcpurple_ip_is_private(remote_ip))
-					/* We assume we are in LAN.  Let's provide
-					   the connection point. */
-					local = TRUE;
-		}
-	}
-
-	if (force_local)
-		local = TRUE;
-
-	if (local && !local_ip)
-		local_ip = silc_net_localip();
-
-	silc_dlist_start(clients);
-	client_entry = silc_dlist_get(clients);
-
-	memset(&params, 0, sizeof(params));
-	params.timeout_secs = 60;
-	if (local)
-	  /* Provide connection point */
-	  params.local_ip = local_ip;
-
-	/* Send the key agreement request */
-	silc_client_send_key_agreement(sg->client, sg->conn, client_entry,
-				       &params, sg->public_key,
-				       sg->private_key,
-				       silcpurple_buddy_keyagr_cb, NULL);
-
-	silc_free(local_ip);
-	silc_free(remote_ip);
-	silc_client_list_free(sg->client, sg->conn, clients);
-}
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-	char *hostname;
-	SilcUInt16 port;
-} *SilcPurpleKeyAgrAsk;
-
-static void
-silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id)
-{
-	SilcClientEntry client_entry;
-	SilcClientConnectionParams params;
-
-	if (id != 1)
-		goto out;
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(a->client, a->conn,
-						    &a->client_id);
-	if (!client_entry) {
-		purple_notify_error(a->client->application, _("Key Agreement"),
-				    _("The remote user is not present in the network any more"),
-				    NULL, NULL);
-		goto out;
-	}
-
-	/* If the hostname was provided by the requestor perform the key agreement
-	   now.  Otherwise, we will send him a request to connect to us. */
-	if (a->hostname) {
-		memset(&params, 0, sizeof(params));
-		params.timeout_secs = 60;
-		silc_client_perform_key_agreement(a->client, a->conn,
-						  client_entry, &params,
-						  a->conn->public_key,
-						  a->conn->private_key,
-						  a->hostname, a->port,
-						  silcpurple_buddy_keyagr_cb, NULL);
-	} else {
-		/* Send request.  Force us as the point of connection since requestor
-		   did not provide the point of connection. */
-		silcpurple_buddy_keyagr_do(a->client->application,
-					   client_entry->nickname, TRUE);
-	}
-
- out:
-	g_free(a->hostname);
-	silc_free(a);
-}
-
-void silcpurple_buddy_keyagr_request(SilcClient client,
-				     SilcClientConnection conn,
-				     SilcClientEntry client_entry,
-				     const char *hostname, SilcUInt16 port,
-				     SilcUInt16 protocol)
-{
-	char tmp[128], tmp2[128];
-	SilcPurpleKeyAgrAsk a;
-	PurpleConnection *gc = client->application;
-
-	/* For now Pidgin don't support UDP key agreement */
-	if (protocol == 1)
-	  return;
-
-	g_snprintf(tmp, sizeof(tmp),
-		   _("Key agreement request received from %s. Would you like to "
-		     "perform the key agreement?"), client_entry->nickname);
-	if (hostname)
-		g_snprintf(tmp2, sizeof(tmp2),
-			   _("The remote user is waiting key agreement on:\n"
-			     "Remote host: %s\nRemote port: %d"), hostname, port);
-
-	a = silc_calloc(1, sizeof(*a));
-	if (!a)
-		return;
-	a->client = client;
-	a->conn = conn;
-	a->client_id = client_entry->id;
-	if (hostname)
-		a->hostname = g_strdup(hostname);
-	a->port = port;
-
-	purple_request_action(client->application, _("Key Agreement Request"), tmp,
-			      hostname ? tmp2 : NULL, 1, purple_request_cpar_from_connection(gc),
-			      a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb),
-			      _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb));
-}
-
-static void
-silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleAccount *account;
-
-	buddy = (PurpleBuddy *)node;
-	account = purple_buddy_get_account(buddy);
-	silcpurple_buddy_keyagr_do(purple_account_get_connection(account),
-			purple_buddy_get_name(buddy), FALSE);
-}
-
-
-/**************************** Static IM Key **********************************/
-
-static void
-silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b;
-	PurpleConnection *gc;
-        SilcPurple sg;
-	SilcDList clients;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	b = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(b));
-	sg = purple_connection_get_protocol_data(gc);
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(sg->client, sg->conn,
-						purple_buddy_get_name(b), FALSE);
-	if (!clients)
-		return;
-
-	silc_dlist_start(clients);
-	silc_client_del_private_message_key(sg->client, sg->conn,
-					    silc_dlist_get(clients));
-	silc_client_list_free(sg->client, sg->conn, clients);
-}
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-} *SilcPurplePrivkey;
-
-static void
-silcpurple_buddy_privkey(PurpleConnection *gc, const char *name);
-
-static void
-silcpurple_buddy_privkey_cb(SilcPurplePrivkey p, const char *passphrase)
-{
-	SilcClientEntry client_entry;
-
-        if (!passphrase || !(*passphrase)) {
-                silc_free(p);
-                return;
-        }
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(p->client, p->conn,
-						    &p->client_id);
-	if (!client_entry) {
-		purple_notify_error(p->client->application, _("IM With Password"),
-				    _("The remote user is not present in the network any more"),
-				    NULL, NULL);
-		silc_free(p);
-		return;
-	}
-
-	/* Set the private message key */
-	silc_client_del_private_message_key(p->client, p->conn,
-					    client_entry);
-	silc_client_add_private_message_key(p->client, p->conn,
-					    client_entry, NULL, NULL,
-					    (unsigned char *)passphrase,
-					    strlen(passphrase));
-        silc_free(p);
-}
-
-static void
-silcpurple_buddy_privkey_resolved(SilcClient client,
-				  SilcClientConnection conn,
-				  SilcStatus status,
-				  SilcDList clients,
-				  void *context)
-{
-	char tmp[256];
-
-	if (!clients) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("User %s is not present in the network"),
-			   (const char *)context);
-		purple_notify_error(client->application, _("IM With Password"),
-				  _("Cannot set IM key"), tmp, NULL);
-		g_free(context);
-		return;
-	}
-
-	silcpurple_buddy_privkey(client->application, context);
-	g_free(context);
-}
-
-static void
-silcpurple_buddy_privkey(PurpleConnection *gc, const char *name)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcPurplePrivkey p;
-	SilcDList clients;
-	SilcClientEntry client_entry;
-
-	if (!name)
-		return;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(sg->client, sg->conn,
-						name, FALSE);
-	if (!clients) {
-		silc_client_get_clients(sg->client, sg->conn, name, NULL,
-					silcpurple_buddy_privkey_resolved,
-					g_strdup(name));
-		return;
-	}
-
-	silc_dlist_start(clients);
-	client_entry = silc_dlist_get(clients);
-
-	p = silc_calloc(1, sizeof(*p));
-	if (!p)
-		return;
-	p->client = sg->client;
-	p->conn = sg->conn;
-	p->client_id = client_entry->id;
-	purple_request_input(gc, _("IM With Password"), NULL,
-	                     _("Set IM Password"), NULL, FALSE, TRUE, NULL,
-	                     _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb),
-	                     _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb),
-	                     purple_request_cpar_from_connection(gc), p);
-
-	silc_client_list_free(sg->client, sg->conn, clients);
-}
-
-static void
-silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-
-	silcpurple_buddy_privkey(gc, purple_buddy_get_name(buddy));
-}
-
-
-/**************************** Get Public Key *********************************/
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-} *SilcPurpleBuddyGetkey;
-
-static void
-silcpurple_buddy_getkey(PurpleConnection *gc, const char *name);
-
-static SilcBool
-silcpurple_buddy_getkey_cb(SilcClient client, SilcClientConnection conn,
-			   SilcCommand command, SilcStatus status,
-			   SilcStatus error, void *context, va_list ap)
-{
-	SilcClientEntry client_entry;
-	SilcPurpleBuddyGetkey g = context;
-
-	if (status != SILC_STATUS_OK) {
-		purple_notify_error(g->client->application, _("Get Public Key"),
-				  _("The remote user is not present in the network any more"),
-				  NULL, NULL);
-		silc_free(g);
-		return FALSE;
-	}
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(g->client, g->conn,
-						    &g->client_id);
-	if (!client_entry) {
-		purple_notify_error(g->client->application, _("Get Public Key"),
-				  _("The remote user is not present in the network any more"),
-				  NULL, NULL);
-		silc_free(g);
-		return FALSE;
-	}
-
-	if (!client_entry->public_key) {
-		silc_free(g);
-		return FALSE;
-	}
-
-	/* Now verify the public key */
-	silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname,
-				     SILC_CONN_CLIENT, client_entry->public_key,
-				     NULL, NULL);
-	silc_free(g);
-	return TRUE;
-}
-
-static void
-silcpurple_buddy_getkey_resolved(SilcClient client,
-				 SilcClientConnection conn,
-				 SilcStatus status,
-				 SilcDList clients,
-				 void *context)
-{
-	char tmp[256];
-
-	if (!clients) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("User %s is not present in the network"),
-			   (const char *)context);
-		purple_notify_error(client->application, _("Get Public Key"),
-				    _("Cannot fetch the public key"), tmp, NULL);
-		g_free(context);
-		return;
-	}
-
-	silcpurple_buddy_getkey(client->application, context);
-	g_free(context);
-}
-
-static void
-silcpurple_buddy_getkey(PurpleConnection *gc, const char *name)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientEntry client_entry;
-	SilcDList clients;
-	SilcPurpleBuddyGetkey g;
-	SilcUInt16 cmd_ident;
-
-	if (!name)
-		return;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, name, FALSE);
-	if (!clients) {
-		silc_client_get_clients(client, conn, name, NULL,
-					silcpurple_buddy_getkey_resolved,
-					g_strdup(name));
-		return;
-	}
-
-	silc_dlist_start(clients);
-	client_entry = silc_dlist_get(clients);
-
-	/* Call GETKEY */
-	g = silc_calloc(1, sizeof(*g));
-	if (!g)
-		return;
-	g->client = client;
-	g->conn = conn;
-	g->client_id = client_entry->id;
-	cmd_ident = silc_client_command_call(client, conn, NULL, "GETKEY",
-					     client_entry->nickname, NULL);
-	silc_client_command_pending(conn, SILC_COMMAND_GETKEY, cmd_ident,
-				    silcpurple_buddy_getkey_cb, g);
-	silc_client_list_free(client, conn, clients);
-}
-
-static void
-silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(buddy));
-
-	silcpurple_buddy_getkey(gc, purple_buddy_get_name(buddy));
-}
-
-static void
-silcpurple_buddy_showkey(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b;
-	PurpleConnection *gc;
-	SilcPurple sg;
-	SilcPublicKey public_key;
-	const char *pkfile;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	b = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(b));
-	sg = purple_connection_get_protocol_data(gc);
-
-	pkfile = purple_blist_node_get_string(node, "public-key");
-	if (!silc_pkcs_load_public_key(pkfile, &public_key)) {
-		purple_notify_error(gc, _("Show Public Key"),
-			_("Could not load public key"), NULL,
-			purple_request_cpar_from_connection(gc));
-		return;
-	}
-
-	silcpurple_show_public_key(sg, purple_buddy_get_name(b), public_key, NULL, NULL);
-	silc_pkcs_public_key_free(public_key);
-}
-
-
-/**************************** Buddy routines *********************************/
-
-/* The buddies are implemented by using the WHOIS and WATCH commands that
-   can be used to search users by their public key.  Since nicknames aren't
-   unique in SILC we cannot trust the buddy list using their nickname.  We
-   associate public keys to buddies and use those to search and watch
-   in the network.
-
-   The problem is that Purple does not return PurpleBuddy contexts to the
-   callbacks but the buddy names.  Naturally, this is not going to work
-   with SILC.  But, for now, we have to do what we can... */
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcClientID client_id;
-	PurpleBuddy *b;
-	unsigned char *offline_pk;
-	SilcUInt32 offline_pk_len;
-	SilcPublicKey public_key;
-	unsigned int offline        : 1;
-	unsigned int pubkey_search  : 1;
-	unsigned int init           : 1;
-} *SilcPurpleBuddyRes;
-
-static void
-silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id);
-static void
-silcpurple_add_buddy_resolved(SilcClient client,
-			      SilcClientConnection conn,
-			      SilcStatus status,
-			      SilcDList clients,
-			      void *context);
-
-void silcpurple_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientEntry client_entry;
-	PurpleBuddy *b;
-	const char *filename, *nick = who;
-	char tmp[256];
-
-	if (!who)
-		return;
-	if (strlen(who) > 1 && who[0] == '@')
-		nick = who + 1;
-	if (strlen(who) > 1 && who[0] == '*')
-		nick = who + 1;
-	if (strlen(who) > 2 && who[0] == '*' && who[1] == '@')
-		nick = who + 2;
-
-	b = purple_blist_find_buddy(purple_connection_get_account(gc), nick);
-	if (b) {
-		/* See if we have this buddy's public key.  If we do use that
-		   to search the details. */
-		gpointer proto_data;
-		filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
-		if (filename) {
-			/* Call WHOIS.  The user info is displayed in the WHOIS
-			   command reply. */
-			silc_client_command_call(client, conn, NULL, "WHOIS",
-						 "-details", "-pubkey", filename, NULL);
-			return;
-		}
-
-		if (!(proto_data = purple_buddy_get_protocol_data(b))) {
-			g_snprintf(tmp, sizeof(tmp),
-				   _("User %s is not present in the network"), purple_buddy_get_name(b));
-			purple_notify_error(gc, _("User Information"),
-				_("Cannot get user information"), tmp,
-				purple_request_cpar_from_connection(gc));
-			return;
-		}
-
-		client_entry = silc_client_get_client_by_id(client, conn, proto_data);
-		if (client_entry) {
-			/* Call WHOIS.  The user info is displayed in the WHOIS
-			   command reply. */
-			silc_client_command_call(client, conn, NULL, "WHOIS",
-						 client_entry->nickname, "-details", NULL);
-		}
-	} else {
-		/* Call WHOIS just with nickname. */
-		silc_client_command_call(client, conn, NULL, "WHOIS", nick, NULL);
-	}
-}
-
-static void
-silcpurple_add_buddy_pk_no(SilcPurpleBuddyRes r)
-{
-	char tmp[512];
-	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"),
-		   purple_buddy_get_name(r->b));
-	purple_notify_error(r->client->application, _("Add Buddy"), tmp,
-			    _("You cannot receive buddy notifications until you "
-			      "import his/her public key.  You can use the Get Public Key "
-			      "command to get the public key."),
-		purple_request_cpar_from_account(purple_buddy_get_account(r->b)));
-	purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-}
-
-static void
-silcpurple_add_buddy_save(SilcBool success, void *context)
-{
-	SilcPurpleBuddyRes r = context;
-	PurpleBuddy *b = r->b;
-	SilcClientEntry client_entry;
-	SilcAttributePayload attr;
-	SilcAttribute attribute;
-	SilcVCardStruct vcard;
-	SilcMime message = NULL, extension = NULL;
-	SilcMime usericon = NULL;
-	SilcAttributeObjPk serverpk, usersign, serversign;
-	gboolean usign_success = TRUE, ssign_success = TRUE;
-	char filename[512], filename2[512], *fingerprint = NULL, *tmp;
-	SilcUInt32 len;
-	SilcHash hash;
-	gsize i;
-
-	if (!success) {
-		/* The user did not trust the public key. */
-		silcpurple_add_buddy_pk_no(r);
-		silc_free(r->offline_pk);
-		if (r->public_key)
-		  silc_pkcs_public_key_free(r->public_key);
-		silc_free(r);
-		return;
-	}
-
-	if (r->offline) {
-		/* User is offline.  Associate the imported public key with
-		   this user. */
-		fingerprint = silc_hash_fingerprint(NULL, r->offline_pk,
-						    r->offline_pk_len);
-		for (i = 0; i < strlen(fingerprint); i++)
-			if (fingerprint[i] == ' ')
-				fingerprint[i] = '_';
-		g_snprintf(filename, sizeof(filename) - 1,
-			   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
-			   silcpurple_silcdir(), fingerprint);
-		purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
-		purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-		silc_free(fingerprint);
-		silc_free(r->offline_pk);
-		if (r->public_key)
-		  silc_pkcs_public_key_free(r->public_key);
-		silc_free(r);
-		return;
-	}
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(r->client, r->conn,
-						    &r->client_id);
-	if (!client_entry) {
-		silc_free(r->offline_pk);
-		silc_pkcs_public_key_free(r->public_key);
-		if (r->public_key)
-		  silc_pkcs_public_key_free(r->public_key);
-		silc_free(r);
-		return;
-	}
-
-	memset(&vcard, 0, sizeof(vcard));
-	memset(&serverpk, 0, sizeof(serverpk));
-	memset(&usersign, 0, sizeof(usersign));
-	memset(&serversign, 0, sizeof(serversign));
-
-	/* Now that we have the public key and we trust it now we
-	   save the attributes of the buddy and update its status. */
-
-	if (client_entry->attrs) {
-		silc_dlist_start(client_entry->attrs);
-		while ((attr = silc_dlist_get(client_entry->attrs))
-		       != SILC_LIST_END) {
-			attribute = silc_attribute_get_attribute(attr);
-
-			switch (attribute) {
-			case SILC_ATTRIBUTE_USER_INFO:
-				if (!silc_attribute_get_object(attr, (void *)&vcard,
-							       sizeof(vcard)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_STATUS_MESSAGE:
-				message = silc_mime_alloc();
-				if (!silc_attribute_get_object(attr, (void *)message,
-							       sizeof(*message)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_EXTENSION:
-				extension = silc_mime_alloc();
-				if (!silc_attribute_get_object(attr, (void *)extension,
-							       sizeof(*extension)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_USER_ICON:
-				usericon = silc_mime_alloc();
-				if (!silc_attribute_get_object(attr, (void *)usericon,
-							       sizeof(*usericon)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
-				if (serverpk.type)
-					continue;
-				if (!silc_attribute_get_object(attr, (void *)&serverpk,
-							       sizeof(serverpk)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
-				if (usersign.data)
-					continue;
-				if (!silc_attribute_get_object(attr, (void *)&usersign,
-							       sizeof(usersign)))
-					continue;
-				break;
-
-			case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
-				if (serversign.data)
-					continue;
-				if (!silc_attribute_get_object(attr, (void *)&serversign,
-							       sizeof(serversign)))
-					continue;
-				break;
-
-			default:
-				break;
-			}
-		}
-	}
-
-	/* Verify the attribute signatures */
-	silc_hash_alloc((const unsigned char *)"sha1", &hash);
-
-	if (usersign.data) {
-		unsigned char *verifyd;
-		SilcUInt32 verify_len;
-
-		verifyd = silc_attribute_get_verify_data(client_entry->attrs,
-							 FALSE, &verify_len);
-		if (verifyd && !silc_pkcs_verify(client_entry->public_key,
-						 usersign.data,
-						 usersign.data_len,
-						 verifyd, verify_len, hash))
-			usign_success = FALSE;
-		silc_free(verifyd);
-	}
-
-	if (serversign.data) {
-		SilcPublicKey public_key;
-		SilcPKCSType type = 0;
-		unsigned char *verifyd;
-		SilcUInt32 verify_len;
-
-		if (purple_strequal(serverpk.type, "silc-rsa"))
-		  type = SILC_PKCS_SILC;
-		else if (purple_strequal(serverpk.type, "ssh-rsa"))
-		  type = SILC_PKCS_SSH2;
-		else if (purple_strequal(serverpk.type, "x509v3-sign-rsa"))
-		  type = SILC_PKCS_X509V3;
-		else if (purple_strequal(serverpk.type, "pgp-sign-rsa"))
-		  type = SILC_PKCS_OPENPGP;
-
-		if (silc_pkcs_public_key_alloc(type, serverpk.data,
-					       serverpk.data_len,
-					       &public_key)) {
-			verifyd = silc_attribute_get_verify_data(client_entry->attrs,
-								 TRUE, &verify_len);
-			if (verifyd && !silc_pkcs_verify(public_key,
-							 serversign.data,
-							 serversign.data_len,
-							 verifyd, verify_len,
-							 hash))
-				ssign_success = FALSE;
-			silc_pkcs_public_key_free(public_key);
-			silc_free(verifyd);
-		}
-	}
-
-	fingerprint = silc_fingerprint(client_entry->fingerprint, 20);
-	for (i = 0; i < strlen(fingerprint); i++)
-		if (fingerprint[i] == ' ')
-			fingerprint[i] = '_';
-
-	if (usign_success || ssign_success) {
-		struct passwd *pw;
-
-		memset(filename2, 0, sizeof(filename2));
-
-		/* Filename for dir */
-		tmp = fingerprint + strlen(fingerprint) - 9;
-		g_snprintf(filename, sizeof(filename) - 1,
-			   "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s",
-			   silcpurple_silcdir(), tmp);
-
-		pw = getpwuid(getuid());
-		if (!pw)
-			return;
-
-		/* Create dir if it doesn't exist */
-		if (pw->pw_uid == geteuid()) {
-			if (g_mkdir(filename, 0755) != 0 && errno != EEXIST)
-				return;
-		}
-
-		/* Save VCard */
-		g_snprintf(filename2, sizeof(filename2) - 1,
-			   "%s" G_DIR_SEPARATOR_S "vcard", filename);
-		if (vcard.full_name) {
-			tmp = (char *)silc_vcard_encode(&vcard, &len);
-			silc_file_writefile(filename2, tmp, len);
-			silc_free(tmp);
-		}
-
-		/* Save status message */
-		if (message) {
-			memset(filename2, 0, sizeof(filename2));
-			g_snprintf(filename2, sizeof(filename2) - 1,
-				   "%s" G_DIR_SEPARATOR_S "status_message.mime",
-				   filename);
-			tmp = (char *)silc_mime_get_data(message, &len);
-			silc_file_writefile(filename2, tmp, len);
-			silc_mime_free(message);
-		}
-
-		/* Save extension data */
-		if (extension) {
-			memset(filename2, 0, sizeof(filename2));
-			g_snprintf(filename2, sizeof(filename2) - 1,
-				   "%s" G_DIR_SEPARATOR_S "extension.mime",
-				   filename);
-			tmp = (char *)silc_mime_get_data(extension, &len);
-			silc_file_writefile(filename2, tmp, len);
-			silc_mime_free(extension);
-		}
-
-		/* Save user icon */
-		if (usericon) {
-			const char *type = silc_mime_get_field(usericon, "Content-Type");
-			if (type &&
-			    (purple_strequal(type, "image/jpeg") ||
-			     purple_strequal(type, "image/gif") ||
-			     purple_strequal(type, "image/bmp") ||
-			     purple_strequal(type, "image/png"))) {
-				const unsigned char *data;
-				SilcUInt32 data_len;
-				data = silc_mime_get_data(usericon, &data_len);
-				if (data) {
-					/* TODO: Check if SILC gives us something to use as the checksum instead */
-					purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup2(data, data_len), data_len, NULL);
-				}
-			}
-			silc_mime_free(usericon);
-		}
-	}
-
-	/* Save the public key path to buddy properties, as it is used
-	   to identify the buddy in the network (and not the nickname). */
-	memset(filename, 0, sizeof(filename));
-	g_snprintf(filename, sizeof(filename) - 1,
-		   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
-		   silcpurple_silcdir(), fingerprint);
-	purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
-
-	/* Update online status */
-	purple_protocol_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
-
-	/* Finally, start watching this user so we receive its status
-	   changes from the server */
-	g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename);
-	silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey",
-				 filename2, NULL);
-
-	silc_hash_free(hash);
-	silc_free(fingerprint);
-	silc_free(r->offline_pk);
-	if (r->public_key)
-	  silc_pkcs_public_key_free(r->public_key);
-	silc_free(r);
-}
-
-static void
-silcpurple_add_buddy_ask_import(void *user_data, const char *name)
-{
-	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;
-
-	/* Load the public key */
-	if (!silc_pkcs_load_public_key(name, &r->public_key)) {
-		silcpurple_add_buddy_ask_pk_cb(r, 0);
-		purple_notify_error(r->client->application, _("Add Buddy"),
-			_("Could not load public key"), NULL,
-			purple_request_cpar_from_account(
-				purple_buddy_get_account(r->b)));
-		return;
-	}
-
-	/* Now verify the public key */
-	r->offline_pk = silc_pkcs_public_key_encode(r->public_key, &r->offline_pk_len);
-	silcpurple_verify_public_key(r->client, r->conn, purple_buddy_get_name(r->b),
-				     SILC_CONN_CLIENT, r->public_key,
-				     silcpurple_add_buddy_save, r);
-}
-
-static void
-silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name)
-{
-	SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data;
-
-	/* The user did not import public key.  The buddy is unusable. */
-	silcpurple_add_buddy_pk_no(r);
-	silc_free(r);
-}
-
-static void
-silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id)
-{
-	if (id != 0) {
-		/* The user did not import public key.  The buddy is unusable. */
-		silcpurple_add_buddy_pk_no(r);
-		silc_free(r);
-		return;
-	}
-
-	/* Open file selector to select the public key. */
-	purple_request_file(r->client->application, _("Open..."), NULL, FALSE,
-			    G_CALLBACK(silcpurple_add_buddy_ask_import),
-			    G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel),
-			    purple_request_cpar_from_account(purple_buddy_get_account(r->b)), r);
-
-}
-
-static void
-silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r)
-{
-	char tmp[512];
-	g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"),
-		   purple_buddy_get_name(r->b));
-	purple_request_action(r->client->application, _("Add Buddy"), tmp,
-			      _("To add the buddy you must import his/her public key. "
-				"Press Import to import a public key."), 0,
-				purple_request_cpar_from_account(purple_buddy_get_account(r->b)), r, 2,
-			      _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb),
-			      _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb));
-}
-
-static SilcBool
-silcpurple_add_buddy_getkey_cb(SilcClient client, SilcClientConnection conn,
-			       SilcCommand command, SilcStatus status,
-			       SilcStatus error, void *context, va_list ap)
-{
-	SilcPurpleBuddyRes r = context;
-	SilcClientEntry client_entry;
-
-	if (status != SILC_STATUS_OK) {
-		/* The buddy is offline/nonexistent. We will require user
-		   to associate a public key with the buddy or the buddy
-		   cannot be added. */
-		r->offline = TRUE;
-		silcpurple_add_buddy_ask_pk(r);
-		return FALSE;
-	}
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(r->client, r->conn,
-						    &r->client_id);
-	if (!client_entry || !client_entry->public_key) {
-		/* The buddy is offline/nonexistent. We will require user
-		   to associate a public key with the buddy or the buddy
-		   cannot be added. */
-		r->offline = TRUE;
-		silcpurple_add_buddy_ask_pk(r);
-		return FALSE;
-	}
-
-	/* Now verify the public key */
-	silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname,
-				     SILC_CONN_CLIENT, client_entry->public_key,
-				     silcpurple_add_buddy_save, r);
-	return TRUE;
-}
-
-static void
-silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
-{
-	PurpleRequestField *f;
-	GList *list;
-	SilcClientEntry client_entry;
-	SilcDList clients;
-
-	f = purple_request_fields_get_field(fields, "list");
-	list = purple_request_field_list_get_selected(f);
-	if (!list) {
-		/* The user did not select any user. */
-		silcpurple_add_buddy_pk_no(r);
-		silc_free(r);
-		return;
-	}
-
-	client_entry = purple_request_field_list_get_data(f, list->data);
-	clients = silc_dlist_init();
-	silc_dlist_add(clients, client_entry);
-	silcpurple_add_buddy_resolved(r->client, r->conn, SILC_STATUS_OK,
-				      clients, r);
-	silc_dlist_uninit(clients);
-}
-
-static void
-silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
-{
-	/* The user did not select any user. */
-	silcpurple_add_buddy_pk_no(r);
-	silc_free(r);
-}
-
-static void
-silcpurple_add_buddy_select(SilcPurpleBuddyRes r, SilcDList clients)
-{
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	char tmp[512], tmp2[128];
-	char *fingerprint;
-	SilcClientEntry client_entry;
-
-	fields = purple_request_fields_new();
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_list_new("list", NULL);
-	purple_request_field_group_add_field(g, f);
-	purple_request_field_list_set_multi_select(f, FALSE);
-	purple_request_fields_add_group(fields, g);
-
-	silc_dlist_start(clients);
-	while ((client_entry = silc_dlist_get(clients))) {
-		fingerprint = NULL;
-		if (*client_entry->fingerprint) {
-			fingerprint = silc_fingerprint(client_entry->fingerprint, 20);
-			g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint);
-		}
-		g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s",
-			   client_entry->realname, client_entry->nickname,
-			   client_entry->username, *client_entry->hostname ?
-			   client_entry->hostname : "",
-			   fingerprint ? tmp2 : "");
-		purple_request_field_list_add_icon(f, tmp, NULL, client_entry);
-		silc_free(fingerprint);
-	}
-
-	purple_request_fields(r->client->application, _("Add Buddy"),
-			      _("Select correct user"),
-			      r->pubkey_search
-			      ? _("More than one user was found with the same public key. Select "
-				  "the correct user from the list to add to the buddy list.")
-			      : _("More than one user was found with the same name. Select "
-				  "the correct user from the list to add to the buddy list."),
-			      fields,
-			      _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb),
-			      _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel),
-			      purple_request_cpar_from_account(purple_buddy_get_account(r->b)), r);
-}
-
-static void
-silcpurple_add_buddy_resolved(SilcClient client,
-			      SilcClientConnection conn,
-			      SilcStatus status,
-			      SilcDList clients,
-			      void *context)
-{
-	SilcPurpleBuddyRes r = context;
-	PurpleBuddy *b = r->b;
-	SilcAttributePayload pub;
-	SilcAttributeObjPk userpk;
-	const char *filename;
-	SilcClientEntry client_entry = NULL;
-	SilcUInt16 cmd_ident;
-	const char *name;
-
-	filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
-
-	/* If the buddy is offline/nonexistent, we will require user
-	   to associate a public key with the buddy or the buddy
-	   cannot be added. */
-	if (!clients) {
-		if (r->init) {
-			silc_free(r);
-			return;
-		}
-
-		r->offline = TRUE;
-		/* If the user has already associated a public key, try loading it
-		 * before prompting the user to load it again */
-		if (filename != NULL)
-			silcpurple_add_buddy_ask_import(r, filename);
-		else
-			silcpurple_add_buddy_ask_pk(r);
-		return;
-	}
-
-	/* If more than one client was found with nickname, we need to verify
-	   from user which one is the correct. */
-	if (silc_dlist_count(clients) > 1 && !r->pubkey_search) {
-		if (r->init) {
-			silc_free(r);
-			return;
-		}
-
-		silcpurple_add_buddy_select(r, clients);
-		return;
-	}
-
-	silc_dlist_start(clients);
-	client_entry = silc_dlist_get(clients);
-
-	name = purple_buddy_get_name(b);
-
-	/* If we searched using public keys and more than one entry was found
-	   the same person is logged on multiple times. */
-	if (silc_dlist_count(clients) > 1 && r->pubkey_search && name) {
-		if (r->init) {
-			/* Find the entry that closest matches to the
-			   buddy nickname. */
-			SilcClientEntry entry;
-			silc_dlist_start(clients);
-			while ((entry = silc_dlist_get(clients))) {
-				if (!g_ascii_strncasecmp(name, entry->nickname,
-						 strlen(name))) {
-					client_entry = entry;
-					break;
-				}
-			}
-		} else {
-			/* Verify from user which one is correct */
-			silcpurple_add_buddy_select(r, clients);
-			return;
-		}
-	}
-
-	g_return_if_fail(client_entry != NULL);
-
-	/* The client was found.  Now get its public key and verify
-	   that before adding the buddy. */
-	memset(&userpk, 0, sizeof(userpk));
-	purple_buddy_set_protocol_data(b, silc_memdup(&client_entry->id, sizeof(client_entry->id)));
-	r->client_id = client_entry->id;
-
-	/* Get the public key from attributes, if not present then
-	   resolve it with GETKEY unless we have it cached already. */
-	if (client_entry->attrs && !client_entry->public_key) {
-		pub = silcpurple_get_attr(client_entry->attrs,
-					  SILC_ATTRIBUTE_USER_PUBLIC_KEY);
-		if (!pub || !silc_attribute_get_object(pub, (void *)&userpk,
-						       sizeof(userpk))) {
-			/* Get public key with GETKEY */
-			cmd_ident =
-			  silc_client_command_call(client, conn, NULL,
-						   "GETKEY", client_entry->nickname, NULL);
-			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-						    cmd_ident,
-						    silcpurple_add_buddy_getkey_cb,
-						    r);
-			return;
-		}
-		if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC,
-						userpk.data, userpk.data_len,
-						&client_entry->public_key))
-			return;
-		silc_free(userpk.data);
-	} else if (filename && !client_entry->public_key) {
-		if (!silc_pkcs_load_public_key(filename, &client_entry->public_key)) {
-			/* Get public key with GETKEY */
-			cmd_ident =
-			  silc_client_command_call(client, conn, NULL,
-						   "GETKEY", client_entry->nickname, NULL);
-			silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-						    cmd_ident,
-						    silcpurple_add_buddy_getkey_cb,
-						    r);
-			return;
-		}
-	} else if (!client_entry->public_key) {
-		/* Get public key with GETKEY */
-		cmd_ident =
-		  silc_client_command_call(client, conn, NULL,
-					   "GETKEY", client_entry->nickname, NULL);
-		silc_client_command_pending(conn, SILC_COMMAND_GETKEY,
-					    cmd_ident,
-					    silcpurple_add_buddy_getkey_cb,
-					    r);
-		return;
-	}
-
-	/* We have the public key, verify it. */
-	silcpurple_verify_public_key(client, conn, client_entry->nickname,
-				     SILC_CONN_CLIENT,
-				     client_entry->public_key,
-				     silcpurple_add_buddy_save, r);
-}
-
-static void
-silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcPurpleBuddyRes r;
-	SilcBuffer attrs;
-	const char *filename, *name = purple_buddy_get_name(b);
-
-	r = silc_calloc(1, sizeof(*r));
-	if (!r)
-		return;
-	r->client = client;
-	r->conn = conn;
-	r->b = b;
-	r->init = init;
-
-	/* See if we have this buddy's public key.  If we do use that
-	   to search the details. */
-	filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key");
-	if (filename) {
-		SilcPublicKey public_key;
-		SilcAttributeObjPk userpk;
-
-		if (!silc_pkcs_load_public_key(filename, &public_key))
-			return;
-
-		/* Get all attributes, and use the public key to search user */
-		name = NULL;
-		attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
-						       SILC_ATTRIBUTE_SERVICE,
-						       SILC_ATTRIBUTE_STATUS_MOOD,
-						       SILC_ATTRIBUTE_STATUS_FREETEXT,
-						       SILC_ATTRIBUTE_STATUS_MESSAGE,
-						       SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
-						       SILC_ATTRIBUTE_PREFERRED_CONTACT,
-						       SILC_ATTRIBUTE_TIMEZONE,
-						       SILC_ATTRIBUTE_GEOLOCATION,
-						       SILC_ATTRIBUTE_USER_ICON,
-						       SILC_ATTRIBUTE_DEVICE_INFO, 0);
-		userpk.type = "silc-rsa";
-		userpk.data = silc_pkcs_public_key_encode(public_key, &userpk.data_len);
-		attrs = silc_attribute_payload_encode(attrs,
-						      SILC_ATTRIBUTE_USER_PUBLIC_KEY,
-						      SILC_ATTRIBUTE_FLAG_VALID,
-						      &userpk, sizeof(userpk));
-		silc_free(userpk.data);
-		silc_pkcs_public_key_free(public_key);
-		r->pubkey_search = TRUE;
-	} else {
-		/* Get all attributes */
-		attrs = silc_client_attributes_request(0);
-	}
-
-	/* Resolve */
-	silc_client_get_clients_whois(client, conn, name, NULL, attrs,
-				      silcpurple_add_buddy_resolved, r);
-	silc_buffer_free(attrs);
-}
-
-void silcpurple_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
-{
-	/* Don't add if the buddy is already on the list.
-	 *
-	 * SILC doesn't have groups, so we also don't need to do anything
-	 * for a move. */
-	if (purple_buddy_get_protocol_data(buddy) == NULL)
-		silcpurple_add_buddy_i(gc, buddy, FALSE);
-}
-
-void silcpurple_send_buddylist(PurpleConnection *gc)
-{
-	GSList *buddies;
-	PurpleAccount *account;
-
-	account = purple_connection_get_account(gc);
-
-	for (buddies = purple_blist_find_buddies(account, NULL); buddies;
-			buddies = g_slist_delete_link(buddies, buddies))
-	{
-		PurpleBuddy *buddy = buddies->data;
-		silcpurple_add_buddy_i(gc, buddy, TRUE);
-	}
-}
-
-void silcpurple_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
-			   PurpleGroup *group)
-{
-	silc_free(purple_buddy_get_protocol_data(buddy));
-}
-
-void silcpurple_idle_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc, int idle)
-
-{
-	SilcPurple sg;
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcAttributeObjService service;
-	const char *server;
-	int port;
-
-	sg = purple_connection_get_protocol_data(gc);
-	if (sg == NULL)
-		return;
-
-	client = sg->client;
-	if (client == NULL)
-		return;
-
-	conn = sg->conn;
-	if (conn == NULL)
-		return;
-
-	server = purple_account_get_string(sg->account, "server",
-					 "silc.silcnet.org");
-	port = purple_account_get_int(sg->account, "port", 706),
-
-	memset(&service, 0, sizeof(service));
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_SERVICE, NULL);
-	service.port = port;
-	g_snprintf(service.address, sizeof(service.address), "%s", server);
-	service.idle = idle;
-	silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_SERVICE,
-				  &service, sizeof(service));
-}
-
-char *silcpurple_status_text(PurpleProtocolClient *ppclient, PurpleBuddy *b)
-{
-	PurpleAccount *account = purple_buddy_get_account(b);
-	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientID *client_id = purple_buddy_get_protocol_data(b);
-	SilcClientEntry client_entry;
-	SilcAttributePayload attr;
-	SilcAttributeMood mood = 0;
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(client, conn, client_id);
-	if (!client_entry)
-		return NULL;
-
-	/* If user is online, we show the mood status, if available.
-	   If user is offline or away that status is indicated. */
-
-	if (client_entry->mode & SILC_UMODE_DETACHED)
-		return g_strdup(_("Detached"));
-	if (client_entry->mode & SILC_UMODE_GONE)
-		return g_strdup(_("Away"));
-	if (client_entry->mode & SILC_UMODE_INDISPOSED)
-		return g_strdup(_("Indisposed"));
-	if (client_entry->mode & SILC_UMODE_BUSY)
-		return g_strdup(_("Busy"));
-	if (client_entry->mode & SILC_UMODE_PAGE)
-		return g_strdup(_("Wake Me Up"));
-	if (client_entry->mode & SILC_UMODE_HYPER)
-		return g_strdup(_("Hyper Active"));
-	if (client_entry->mode & SILC_UMODE_ROBOT)
-		return g_strdup(_("Robot"));
-
-	attr = silcpurple_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_MOOD);
-	if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
-		/* The mood is a bit mask, so we could show multiple moods,
-		   but let's show only one for now. */
-		if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
-			return g_strdup(_("Happy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SAD)
-			return g_strdup(_("Sad"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
-			return g_strdup(_("Angry"));
-		if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
-			return g_strdup(_("Jealous"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
-			return g_strdup(_("Ashamed"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
-			return g_strdup(_("Invincible"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
-			return g_strdup(_("In Love"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
-			return g_strdup(_("Sleepy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_BORED)
-			return g_strdup(_("Bored"));
-		if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
-			return g_strdup(_("Excited"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
-			return g_strdup(_("Anxious"));
-	}
-
-	return NULL;
-}
-
-void silcpurple_tooltip_text(PurpleProtocolClient *ppclient, PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
-{
-	PurpleAccount *account = purple_buddy_get_account(b);
-	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcClientID *client_id = purple_buddy_get_protocol_data(b);
-	SilcClientEntry client_entry;
-	char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
-	char tmp[256];
-
-	/* Get the client entry. */
-	client_entry = silc_client_get_client_by_id(client, conn, client_id);
-	if (!client_entry)
-		return;
-
-	/* TODO: Check whether it's correct to call add_pair_html,
-	         or if we should be using add_pair_plaintext */
-	purple_notify_user_info_add_pair_html(user_info, _("Nickname"), client_entry->nickname);
-	g_snprintf(tmp, sizeof(tmp), "%s@%s", client_entry->username, client_entry->hostname);
-	/* TODO: Check whether it's correct to call add_pair_html,
-	         or if we should be using add_pair_plaintext */
-	purple_notify_user_info_add_pair_html(user_info, _("Username"), tmp);
-	if (client_entry->mode) {
-		memset(tmp, 0, sizeof(tmp));
-		silcpurple_get_umode_string(client_entry->mode,
-					  tmp, sizeof(tmp) - strlen(tmp));
-		purple_notify_user_info_add_pair_plaintext(user_info, _("User Modes"), tmp);
-	}
-
-	silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
-
-	if (statusstr) {
-		/* TODO: Check whether it's correct to call add_pair_html,
-		         or if we should be using add_pair_plaintext */
-		purple_notify_user_info_add_pair_html(user_info, _("Message"), statusstr);
-		g_free(statusstr);
-	}
-
-	if (full) {
-		if (moodstr) {
-			/* TODO: Check whether it's correct to call add_pair_html,
-			         or if we should be using add_pair_plaintext */
-			purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr);
-			g_free(moodstr);
-		}
-
-		if (contactstr) {
-			/* TODO: Check whether it's correct to call add_pair_html,
-			         or if we should be using add_pair_plaintext */
-			purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr);
-			g_free(contactstr);
-		}
-
-		if (langstr) {
-			/* TODO: Check whether it's correct to call add_pair_html,
-			         or if we should be using add_pair_plaintext */
-			purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr);
-			g_free(langstr);
-		}
-
-		if (devicestr) {
-			/* TODO: Check whether it's correct to call add_pair_html,
-			         or if we should be using add_pair_plaintext */
-			purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr);
-			g_free(devicestr);
-		}
-
-		if (tzstr) {
-			/* TODO: Check whether it's correct to call add_pair_html,
-			         or if we should be using add_pair_plaintext */
-			purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr);
-			g_free(tzstr);
-		}
-
-		if (geostr) {
-			/* TODO: Check whether it's correct to call add_pair_html,
-			         or if we should be using add_pair_plaintext */
-			purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr);
-			g_free(geostr);
-		}
-	}
-}
-
-static void
-silcpurple_buddy_kill(PurpleBlistNode *node, gpointer data)
-{
-	PurpleBuddy *b;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_BUDDY(node));
-
-	b = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(purple_buddy_get_account(b));
-	sg = purple_connection_get_protocol_data(gc);
-
-	/* Call KILL */
-	silc_client_command_call(sg->client, sg->conn, NULL, "KILL",
-				 purple_buddy_get_name(b), "Killed by operator", NULL);
-}
-
-typedef struct {
-	SilcPurple sg;
-	SilcClientEntry client_entry;
-} *SilcPurpleBuddyWb;
-
-static void
-silcpurple_buddy_wb(PurpleBlistNode *node, gpointer data)
-{
-	SilcPurpleBuddyWb wb = data;
-	silcpurple_wb_init(wb->sg, wb->client_entry);
-	silc_free(wb);
-}
-
-GList *silcpurple_buddy_menu(PurpleBuddy *buddy)
-{
-	PurpleAccount *account = purple_buddy_get_account(buddy);
-	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClientConnection conn = sg->conn;
-	const char *pkfile = NULL;
-	SilcClientEntry client_entry = NULL;
-	PurpleActionMenu *act;
-	GList *m = NULL;
-	SilcPurpleBuddyWb wb;
-
-	pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key");
-	client_entry = silc_client_get_client_by_id(sg->client,
-						    sg->conn,
-						    purple_buddy_get_protocol_data(buddy));
-
-	if (client_entry &&
-	    silc_client_private_message_key_is_set(sg->client,
-						   sg->conn, client_entry)) {
-		act = purple_action_menu_new(_("Reset IM Key"),
-		                           G_CALLBACK(silcpurple_buddy_resetkey),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	} else {
-		act = purple_action_menu_new(_("IM with Key Exchange"),
-		                           G_CALLBACK(silcpurple_buddy_keyagr),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		act = purple_action_menu_new(_("IM with Password"),
-		                           G_CALLBACK(silcpurple_buddy_privkey_menu),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (pkfile) {
-		act = purple_action_menu_new(_("Show Public Key"),
-		                           G_CALLBACK(silcpurple_buddy_showkey),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-	} else {
-		act = purple_action_menu_new(_("Get Public Key..."),
-		                           G_CALLBACK(silcpurple_buddy_getkey_menu),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (conn && conn->local_entry->mode & SILC_UMODE_ROUTER_OPERATOR) {
-		act = purple_action_menu_new(_("Kill User"),
-		                           G_CALLBACK(silcpurple_buddy_kill),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (client_entry) {
-		wb = silc_calloc(1, sizeof(*wb));
-		wb->sg = sg;
-		wb->client_entry = client_entry;
-		act = purple_action_menu_new(_("Draw On Whiteboard"),
-		                           G_CALLBACK(silcpurple_buddy_wb),
-		                           (void *)wb, NULL);
-		m = g_list_append(m, act);
-	}
-	return m;
-}
-
-void silcpurple_buddy_set_icon(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcMime mime;
-	const gchar *type;
-
-	/* Remove */
-	if (!img) {
-		silc_client_attribute_del(client, conn,
-					  SILC_ATTRIBUTE_USER_ICON, NULL);
-		return;
-	}
-
-	type = purple_image_get_mimetype(img);
-	if (type == NULL)
-		return;
-	if (purple_strequal(purple_image_get_extension(img), "ico"))
-		return;
-
-	/* Add */
-	mime = silc_mime_alloc();
-	if (!mime)
-		return;
-
-	silc_mime_add_field(mime, "Content-Type", type);
-	silc_mime_add_data(mime, purple_image_get_data(img),
-		purple_image_get_data_size(img));
-
-	silc_client_attribute_add(client, conn, SILC_ATTRIBUTE_USER_ICON,
-		mime, sizeof(*mime));
-
-	silc_mime_free(mime);
-}
--- a/libpurple/protocols/silc/chat.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1376 +0,0 @@
-/*
-
-  silcpurple_chat.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include <glib/gi18n-lib.h>
-
-#include "silcpurple.h"
-#include "wb.h"
-
-/***************************** Channel Routines ******************************/
-
-GList *silcpurple_chat_info(PurpleProtocolChat *protocol_chat, PurpleConnection *gc)
-{
-	GList *ci = NULL;
-	PurpleProtocolChatEntry *pce;
-
-	pce = g_new0(PurpleProtocolChatEntry, 1);
-	pce->label = _("_Channel:");
-	pce->identifier = "channel";
-	pce->required = TRUE;
-	ci = g_list_append(ci, pce);
-
-	pce = g_new0(PurpleProtocolChatEntry, 1);
-	pce->label = _("_Passphrase:");
-	pce->identifier = "passphrase";
-	pce->secret = TRUE;
-	ci = g_list_append(ci, pce);
-
-	return ci;
-}
-
-GHashTable *silcpurple_chat_info_defaults(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, const char *chat_name)
-{
-	GHashTable *defaults;
-
-	defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-
-	if (chat_name != NULL)
-		g_hash_table_insert(defaults, "channel", g_strdup(chat_name));
-
-	return defaults;
-}
-
-static void
-silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components);
-
-static void
-silcpurple_chat_getinfo_res(SilcClient client,
-			    SilcClientConnection conn,
-			    SilcStatus status,
-			    SilcDList channels,
-			    void *context)
-{
-	GHashTable *components = context;
-	PurpleConnection *gc = client->application;
-	const char *chname;
-	char tmp[256];
-
-	chname = g_hash_table_lookup(components, "channel");
-	if (!chname)
-		return;
-
-	if (!channels) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("Channel %s does not exist in the network"), chname);
-		purple_notify_error(gc, _("Channel Information"),
-			_("Cannot get channel information"), tmp,
-			purple_request_cpar_from_connection(gc));
-		return;
-	}
-
-	silcpurple_chat_getinfo(gc, components);
-}
-
-
-static void
-silcpurple_chat_getinfo(PurpleConnection *gc, GHashTable *components)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	const char *chname;
-	char tmp[256], *tmp2;
-	GString *s;
-	SilcChannelEntry channel;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-
-	if (!components)
-		return;
-
-	chname = g_hash_table_lookup(components, "channel");
-	if (!chname)
-		return;
-	channel = silc_client_get_channel(sg->client, sg->conn,
-					  (char *)chname);
-	if (!channel) {
-		silc_client_get_channel_resolve(sg->client, sg->conn,
-						(char *)chname,
-						silcpurple_chat_getinfo_res,
-						components);
-		return;
-	}
-
-	s = g_string_new("");
-	tmp2 = g_markup_escape_text(channel->channel_name, -1);
-	g_string_append_printf(s, _("<b>Channel Name:</b> %s"), tmp2);
-	g_free(tmp2);
-	if (channel->user_list && silc_hash_table_count(channel->user_list))
-		g_string_append_printf(s, _("<br><b>User Count:</b> %d"),
-				       (int)silc_hash_table_count(channel->user_list));
-
-	silc_hash_table_list(channel->user_list, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
-			tmp2 = g_markup_escape_text(chu->client->nickname, -1);
-			g_string_append_printf(s, _("<br><b>Channel Founder:</b> %s"),
-					       tmp2);
-			g_free(tmp2);
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-
-	if (channel->cipher)
-		g_string_append_printf(s, _("<br><b>Channel Cipher:</b> %s"),
-				       channel->cipher);
-
-	if (channel->hmac)
-		/* Definition of HMAC: http://en.wikipedia.org/wiki/HMAC */
-		g_string_append_printf(s, _("<br><b>Channel HMAC:</b> %s"),
-				       channel->hmac);
-
-	if (channel->topic) {
-		tmp2 = g_markup_escape_text(channel->topic, -1);
-		g_string_append_printf(s, _("<br><b>Channel Topic:</b><br>%s"), tmp2);
-		g_free(tmp2);
-	}
-
-	if (channel->mode) {
-		g_string_append(s, _("<br><b>Channel Modes:</b> "));
-		silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
-		g_string_append(s, tmp);
-	}
-
-	if (channel->founder_key) {
-		char *fingerprint, *babbleprint;
-		unsigned char *pk;
-		SilcUInt32 pk_len;
-		pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len);
-		if (pk) {
-			fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-			babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-
-			g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint);
-			g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint);
-
-			silc_free(fingerprint);
-			silc_free(babbleprint);
-			silc_free(pk);
-		}
-	}
-
-	purple_notify_formatted(gc, NULL, _("Channel Information"), NULL, s->str, NULL, NULL);
-	g_string_free(s, TRUE);
-}
-
-
-static void
-silcpurple_chat_getinfo_menu(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat = (PurpleChat *)node;
-	PurpleAccount *account = purple_chat_get_account(chat);
-	silcpurple_chat_getinfo(purple_account_get_connection(account),
-			purple_chat_get_components(chat));
-}
-
-
-/************************* Channel Authentication ****************************/
-
-typedef struct {
-	SilcPurple sg;
-	SilcChannelEntry channel;
-	PurpleChat *c;
-	SilcDList pubkeys;
-} *SilcPurpleChauth;
-
-static void
-silcpurple_chat_chpk_add(void *user_data, const char *name)
-{
-	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;
-	SilcPurple sg = sgc->sg;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcPublicKey public_key;
-	SilcBuffer chpks, pk, chidp;
-	unsigned char mode[4];
-	SilcUInt32 m;
-
-	/* Load the public key */
-	if (!silc_pkcs_load_public_key(name, &public_key)) {
-		silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-		silc_dlist_uninit(sgc->pubkeys);
-		silc_free(sgc);
-		purple_notify_error(client->application,
-				    _("Add Channel Public Key"),
-				    _("Could not load public key"), NULL, NULL);
-		return;
-	}
-
-	pk = silc_public_key_payload_encode(public_key);
-	chpks = silc_buffer_alloc_size(2);
-	SILC_PUT16_MSB(1, chpks->head);
-	chpks = silc_argument_payload_encode_one(chpks, pk->data,
-						 silc_buffer_len(pk), 0x00);
-	silc_buffer_free(pk);
-
-	m = sgc->channel->mode;
-	m |= SILC_CHANNEL_MODE_CHANNEL_AUTH;
-
-	/* Send CMODE */
-	SILC_PUT32_MSB(m, mode);
-	chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL);
-	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
-				 silcpurple_command_reply, NULL, 3,
-				 1, chidp->data, silc_buffer_len(chidp),
-				 2, mode, sizeof(mode),
-				 9, chpks->data, silc_buffer_len(chpks));
-	silc_buffer_free(chpks);
-	silc_buffer_free(chidp);
-	if (sgc->pubkeys) {
-	  silc_dlist_start(sgc->pubkeys);
-	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
-		silc_pkcs_public_key_free(public_key);
-	  silc_dlist_uninit(sgc->pubkeys);
-	}
-	silc_free(sgc);
-}
-
-static void
-silcpurple_chat_chpk_cancel(void *user_data, const char *name)
-{
-	SilcPurpleChauth sgc = (SilcPurpleChauth)user_data;
-	SilcPublicKey public_key;
-
-	silcpurple_chat_chauth_show(sgc->sg, sgc->channel, sgc->pubkeys);
-
-	if (sgc->pubkeys) {
-	  silc_dlist_start(sgc->pubkeys);
-	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
-		silc_pkcs_public_key_free(public_key);
-	  silc_dlist_uninit(sgc->pubkeys);
-	}
-	silc_free(sgc);
-}
-
-static void
-silcpurple_chat_chpk_cb(SilcPurpleChauth sgc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = sgc->sg;
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	PurpleRequestField *f;
-	GList *list;
-	SilcPublicKey public_key;
-	SilcBuffer chpks, pk, chidp;
-	SilcUInt16 c = 0, ct;
-	unsigned char mode[4];
-	SilcUInt32 m;
-
-	f = purple_request_fields_get_field(fields, "list");
-	if (!purple_request_field_list_get_selected(f)) {
-		/* Add new public key */
-		purple_request_file(sg->gc, _("Open Public Key..."), NULL, FALSE,
-				    G_CALLBACK(silcpurple_chat_chpk_add),
-				    G_CALLBACK(silcpurple_chat_chpk_cancel),
-				    purple_request_cpar_from_connection(sg->gc), sgc);
-		return;
-	}
-
-	list = purple_request_field_list_get_items(f);
-	chpks = silc_buffer_alloc_size(2);
-
-	for (ct = 0; list; list = list->next, ct++) {
-		PurpleKeyValuePair *item = list->data;
-
-		public_key = purple_request_field_list_get_data(f, item->key);
-		if (purple_request_field_list_is_selected(f, item->key)) {
-			/* Delete this public key */
-			pk = silc_public_key_payload_encode(public_key);
-			chpks = silc_argument_payload_encode_one(chpks, pk->data,
-								 silc_buffer_len(pk), 0x01);
-			silc_buffer_free(pk);
-			c++;
-		}
-	}
-	if (!c) {
-		silc_buffer_free(chpks);
-		return;
-	}
-	SILC_PUT16_MSB(c, chpks->head);
-
-	m = sgc->channel->mode;
-	if (ct == c)
-		m &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH;
-
-	/* Send CMODE */
-	SILC_PUT32_MSB(m, mode);
-	chidp = silc_id_payload_encode(&sgc->channel->id, SILC_ID_CHANNEL);
-	silc_client_command_send(client, conn, SILC_COMMAND_CMODE,
-				 silcpurple_command_reply, NULL, 3,
-				 1, chidp->data, silc_buffer_len(chidp),
-				 2, mode, sizeof(mode),
-				 9, chpks->data, silc_buffer_len(chpks));
-	silc_buffer_free(chpks);
-	silc_buffer_free(chidp);
-	if (sgc->pubkeys) {
-	  silc_dlist_start(sgc->pubkeys);
-	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
-		silc_pkcs_public_key_free(public_key);
-	  silc_dlist_uninit(sgc->pubkeys);
-	}
-	silc_free(sgc);
-}
-
-static void
-silcpurple_chat_chauth_ok(SilcPurpleChauth sgc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = sgc->sg;
-	PurpleRequestField *f;
-	SilcPublicKey public_key;
-	const char *curpass, *val;
-	int set;
-
-	f = purple_request_fields_get_field(fields, "passphrase");
-	val = purple_request_field_string_get_value(f);
-	curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");
-
-	if (!val && curpass)
-		set = 0;
-	else if (val && !curpass)
-		set = 1;
-	else if (val && curpass && !purple_strequal(val, curpass))
-		set = 1;
-	else
-		set = -1;
-
-	if (set == 1) {
-		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-					 sgc->channel->channel_name, "+a", val, NULL);
-		purple_blist_node_set_string((PurpleBlistNode *)sgc->c, "passphrase", val);
-	} else if (set == 0) {
-		silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-					 sgc->channel->channel_name, "-a", NULL);
-		purple_blist_node_remove_setting((PurpleBlistNode *)sgc->c, "passphrase");
-	}
-
-	if (sgc->pubkeys) {
-	  silc_dlist_start(sgc->pubkeys);
-	  while ((public_key = silc_dlist_get(sgc->pubkeys)))
-		silc_pkcs_public_key_free(public_key);
-	  silc_dlist_uninit(sgc->pubkeys);
-	}
-	silc_free(sgc);
-}
-
-void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
-				 SilcDList channel_pubkeys)
-{
-	SilcPublicKey public_key;
-	SilcSILCPublicKey silc_pubkey;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
-	char *fingerprint, *babbleprint;
-	SilcPublicKeyIdentifier ident;
-	char tmp2[1024];
-	const gchar *t;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	SilcPurpleChauth sgc;
-	const char *curpass = NULL;
-
-	sgc = silc_calloc(1, sizeof(*sgc));
-	if (!sgc)
-		return;
-	sgc->sg = sg;
-	sgc->channel = channel;
-
-	fields = purple_request_fields_new();
-
-	if (sgc->c)
-	  curpass = purple_blist_node_get_string((PurpleBlistNode *)sgc->c, "passphrase");
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("passphrase", _("Channel Passphrase"),
-					    curpass, FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_label_new("l1", _("Channel Public Keys List"));
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	t = _("Channel authentication is used to secure the channel from "
-	      "unauthorized access. The authentication may be based on "
-	      "passphrase and digital signatures. If passphrase is set, it "
-	      "is required to be able to join. If channel public keys are set "
-	      "then only users whose public keys are listed are able to join.");
-
-	if (!channel_pubkeys || !silc_dlist_count(channel_pubkeys)) {
-		f = purple_request_field_list_new("list", NULL);
-		purple_request_field_group_add_field(g, f);
-		purple_request_fields(sg->gc, _("Channel Authentication"),
-				      _("Channel Authentication"), t, fields,
-				      _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
-				      _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
-				      purple_request_cpar_from_connection(sg->gc), sgc);
-		if (channel_pubkeys)
-		  silc_dlist_uninit(channel_pubkeys);
-		return;
-	}
-	sgc->pubkeys = channel_pubkeys;
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_list_new("list", NULL);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	silc_dlist_start(channel_pubkeys);
-	while ((public_key = silc_dlist_get(channel_pubkeys))) {
-		pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-		if (!pk)
-			continue;
-		fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4);
-		babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4);
-
-		silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
-		ident = &silc_pubkey->identifier;
-
-		g_snprintf(tmp2, sizeof(tmp2), "%s\n  %s\n  %s",
-			   ident->realname ? ident->realname : ident->username ?
-			   ident->username : "", fingerprint, babbleprint);
-		purple_request_field_list_add_icon(f, tmp2, NULL, public_key);
-
-		silc_free(fingerprint);
-		silc_free(babbleprint);
-	}
-
-	purple_request_field_list_set_multi_select(f, FALSE);
-	purple_request_fields(sg->gc, _("Channel Authentication"),
-			      _("Channel Authentication"), t, fields,
-			      _("Add / Remove"), G_CALLBACK(silcpurple_chat_chpk_cb),
-			      _("OK"), G_CALLBACK(silcpurple_chat_chauth_ok),
-			      purple_request_cpar_from_connection(sg->gc), sgc);
-}
-
-static void
-silcpurple_chat_chauth(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "+C", NULL);
-}
-
-
-/************************** Channel Private Groups **************************/
-
-/* Private groups are "virtual" channels.  They are groups inside a channel.
-   This is implemented by using channel private keys.  By knowing a channel
-   private key user becomes part of that group and is able to talk on that
-   group.  Other users, on the same channel, won't be able to see the
-   messages of that group.  It is possible to have multiple groups inside
-   a channel - and thus having multiple private keys on the channel. */
-
-typedef struct {
-	SilcPurple sg;
-	PurpleChat *c;
-	const char *channel;
-} *SilcPurpleCharPrv;
-
-static void
-silcpurple_chat_prv_add(SilcPurpleCharPrv p, PurpleRequestFields *fields)
-{
-	SilcPurple sg = p->sg;
-	gchar *tmp;
-	PurpleRequestField *f;
-	const char *name, *passphrase, *alias;
-	GHashTable *comp;
-	PurpleGroup *g;
-	PurpleChat *cn;
-
-	f = purple_request_fields_get_field(fields, "name");
-	name = purple_request_field_string_get_value(f);
-	if (!name) {
-		silc_free(p);
-		return;
-	}
-	f = purple_request_fields_get_field(fields, "passphrase");
-	passphrase = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "alias");
-	alias = purple_request_field_string_get_value(f);
-
-	/* Add private group to buddy list */
-	tmp = g_strdup_printf("%s [Private Group]", name);
-	comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
-	g_hash_table_replace(comp, "channel", tmp);
-	g_hash_table_replace(comp, "passphrase", g_strdup(passphrase));
-
-	cn = purple_chat_new(sg->account, alias, comp);
-	g = purple_chat_get_group(p->c);
-	purple_blist_add_chat(cn, g, (PurpleBlistNode *)p->c);
-
-	/* Associate to a real channel */
-	purple_blist_node_set_string((PurpleBlistNode *)cn, "parentch", p->channel);
-
-	/* Join the group */
-	silcpurple_chat_join(NULL, sg->gc, comp);
-
-	silc_free(p);
-}
-
-static void
-silcpurple_chat_prv_cancel(SilcPurpleCharPrv p, PurpleRequestFields *fields)
-{
-	silc_free(p);
-}
-
-static void
-silcpurple_chat_prv(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	SilcPurpleCharPrv p;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	char tmp[512];
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	p = silc_calloc(1, sizeof(*p));
-	if (!p)
-		return;
-	p->sg = sg;
-
-	p->channel = g_hash_table_lookup(purple_chat_get_components(chat), "channel");
-	p->c = purple_blist_find_chat(sg->account, p->channel);
-
-	fields = purple_request_fields_new();
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("name", _("Group Name"),
-					  NULL, FALSE);
-	purple_request_field_group_add_field(g, f);
-
-	f = purple_request_field_string_new("passphrase", _("Passphrase"),
-					  NULL, FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-
-	f = purple_request_field_string_new("alias", _("Alias"),
-					  NULL, FALSE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g_snprintf(tmp, sizeof(tmp),
-		   _("Please enter the %s channel private group name and passphrase."),
-		   p->channel);
-	purple_request_fields(gc, _("Add Channel Private Group"), NULL, tmp, fields,
-			      _("Add"), G_CALLBACK(silcpurple_chat_prv_add),
-			      _("Cancel"), G_CALLBACK(silcpurple_chat_prv_cancel),
-			      purple_request_cpar_from_connection(gc), p);
-}
-
-
-/****************************** Channel Modes ********************************/
-
-static void
-silcpurple_chat_permanent_reset(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "-f", NULL);
-}
-
-static void
-silcpurple_chat_permanent(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-	const char *channel;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (!sg->conn)
-		return;
-
-	/* XXX we should have ability to define which founder
-	   key to use.  Now we use the user's own public key
-	   (default key). */
-
-	/* Call CMODE */
-	channel = g_hash_table_lookup(purple_chat_get_components(chat), "channel");
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE", channel,
-				 "+f", NULL);
-}
-
-static void
-silcpurple_chat_ulimit_cb(PurpleKeyValuePair *s, const char *limit)
-{
-	SilcPurple sg = s->value;
-	SilcChannelEntry channel;
-	guint ulimit = 0;
-
-	channel = silc_client_get_channel(sg->client, sg->conn, s->key);
-	if (!channel)
-		return;
-	if (limit)
-		ulimit = strtoul(limit, NULL, 10);
-
-	if (!limit || !(*limit) || *limit == '0') {
-		if (!limit || ulimit != channel->user_limit) {
-			silc_client_command_call(sg->client, sg->conn, NULL,
-			                         "CMODE", s->key, "-l", NULL);
-		}
-	} else if (ulimit != channel->user_limit) {
-		/* Call CMODE */
-		silc_client_command_call(sg->client, sg->conn, NULL,
-		                         "CMODE", s->key, "+l", limit, NULL);
-	}
-
-	purple_key_value_pair_free(s);
-}
-
-static void
-silcpurple_chat_ulimit(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	PurpleKeyValuePair *s;
-	SilcChannelEntry channel;
-	char *ch;
-	char tmp[32];
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (!sg->conn)
-		return;
-
-	ch = g_hash_table_lookup(purple_chat_get_components(chat), "channel");
-	channel = silc_client_get_channel(sg->client, sg->conn, ch);
-	if (!channel)
-		return;
-
-	s = purple_key_value_pair_new(ch, sg);
-	g_snprintf(tmp, sizeof(tmp), "%d", (int)channel->user_limit);
-	purple_request_input(gc, _("User Limit"), NULL,
-			   _("Set user limit on channel. Set to zero to reset user limit."),
-			   tmp, FALSE, FALSE, NULL,
-			   _("OK"), G_CALLBACK(silcpurple_chat_ulimit_cb),
-			   _("Cancel"), G_CALLBACK(silcpurple_chat_ulimit_cb),
-			   purple_request_cpar_from_connection(gc), s);
-}
-
-static void
-silcpurple_chat_resettopic(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "-t", NULL);
-}
-
-static void
-silcpurple_chat_settopic(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "+t", NULL);
-}
-
-static void
-silcpurple_chat_resetprivate(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "-p", NULL);
-}
-
-static void
-silcpurple_chat_setprivate(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "+p", NULL);
-}
-
-static void
-silcpurple_chat_resetsecret(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "-s", NULL);
-}
-
-static void
-silcpurple_chat_setsecret(PurpleBlistNode *node, gpointer data)
-{
-	PurpleChat *chat;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(PURPLE_IS_CHAT(node));
-
-	chat = (PurpleChat *) node;
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	sg = purple_connection_get_protocol_data(gc);
-
-	silc_client_command_call(sg->client, sg->conn, NULL, "CMODE",
-				 g_hash_table_lookup(purple_chat_get_components(chat), "channel"),
-				 "+s", NULL);
-}
-
-typedef struct {
-	SilcPurple sg;
-	SilcChannelEntry channel;
-} *SilcPurpleChatWb;
-
-static void
-silcpurple_chat_wb(PurpleBlistNode *node, gpointer data)
-{
-	SilcPurpleChatWb wb = data;
-	silcpurple_wb_init_ch(wb->sg, wb->channel);
-	silc_free(wb);
-}
-
-GList *silcpurple_chat_menu(PurpleChat *chat)
-{
-	GHashTable *components = purple_chat_get_components(chat);
-	PurpleConnection *gc = purple_account_get_connection(purple_chat_get_account(chat));
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClientConnection conn = sg->conn;
-	const char *chname = NULL;
-	SilcChannelEntry channel = NULL;
-	SilcChannelUser chu = NULL;
-	SilcUInt32 mode = 0;
-
-	GList *m = NULL;
-	PurpleActionMenu *act;
-
-	if (components)
-		chname = g_hash_table_lookup(components, "channel");
-	if (!chname)
-		return NULL;
-	channel = silc_client_get_channel(sg->client, sg->conn,
-					  (char *)chname);
-	if (channel) {
-		chu = silc_client_on_channel(channel, conn->local_entry);
-		if (chu)
-			mode = chu->mode;
-	}
-
-	if (strstr(chname, "[Private Group]"))
-		return NULL;
-
-	act = purple_action_menu_new(_("Get Info"),
-	                           G_CALLBACK(silcpurple_chat_getinfo_menu),
-	                           NULL, NULL);
-	m = g_list_append(m, act);
-
-	if (chu) {
-		act = purple_action_menu_new(_("Add Private Group"),
-		                           G_CALLBACK(silcpurple_chat_prv),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-	}
-
-	if (chu && mode & SILC_CHANNEL_UMODE_CHANFO) {
-		act = purple_action_menu_new(_("Channel Authentication"),
-		                           G_CALLBACK(silcpurple_chat_chauth),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
-			act = purple_action_menu_new(_("Reset Permanent"),
-			                           G_CALLBACK(silcpurple_chat_permanent_reset),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_action_menu_new(_("Set Permanent"),
-			                           G_CALLBACK(silcpurple_chat_permanent),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (chu && mode & SILC_CHANNEL_UMODE_CHANOP) {
-		act = purple_action_menu_new(_("Set User Limit"),
-		                           G_CALLBACK(silcpurple_chat_ulimit),
-		                           NULL, NULL);
-		m = g_list_append(m, act);
-
-		if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
-			act = purple_action_menu_new(_("Reset Topic Restriction"),
-			                           G_CALLBACK(silcpurple_chat_resettopic),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_action_menu_new(_("Set Topic Restriction"),
-			                           G_CALLBACK(silcpurple_chat_settopic),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
-			act = purple_action_menu_new(_("Reset Private Channel"),
-			                           G_CALLBACK(silcpurple_chat_resetprivate),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_action_menu_new(_("Set Private Channel"),
-			                           G_CALLBACK(silcpurple_chat_setprivate),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-
-		if (channel->mode & SILC_CHANNEL_MODE_SECRET) {
-			act = purple_action_menu_new(_("Reset Secret Channel"),
-			                           G_CALLBACK(silcpurple_chat_resetsecret),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		} else {
-			act = purple_action_menu_new(_("Set Secret Channel"),
-			                           G_CALLBACK(silcpurple_chat_setsecret),
-			                           NULL, NULL);
-			m = g_list_append(m, act);
-		}
-	}
-
-	if (chu && channel) {
-		SilcPurpleChatWb wb;
-		wb = silc_calloc(1, sizeof(*wb));
-		wb->sg = sg;
-		wb->channel = channel;
-		act = purple_action_menu_new(_("Draw On Whiteboard"),
-		                           G_CALLBACK(silcpurple_chat_wb),
-		                           (void *)wb, NULL);
-		m = g_list_append(m, act);
-	}
-
-	return m;
-}
-
-
-/******************************* Joining Etc. ********************************/
-
-char *silcpurple_get_chat_name(PurpleProtocolChat *protocol_chat, GHashTable *data)
-{
-	return g_strdup(g_hash_table_lookup(data, "channel"));
-}
-
-void silcpurple_chat_join(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, GHashTable *data)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	const char *channel, *passphrase, *parentch;
-
-	if (!conn)
-		return;
-
-	channel = g_hash_table_lookup(data, "channel");
-	passphrase = g_hash_table_lookup(data, "passphrase");
-
-	/* Check if we are joining a private group.  Handle it
-	   purely locally as it's not a real channel */
-	if (strstr(channel, "[Private Group]")) {
-		SilcChannelEntry channel_entry;
-		SilcChannelPrivateKey key;
-		PurpleChat *c;
-		SilcPurplePrvgrp grp;
-
-		c = purple_blist_find_chat(sg->account, channel);
-		parentch = purple_blist_node_get_string((PurpleBlistNode *)c, "parentch");
-		if (!parentch)
-			return;
-
-		channel_entry = silc_client_get_channel(sg->client, sg->conn,
-							(char *)parentch);
-		if (!channel_entry ||
-		    !silc_client_on_channel(channel_entry, sg->conn->local_entry)) {
-			char tmp[512];
-			g_snprintf(tmp, sizeof(tmp),
-				   _("You have to join the %s channel before you are "
-				     "able to join the private group"), parentch);
-			purple_notify_error(gc, _("Join Private Group"),
-				_("Cannot join private group"), tmp,
-				purple_request_cpar_from_connection(gc));
-			return;
-		}
-
-		/* Add channel private key */
-		if (!silc_client_add_channel_private_key(client, conn,
-							 channel_entry, channel,
-							 NULL, NULL,
-							 (unsigned char *)passphrase,
-							 strlen(passphrase), &key))
-			return;
-
-		/* Join the group */
-		grp = silc_calloc(1, sizeof(*grp));
-		if (!grp)
-			return;
-		grp->id = ++sg->channel_ids + SILCPURPLE_PRVGRP;
-		grp->chid = SILC_PTR_TO_32(channel_entry->context);
-		grp->parentch = parentch;
-		grp->channel = channel;
-		grp->key = key;
-		sg->grps = g_list_append(sg->grps, grp);
-		purple_serv_got_joined_chat(gc, grp->id, channel);
-		return;
-	}
-
-	/* XXX We should have other properties here as well:
-	   1. whether to try to authenticate to the channel
-	     1a. with default key,
-	     1b. with specific key.
-	   2. whether to try to authenticate to become founder.
-	     2a. with default key,
-	     2b. with specific key.
-
-	   Since now such variety is not possible in the join dialog
-	   we always use -founder and -auth options, which try to
-	   do both 1 and 2 with default keys. */
-
-	/* Call JOIN */
-	if ((passphrase != NULL) && (*passphrase != '\0'))
-		silc_client_command_call(client, conn, NULL, "JOIN",
-					 channel, passphrase, "-auth", "-founder", NULL);
-	else
-		silc_client_command_call(client, conn, NULL, "JOIN",
-					 channel, "-auth", "-founder", NULL);
-}
-
-void silcpurple_chat_invite(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *msg,
-			    const char *name)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-
-	if (!conn)
-		return;
-
-	/* See if we are inviting on a private group.  Invite
-	   to the actual channel */
-	if (id > SILCPURPLE_PRVGRP) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == (gulong)id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		id = prv->chid;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call INVITE */
-	silc_client_command_call(client, conn, NULL, "INVITE",
-				 chu->channel->channel_name,
-				 name, NULL);
-}
-
-void silcpurple_chat_leave(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-	GList *l;
-	SilcPurplePrvgrp prv;
-
-	if (!conn)
-		return;
-
-	/* See if we are leaving a private group */
-	if (id > SILCPURPLE_PRVGRP) {
-		SilcChannelEntry channel;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == (gulong)id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)prv->parentch);
-		if (!channel)
-			return;
-		silc_client_del_channel_private_key(client, conn,
-						    channel, prv->key);
-		silc_free(prv);
-		sg->grps = g_list_delete_link(sg->grps, l);
-		purple_serv_got_chat_left(gc, id);
-		return;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call LEAVE */
-	silc_client_command_call(client, conn, NULL, "LEAVE",
-				 chu->channel->channel_name, NULL);
-
-	purple_serv_got_chat_left(gc, id);
-
-	/* Leave from private groups on this channel as well */
-	for (l = sg->grps; l; l = l->next)
-		if (((SilcPurplePrvgrp)l->data)->chid == (gulong)id) {
-			prv = l->data;
-			silc_client_del_channel_private_key(client, conn,
-							    chu->channel,
-							    prv->key);
-			purple_serv_got_chat_left(gc, prv->id);
-			silc_free(prv);
-			sg->grps = g_list_delete_link(sg->grps, l);
-			if (!sg->grps)
-				break;
-		}
-}
-
-int silcpurple_chat_send(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, PurpleMessage *pmsg)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	SilcChannelEntry channel = NULL;
-	SilcChannelPrivateKey key = NULL;
-	SilcMessageFlags flags;
-	int ret = 0;
-	const gchar *msg = purple_message_get_contents(pmsg);
-	char *msg2, *tmp;
-	gboolean found = FALSE;
-	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
-	SilcDList list;
-	PurpleMessageFlags msgflags = purple_message_get_flags(pmsg);
-
-	if (!msg || !conn)
-		return 0;
-
-	flags = SILC_MESSAGE_FLAG_UTF8;
-
-	tmp = msg2 = purple_unescape_html(msg);
-
-	if (!g_ascii_strncasecmp(msg2, "/me ", 4))
-	{
-		msg2 += 4;
-		if (!*msg2) {
-			g_free(tmp);
-			return 0;
-		}
-		flags |= SILC_MESSAGE_FLAG_ACTION;
-	} else if (strlen(msg) > 1 && msg[0] == '/') {
-		if (!silc_client_command_call(client, conn, msg + 1)) {
-			purple_notify_error(gc, _("Call Command"),
-				_("Cannot call command"), _("Unknown command"),
-				purple_request_cpar_from_connection(gc));
-		}
-		g_free(tmp);
-		return 0;
-	}
-
-
-	if (sign)
-		flags |= SILC_MESSAGE_FLAG_SIGNED;
-
-	/* Get the channel private key if we are sending on
-	   private group */
-	if (id > SILCPURPLE_PRVGRP) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == (gulong)id)
-				break;
-		if (!l) {
-			g_free(tmp);
-			return 0;
-		}
-		prv = l->data;
-		channel = silc_client_get_channel(sg->client, sg->conn,
-						  (char *)prv->parentch);
-		if (!channel) {
-			g_free(tmp);
-			return 0;
-		}
-		key = prv->key;
-	}
-
-	if (!channel) {
-		/* Find channel by id */
-		silc_hash_table_list(conn->local_entry->channels, &htl);
-		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-			if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) {
-				found = TRUE;
-				break;
-			}
-		}
-		silc_hash_table_list_reset(&htl);
-		if (!found) {
-			g_free(tmp);
-			return 0;
-		}
-		channel = chu->channel;
-	}
-
-	/* Check for images */
-	if (msgflags & PURPLE_MESSAGE_IMAGES) {
-		list = silcpurple_image_message(msg, &flags);
-		if (list) {
-			/* Send one or more MIME message.  If more than one, they
-			   are MIME fragments due to over large message */
-			SilcBuffer buf;
-
-			silc_dlist_start(list);
-			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
-				ret =
-			 	silc_client_send_channel_message(client, conn,
-								 channel, key,
-								 flags, sg->sha1hash,
-								 buf->data,
-								 silc_buffer_len(buf));
-			silc_mime_partial_free(list);
-			g_free(tmp);
-
-			if (ret)
-				  purple_serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), msgflags, msg, time(NULL));
-			return ret;
-		}
-	}
-
-	/* Send channel message */
-	ret = silc_client_send_channel_message(client, conn, channel, key,
-					       flags, sg->sha1hash,
-					       (unsigned char *)msg2,
-					       strlen(msg2));
-	if (ret) {
-		purple_serv_got_chat_in(gc, id, purple_connection_get_display_name(gc), msgflags, msg,
-				 time(NULL));
-	}
-	g_free(tmp);
-
-	return ret;
-}
-
-void silcpurple_chat_set_topic(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *topic)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	gboolean found = FALSE;
-
-	if (!conn)
-		return;
-
-	/* See if setting topic on private group.  Set it
-	   on the actual channel */
-	if (id > SILCPURPLE_PRVGRP) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->id == (gulong)id)
-				break;
-		if (!l)
-			return;
-		prv = l->data;
-		id = prv->chid;
-	}
-
-	/* Find channel by id */
-	silc_hash_table_list(conn->local_entry->channels, &htl);
-	while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-		if (SILC_PTR_TO_32(chu->channel->context) == (gulong)id ) {
-			found = TRUE;
-			break;
-		}
-	}
-	silc_hash_table_list_reset(&htl);
-	if (!found)
-		return;
-
-	/* Call TOPIC */
-	silc_client_command_call(client, conn, NULL, "TOPIC",
-				 chu->channel->channel_name, topic, NULL);
-}
-
-PurpleRoomlist *
-silcpurple_roomlist_get_list(PurpleProtocolRoomlist *protocol_roomlist,
-                             PurpleConnection *gc)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-
-	if (!conn)
-		return NULL;
-
-	if (sg->roomlist)
-		g_object_unref(sg->roomlist);
-
-	sg->roomlist_cancelled = FALSE;
-
-	sg->roomlist = purple_roomlist_new(purple_connection_get_account(gc));
-
-	/* Call LIST */
-	silc_client_command_call(client, conn, "LIST");
-
-	purple_roomlist_set_in_progress(sg->roomlist, TRUE);
-
-	return sg->roomlist;
-}
-
-void
-silcpurple_roomlist_cancel(PurpleProtocolRoomlist *protocol_roomlist,
-                           PurpleRoomlist *list)
-{
-	PurpleAccount *account = purple_roomlist_get_account(list);
-	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg;
-
-	if (!gc)
-		return;
-	sg = purple_connection_get_protocol_data(gc);
-
-	purple_roomlist_set_in_progress(list, FALSE);
-	if (sg->roomlist == list) {
-		g_object_unref(sg->roomlist);
-		sg->roomlist = NULL;
-		sg->roomlist_cancelled = TRUE;
-	}
-}
--- a/libpurple/protocols/silc/ft.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,546 +0,0 @@
-/*
-
-  silcpurple_ft.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include <glib/gi18n-lib.h>
-#include <glib/gstdio.h>
-
-#include "silcpurple.h"
-#include "ft.h"
-
-/****************************** File Transfer ********************************/
-
-/* This implements the secure file transfer protocol (SFTP) using the SILC
-   SFTP library implementation.  The API we use from the SILC Toolkit is the
-   SILC Client file transfer API, as it provides a simple file transfer we
-   need in this case.  We could use the SILC SFTP API directly, but it would
-   be an overkill since we'd effectively re-implement the file transfer what
-   the SILC Client's file transfer API already provides.
-
-   From Purple we do NOT use the FT API to do the transfer as it is very limiting.
-   In fact it does not suite to file transfers like SFTP at all.  For example,
-   it assumes that read operations are synchronous what they are not in SFTP.
-   It also assumes that the file transfer socket is to be handled by the Purple
-   eventloop, and this naturally is something we don't want to do in case of
-   SILC Toolkit.  The FT API suites well to purely stream based file transfers
-   like HTTP GET and similar.
-
-   For this reason, we directly access the Purple GKT FT API and hack the FT
-   API to merely provide the user interface experience and all the magic
-   is done in the SILC Toolkit.  Ie. we update the statistics information in
-   the FT API for user interface, and that's it.  A bit dirty but until the
-   FT API gets better this is the way to go.  Good thing that FT API allowed
-   us to do this. */
-
-struct _SilcPurpleXfer {
-	PurpleXfer parent;
-
-	SilcPurple sg;
-	SilcClientEntry client_entry;
-	SilcUInt32 session_id;
-	char *hostname;
-	SilcUInt16 port;
-
-	SilcClientFileName completion;
-	void *completion_context;
-};
-
-G_DEFINE_DYNAMIC_TYPE(SilcPurpleXfer, silcpurple_xfer, PURPLE_TYPE_XFER);
-
-static void
-silcpurple_ftp_monitor(SilcClient client,
-		     SilcClientConnection conn,
-		     SilcClientMonitorStatus status,
-		     SilcClientFileError error,
-		     SilcUInt64 offset,
-		     SilcUInt64 filesize,
-		     SilcClientEntry client_entry,
-		     SilcUInt32 session_id,
-		     const char *filepath,
-		     void *context)
-{
-	PurpleXfer *xfer = context;
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-	PurpleConnection *gc = spx->sg->gc;
-	char tmp[256];
-
-	if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) {
-		/* All started sessions terminate here */
-		g_object_unref(xfer);
-		return;
-	}
-
-	if (status == SILC_CLIENT_FILE_MONITOR_DISCONNECT) {
-		purple_notify_error(gc, _("Secure File Transfer"), _("Error "
-			"during file transfer"), _("Remote disconnected"),
-			purple_request_cpar_from_connection(gc));
-		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
-		silc_client_file_close(client, conn, session_id);
-		return;
-	}
-
-	if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT)
-		return;
-
-	if (status == SILC_CLIENT_FILE_MONITOR_ERROR) {
-		if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) {
-			g_snprintf(tmp, sizeof(tmp), "No such file %s",
-				   filepath ? filepath : "[N/A]");
-			purple_notify_error(gc, _("Secure File Transfer"),
-				_("Error during file transfer"), tmp,
-				purple_request_cpar_from_connection(gc));
-		} else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-				_("Error during file transfer"),
-				_("Permission denied"),
-				purple_request_cpar_from_connection(gc));
-		} else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-				_("Error during file transfer"),
-				_("Key agreement failed"),
-				purple_request_cpar_from_connection(gc));
-		} else if (error == SILC_CLIENT_FILE_TIMEOUT) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-				_("Error during file transfer"),
-				_("Connection timed out"),
-				purple_request_cpar_from_connection(gc));
-		} else if (error == SILC_CLIENT_FILE_CONNECT_FAILED) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-				_("Error during file transfer"),
-				_("Creating connection failed"),
-				purple_request_cpar_from_connection(gc));
-		} else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) {
-			purple_notify_error(gc, _("Secure File Transfer"),
-				_("Error during file transfer"),
-				_("File transfer session does not exist"),
-				purple_request_cpar_from_connection(gc));
-		}
-		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
-		silc_client_file_close(client, conn, session_id);
-		return;
-	}
-
-	/* Update file transfer UI */
-	if (!offset && filesize) {
-		purple_xfer_set_size(xfer, filesize);
-	}
-	if (offset && filesize) {
-		purple_xfer_set_bytes_sent(xfer, offset);
-	}
-
-	if (status == SILC_CLIENT_FILE_MONITOR_SEND ||
-	    status == SILC_CLIENT_FILE_MONITOR_RECEIVE) {
-		if (offset == filesize) {
-			/* Download finished */
-			purple_xfer_set_completed(xfer, TRUE);
-			silc_client_file_close(client, conn, session_id);
-		}
-	}
-}
-
-static void
-silcpurple_ftp_cancel(PurpleXfer *xfer)
-{
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-
-	if (!spx) {
-		return;
-	}
-
-	purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
-	silc_client_file_close(spx->sg->client, spx->sg->conn, spx->session_id);
-}
-
-static void
-silcpurple_ftp_ask_name_ok(PurpleXfer *xfer)
-{
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-	const char *name;
-
-	if (!spx) {
-		return;
-	}
-
-	name = purple_xfer_get_local_filename(xfer);
-	g_unlink(name);
-	spx->completion(name, spx->completion_context);
-}
-
-static void
-silcpurple_ftp_ask_name(SilcClient client,
-		      SilcClientConnection conn,
-		      SilcUInt32 session_id,
-		      const char *remote_filename,
-		      SilcClientFileName completion,
-		      void *completion_context,
-		      void *context)
-{
-	PurpleXfer *xfer = context;
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-
-	spx->completion = completion;
-	spx->completion_context = completion_context;
-
-	/* Request to save the file */
-	purple_xfer_set_filename(xfer, remote_filename);
-	purple_xfer_request(xfer);
-}
-
-static void
-silcpurple_ftp_request_result(PurpleXfer *xfer)
-{
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-	SilcClientFileError status;
-	PurpleConnection *gc = spx->sg->gc;
-	SilcClientConnectionParams params;
-	gboolean local = spx->hostname ? FALSE : TRUE;
-	char *local_ip = NULL, *remote_ip = NULL;
-	SilcSocket sock;
-
-	if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_ACCEPTED) {
-		return;
-	}
-
-	silc_socket_stream_get_info(silc_packet_stream_get_stream(spx->sg->conn->stream),
-				    &sock, NULL, NULL, NULL);
-
-	if (local) {
-		/* Do the same magic what we do with key agreement (see silcpurple_buddy.c)
-		   to see if we are behind NAT. */
-		if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) {
-			/* Check if the IP is private */
-			if (silcpurple_ip_is_private(local_ip)) {
-				local = TRUE;
-				/* Local IP is private, resolve the remote server IP to see whether
-				   we are talking to Internet or just on LAN. */
-				if (silc_net_check_host_by_sock(sock, NULL,
-								&remote_ip))
-				  if (silcpurple_ip_is_private(remote_ip))
-				    /* We assume we are in LAN.  Let's provide the connection point. */
-				    local = TRUE;
-			}
-		}
-
-		if (local && !local_ip)
-		  local_ip = silc_net_localip();
-	}
-
-	memset(&params, 0, sizeof(params));
-	params.timeout_secs = 60;
-	if (local)
-	  /* Provide connection point */
-	  params.local_ip = local_ip;
-
-	/* Start the file transfer */
-	status = silc_client_file_receive(spx->sg->client, spx->sg->conn,
-	                                  &params, spx->sg->public_key,
-	                                  spx->sg->private_key,
-	                                  silcpurple_ftp_monitor, xfer,
-	                                  NULL, spx->session_id,
-	                                  silcpurple_ftp_ask_name, xfer);
-	switch (status) {
-	case SILC_CLIENT_FILE_OK:
-		silc_free(local_ip);
-		silc_free(remote_ip);
-		return;
-		break;
-
-	case SILC_CLIENT_FILE_UNKNOWN_SESSION:
-		purple_notify_error(gc, _("Secure File Transfer"),
-			_("No file transfer session active"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	case SILC_CLIENT_FILE_ALREADY_STARTED:
-		purple_notify_error(gc, _("Secure File Transfer"),
-			_("File transfer already started"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-
-	case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED:
-		purple_notify_error(gc, _("Secure File Transfer"),
-			_("Could not perform key agreement for file transfer"),
-			NULL, purple_request_cpar_from_connection(gc));
-		break;
-
-	default:
-		purple_notify_error(gc, _("Secure File Transfer"),
-			_("Could not start the file transfer"), NULL,
-			purple_request_cpar_from_connection(gc));
-		break;
-	}
-
-	/* Error */
-	g_object_unref(xfer);
-	silc_free(local_ip);
-	silc_free(remote_ip);
-}
-
-static void
-silcpurple_ftp_request_init(PurpleXfer *xfer)
-{
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-
-	if (spx->completion) {
-		silcpurple_ftp_ask_name_ok(xfer);
-	} else {
-		silcpurple_ftp_request_result(xfer);
-	}
-}
-
-static void
-silcpurple_ftp_request_denied(PurpleXfer *xfer)
-{
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-
-	if (!spx) {
-		return;
-	}
-
-	/* Cancel the transmission */
-	if (spx->completion) {
-		spx->completion(NULL, spx->completion_context);
-	}
-	silc_client_file_close(spx->sg->client, spx->sg->conn, spx->session_id);
-}
-
-void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn,
-			    SilcClientEntry client_entry, SilcUInt32 session_id,
-			    const char *hostname, SilcUInt16 port)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcPurpleXfer *spx;
-
-	spx = g_object_new(SILCPURPLE_TYPE_XFER,
-	                   "account", sg->account,
-	                   "type", PURPLE_XFER_TYPE_RECEIVE,
-	                   "remote-user", client_entry->nickname,
-	                   NULL);
-
-	spx->sg = sg;
-	spx->client_entry = client_entry;
-	spx->session_id = session_id;
-	spx->hostname = g_strdup(hostname);
-	spx->port = port;
-
-	purple_xfer_start(PURPLE_XFER(spx), -1, hostname, port);
-
-	/* File transfer request */
-	purple_xfer_request(PURPLE_XFER(spx));
-}
-
-static void
-silcpurple_ftp_send_cancel(PurpleXfer *xfer)
-{
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-
-	if (!spx) {
-		return;
-	}
-
-	/* This call will free all resources */
-	silc_client_file_close(spx->sg->client, spx->sg->conn, spx->session_id);
-}
-
-static void
-silcpurple_ftp_send(PurpleXfer *xfer)
-{
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(xfer);
-	const char *name;
-	char *local_ip = NULL, *remote_ip = NULL;
-	gboolean local = TRUE;
-	SilcClientConnectionParams params;
-	SilcSocket sock;
-
-	if (!spx) {
-		return;
-	}
-
-	name = purple_xfer_get_local_filename(xfer);
-
-	silc_socket_stream_get_info(silc_packet_stream_get_stream(spx->sg->conn->stream),
-				    &sock, NULL, NULL, NULL);
-
-	/* Do the same magic what we do with key agreement (see silcpurple_buddy.c)
-	   to see if we are behind NAT. */
-	if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) {
-		/* Check if the IP is private */
-		if (silcpurple_ip_is_private(local_ip)) {
-			local = FALSE;
-			/* Local IP is private, resolve the remote server IP to see whether
-			   we are talking to Internet or just on LAN. */
-			if (silc_net_check_host_by_sock(sock, NULL,
-							&remote_ip))
-				if (silcpurple_ip_is_private(remote_ip))
-					/* We assume we are in LAN.  Let's provide the connection point. */
-					local = TRUE;
-		}
-	}
-
-	if (local && !local_ip)
-		local_ip = silc_net_localip();
-
-	memset(&params, 0, sizeof(params));
-	params.timeout_secs = 60;
-	if (local)
-	  /* Provide connection point */
-	  params.local_ip = local_ip;
-
-	/* Send the file */
-	silc_client_file_send(spx->sg->client, spx->sg->conn,
-	                      spx->client_entry, &params,
-	                      spx->sg->public_key, spx->sg->private_key,
-	                      silcpurple_ftp_monitor, xfer,
-	                      name, &spx->session_id);
-
-	silc_free(local_ip);
-	silc_free(remote_ip);
-}
-
-static void
-silcpurple_ftp_send_file_resolved(SilcClient client,
-				  SilcClientConnection conn,
-				  SilcStatus status,
-				  SilcDList clients,
-				  void *context)
-{
-	PurpleConnection *gc = client->application;
-	char tmp[256];
-
-	if (!clients) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("User %s is not present in the network"),
-			   (const char *)context);
-		purple_notify_error(gc, _("Secure File Transfer"),
-			_("Cannot send file"), tmp,
-			purple_request_cpar_from_connection(gc));
-		g_free(context);
-		return;
-	}
-
-	silcpurple_ftp_send_file(NULL, client->application, (const char *)context, NULL);
-	g_free(context);
-}
-
-PurpleXfer *silcpurple_ftp_new_xfer(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcDList clients;
-	SilcClientEntry client_entry;
-	SilcPurpleXfer *spx;
-
-	g_return_val_if_fail(name != NULL, NULL);
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, name, FALSE);
-	if (!clients) {
-		silc_client_get_clients(client, conn, name, NULL,
-					silcpurple_ftp_send_file_resolved,
-					g_strdup(name));
-		return NULL;
-	}
-	silc_dlist_start(clients);
-
-	client_entry = silc_dlist_get(clients);
-	silc_free(clients);
-
-	spx = g_object_new(SILCPURPLE_TYPE_XFER,
-	                   "account", sg->account,
-	                   "type", PURPLE_XFER_TYPE_SEND,
-	                   "remote-user", client_entry->nickname,
-	                   NULL);
-
-	spx->sg = sg;
-	spx->client_entry = client_entry;
-
-	return PURPLE_XFER(spx);
-}
-
-void silcpurple_ftp_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name, const char *file)
-{
-	PurpleXfer *xfer = silcpurple_ftp_new_xfer(prplxfer, gc, name);
-
-	g_return_if_fail(xfer != NULL);
-
-	/* Choose file to send */
-	if (file)
-		purple_xfer_request_accepted(xfer, file);
-	else
-		purple_xfer_request(xfer);
-}
-
-static void
-silcpurple_ftp_init(PurpleXfer *xfer)
-{
-	switch(purple_xfer_get_xfer_type(xfer)) {
-	case PURPLE_XFER_TYPE_SEND:
-		silcpurple_ftp_send(xfer);
-		break;
-	case PURPLE_XFER_TYPE_RECEIVE:
-		silcpurple_ftp_request_init(xfer);
-		break;
-	case PURPLE_XFER_TYPE_UNKNOWN:
-		g_return_if_reached();
-		break;
-	}
-}
-
-/******************************************************************************
- * GObject Implementation
- *****************************************************************************/
-static void
-silcpurple_xfer_init(SilcPurpleXfer *spx)
-{
-}
-
-static void
-silcpurple_xfer_finalize(GObject *obj) {
-	SilcPurpleXfer *spx = SILCPURPLE_XFER(obj);
-
-	g_free(spx->hostname);
-
-	G_OBJECT_CLASS(silcpurple_xfer_parent_class)->finalize(obj);
-}
-
-static void
-silcpurple_xfer_class_init(SilcPurpleXferClass *klass) {
-	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-	PurpleXferClass *xfer_class = PURPLE_XFER_CLASS(klass);
-
-	obj_class->finalize = silcpurple_xfer_finalize;
-
-	xfer_class->init = silcpurple_ftp_init;
-	xfer_class->request_denied = silcpurple_ftp_request_denied;
-	xfer_class->cancel_send = silcpurple_ftp_send_cancel;
-	xfer_class->cancel_recv = silcpurple_ftp_cancel;
-}
-
-static void
-silcpurple_xfer_class_finalize(SilcPurpleXferClass *klass) {
-}
-
-/******************************************************************************
- * Public API
- *****************************************************************************/
-void
-silcpurple_xfer_register(GTypeModule *module) {
-	silcpurple_xfer_register_type(module);
-}
--- a/libpurple/protocols/silc/ft.h	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Purple - Internet Messaging Library
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * 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, see <https://www.gnu.org/licenses/>.
- */
-
-#ifndef PURPLE_SILC_FT_H
-#define PURPLE_SILC_FT_H
-
-#include <purple.h>
-
-G_BEGIN_DECLS
-
-#define SILCPURPLE_TYPE_XFER (silcpurple_xfer_get_type())
-G_DECLARE_FINAL_TYPE(SilcPurpleXfer, silcpurple_xfer, SILCPURPLE, XFER, PurpleXfer);
-
-void silcpurple_xfer_register(GTypeModule *module);
-
-G_END_DECLS
-
-#endif /* PURPLE_SILC_FT_H */
--- a/libpurple/protocols/silc/meson.build	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-SILC_SOURCES = [
-	'buddy.c',
-	'chat.c',
-	'ft.c',
-	'ft.h',
-	'ops.c',
-	'pk.c',
-	'silc.c',
-	'silcpurple.h',
-	'util.c',
-	'wb.c',
-	'wb.h'
-]
-
-if DYNAMIC_SILC
-	silc_resources = gnome.compile_resources('silcresource',
-		'resources/silc.gresource.xml',
-		source_dir : 'resources',
-		c_name : 'silc')
-	SILC_SOURCES += silc_resources
-
-	silc_prpl = shared_library('silcpurple', SILC_SOURCES,
-	    c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-SILC"'],
-	    dependencies : [silc, libpurple_dep, glib],
-	    install : true, install_dir : PURPLE_PLUGINDIR)
-
-	devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
-endif
--- a/libpurple/protocols/silc/ops.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1825 +0,0 @@
-/*
-
-  silcpurple_ops.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include <glib/gi18n-lib.h>
-#include <glib/gstdio.h>
-
-#include "libpurple/glibcompat.h"
-
-#include "silcpurple.h"
-#include "wb.h"
-
-static void
-silc_channel_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcChannelEntry channel,
-		     SilcMessagePayload payload,
-		     SilcChannelPrivateKey key, SilcMessageFlags flags,
-		     const unsigned char *message,
-		     SilcUInt32 message_len);
-static void
-silc_private_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcMessagePayload payload,
-		     SilcMessageFlags flags, const unsigned char *message,
-		     SilcUInt32 message_len);
-static void
-silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-		    SilcAskPassphrase completion, void *context);
-
-/* Message sent to the application by library. `conn' associates the
-   message to a specific connection.  `conn', however, may be NULL.
-   The `type' indicates the type of the message sent by the library.
-   The application can for example filter the message according the
-   type. */
-
-void silc_say(SilcClient client, SilcClientConnection conn,
-	      SilcClientMessageType type, char *msg, ...)
-{
-	char tmp[256];
-	va_list va;
-	PurpleConnection *gc = NULL;
-	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
-
-	va_start(va, msg);
-	silc_vsnprintf(tmp, sizeof(tmp), msg, va);
-	va_end(va);
-
-	if (type != SILC_CLIENT_MESSAGE_ERROR) {
-		purple_debug_misc("silc", "silc_say (%d) %s\n", type, tmp);
-		return;
-	}
-
-	purple_debug_error("silc", "silc_say error: %s\n", tmp);
-
-	if (purple_strequal(tmp, "Authentication failed"))
-		reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
-
-	if (client != NULL)
-		gc = client->application;
-
-	if (gc != NULL)
-		purple_connection_error(gc, reason, tmp);
-	else
-		purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp, NULL);
-}
-
-/* Processes incoming MIME message.  Can be private message or channel
-   message.  Returns TRUE if the message `mime' was displayed. */
-
-static SilcBool
-silcpurple_mime_message(SilcClient client, SilcClientConnection conn,
-			SilcClientEntry sender, SilcChannelEntry channel,
-			SilcMessagePayload payload, SilcChannelPrivateKey key,
-			SilcMessageFlags flags, SilcMime mime,
-			gboolean recursive)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	const char *type;
-	const unsigned char *data;
-	SilcUInt32 data_len;
-	PurpleMessageFlags cflags = 0;
-	PurpleConversation *chat = NULL;
-	PurpleConversationManager *manager = NULL;
-	SilcBool ret = FALSE;
-
-	if (!mime)
-		return FALSE;
-
-	/* Check for fragmented MIME message */
-	if (silc_mime_is_partial(mime)) {
-		if (!sg->mimeass)
-			sg->mimeass = silc_mime_assembler_alloc();
-
-		/* Defragment */
-		mime = silc_mime_assemble(sg->mimeass, mime);
-		if (!mime)
-			/* More fragments to come */
-			return FALSE;
-
-		/* Process the complete message */
-		return silcpurple_mime_message(client, conn, sender, channel,
-					       payload, key, flags, mime,
-					       FALSE);
-	}
-
-	/* Check for multipart message */
-	if (silc_mime_is_multipart(mime)) {
-		SilcMime p;
-		const char *mtype;
-		SilcDList parts = silc_mime_get_multiparts(mime, &mtype);
-
-		if (purple_strequal(mtype, "mixed")) {
-			/* Contains multiple messages */
-			silc_dlist_start(parts);
-			while ((p = silc_dlist_get(parts)) != SILC_LIST_END) {
-			  /* Recursively process parts */
-			  ret = silcpurple_mime_message(client, conn, sender, channel,
-							payload, key, flags, p, TRUE);
-			}
-		}
-
-		if (purple_strequal(mtype, "alternative")) {
-			/* Same message in alternative formats.  Kopete sends
-			   these.  Go in order from last to first. */
-			silc_dlist_end(parts);
-			while ((p = silc_dlist_get(parts)) != SILC_LIST_END) {
-			  /* Go through the alternatives and display the first
-			     one we support. */
-			  if (silcpurple_mime_message(client, conn, sender, channel,
-						      payload, key, flags, p, TRUE)) {
-			    ret = TRUE;
-			    break;
-			  }
-			}
-		}
-
-		goto out;
-	}
-
-	/* Get content type and MIME data */
-	type = silc_mime_get_field(mime, "Content-Type");
-	if (!type)
-		goto out;
-	data = silc_mime_get_data(mime, &data_len);
-	if (!data)
-		goto out;
-
-	/* Process according to content type */
-
-	/* Plain text */
-	if (strstr(type, "text/plain")) {
-		/* Default is UTF-8, don't check for other charsets */
-		if (!strstr(type, "utf-8"))
-			goto out;
-
-		if (channel)
-			silc_channel_message(client, conn, sender, channel,
-					     payload, key,
-					     SILC_MESSAGE_FLAG_UTF8, data,
-					     data_len);
-		else
-			silc_private_message(client, conn, sender, payload,
-					     SILC_MESSAGE_FLAG_UTF8, data,
-					     data_len);
-		ret = TRUE;
-		goto out;
-	}
-
-	manager = purple_conversation_manager_get_default();
-
-	/* Image */
-	if (g_str_has_prefix(type, "image/")) {
-		char tmp[32];
-		PurpleImage *img;
-		guint img_id;
-
-		/* Get channel chat (if message is for channel) */
-		if (key && channel) {
-			GList *l;
-			SilcPurplePrvgrp prv;
-
-			for (l = sg->grps; l; l = l->next)
-				if (((SilcPurplePrvgrp)l->data)->key == key) {
-					prv = l->data;
-					chat = purple_conversation_manager_find_chat(manager,
-					                                             sg->account,
-					                                             prv->channel);
-					break;
-				}
-		}
-		if (channel && !chat) {
-			chat = purple_conversation_manager_find_chat(manager, sg->account,
-			                                             channel->channel_name);
-		}
-
-		if (channel && !chat) {
-			goto out;
-		}
-
-		img = purple_image_new_from_data(data, data_len);
-		if (!img)
-			goto out;
-		img_id = purple_image_store_add_temporary(img);
-		if (!img_id) {
-			g_clear_object(&img);
-			goto out;
-		}
-
-		cflags |= PURPLE_MESSAGE_IMAGES | PURPLE_MESSAGE_RECV;
-		g_snprintf(tmp, sizeof(tmp), "<img src=\""
-			PURPLE_IMAGE_STORE_PROTOCOL "%u\">", img_id);
-
-		if (channel) {
-			purple_serv_got_chat_in(gc,
-				purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)),
-				sender->nickname, cflags, tmp, time(NULL));
-		} else {
-			purple_serv_got_im(gc, sender->nickname,
-				tmp, cflags, time(NULL));
-		}
-
-		g_clear_object(&img);
-
-		goto out;
-	}
-
-	/* Whiteboard message */
-	if (strstr(type, "application/x-wb") &&
-	    !purple_account_get_bool(sg->account, "block-wb", FALSE)) {
-		if (channel)
-			silcpurple_wb_receive_ch(client, conn, sender, channel,
-					       payload, flags, data, data_len);
-		else
-			silcpurple_wb_receive(client, conn, sender, payload,
-					      flags, data, data_len);
-		ret = TRUE;
-		goto out;
-	}
-
- out:
-	if (!recursive)
-		silc_mime_free(mime);
-	return ret;
-}
-
-/* Message for a channel. The `sender' is the sender of the message
-   The `channel' is the channel. The `message' is the message.  Note
-   that `message' maybe NULL.  The `flags' indicates message flags
-   and it is used to determine how the message can be interpreted
-   (like it may tell the message is multimedia message). */
-
-static void
-silc_channel_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcChannelEntry channel,
-		     SilcMessagePayload payload,
-		     SilcChannelPrivateKey key, SilcMessageFlags flags,
-		     const unsigned char *message,
-		     SilcUInt32 message_len)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	PurpleConversation *chat = NULL;
-	PurpleConversationManager *manager = NULL;
-	char *msg, *tmp;
-
-	if (!message)
-		return;
-
-	manager = purple_conversation_manager_get_default();
-
-	if (key) {
-		GList *l;
-		SilcPurplePrvgrp prv;
-
-		for (l = sg->grps; l; l = l->next)
-			if (((SilcPurplePrvgrp)l->data)->key == key) {
-				prv = l->data;
-				chat = purple_conversation_manager_find_chat(manager, sg->account,
-				                                             prv->channel);
-				break;
-			}
-	}
-	if (!chat) {
-		chat = purple_conversation_manager_find_chat(manager, sg->account,
-		                                             channel->channel_name);
-	}
-
-	if (!chat) {
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_SIGNED &&
-	    purple_account_get_bool(sg->account, "sign-verify", FALSE)) {
-		/* XXX */
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_DATA) {
-		/* Process MIME message */
-		SilcMime mime;
-		mime = silc_mime_decode(NULL, message, message_len);
-		silcpurple_mime_message(client, conn, sender, channel, payload,
-					key, flags, mime, FALSE);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_ACTION) {
-		msg = g_strdup_printf("/me %s",
-				      (const char *)message);
-		if (!msg)
-			return;
-
-		tmp = g_markup_escape_text(msg, -1);
-		/* Send to Purple */
-		purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)),
-			sender->nickname, PURPLE_MESSAGE_RECV, tmp, time(NULL));
-		g_free(tmp);
-		g_free(msg);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_NOTICE) {
-		msg = g_strdup_printf("(notice) <I>%s</I> %s",
-				      sender->nickname, (const char *)message);
-		if (!msg)
-			return;
-
-		/* Send to Purple */
-		purple_conversation_write_system_message(
-			PURPLE_CONVERSATION(chat), msg, 0);
-		g_free(msg);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_UTF8) {
-		const char *msg = (const char *)message;
-		char *salvaged = NULL;
-		if (!g_utf8_validate((const char *)message, -1, NULL)) {
-			salvaged = g_utf8_make_valid((const char *)message, -1);
-			msg = salvaged;
-		}
-		tmp = g_markup_escape_text(msg, -1);
-		/* Send to Purple */
-		purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)),
-			sender->nickname, PURPLE_MESSAGE_RECV, tmp, time(NULL));
-		g_free(salvaged);
-		g_free(tmp);
-	}
-}
-
-
-/* Private message to the client. The `sender' is the sender of the
-   message. The message is `message'and maybe NULL.  The `flags'
-   indicates message flags  and it is used to determine how the message
-   can be interpreted (like it may tell the message is multimedia
-   message). */
-
-static void
-silc_private_message(SilcClient client, SilcClientConnection conn,
-		     SilcClientEntry sender, SilcMessagePayload payload,
-		     SilcMessageFlags flags, const unsigned char *message,
-		     SilcUInt32 message_len)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	PurpleConversation *convo;
-	PurpleConversationManager *manager = NULL;
-	char *msg, *tmp;
-
-	if (!message) {
-		return;
-	}
-
-	manager = purple_conversation_manager_get_default();
-	/* XXX - Should this be PURPLE_CONV_TYPE_IM? */
-	convo = purple_conversation_manager_find(manager, sg->account,
-	                                         sender->nickname);
-
-	if (flags & SILC_MESSAGE_FLAG_SIGNED &&
-	    purple_account_get_bool(sg->account, "sign-verify", FALSE)) {
-		/* XXX */
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_DATA) {
-		/* Process MIME message */
-		SilcMime mime;
-		mime = silc_mime_decode(NULL, message, message_len);
-		silcpurple_mime_message(client, conn, sender, NULL, payload,
-				      NULL, flags, mime, FALSE);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_ACTION && convo) {
-		msg = g_strdup_printf("/me %s",
-				      (const char *)message);
-		if (!msg)
-			return;
-
-		/* Send to Purple */
-		tmp = g_markup_escape_text(msg, -1);
-		purple_serv_got_im(gc, sender->nickname, tmp, 0, time(NULL));
-		g_free(msg);
-		g_free(tmp);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_NOTICE && convo) {
-		msg = g_strdup_printf("(notice) <I>%s</I> %s",
-				      sender->nickname, (const char *)message);
-		if (!msg)
-			return;
-
-		/* Send to Purple */
-		purple_conversation_write_system_message(convo, msg, 0);
-		g_free(msg);
-		return;
-	}
-
-	if (flags & SILC_MESSAGE_FLAG_UTF8) {
-		const char *msg = (const char *)message;
-		char *salvaged = NULL;
-		if (!g_utf8_validate((const char *)message, -1, NULL)) {
-			salvaged = g_utf8_make_valid((const char *)message, -1);
-			msg = salvaged;
-		}
-		tmp = g_markup_escape_text(msg, -1);
-		/* Send to Purple */
-		purple_serv_got_im(gc, sender->nickname, tmp, 0, time(NULL));
-		g_free(salvaged);
-		g_free(tmp);
-	}
-}
-
-
-/* Notify message to the client. The notify arguments are sent in the
-   same order as servers sends them. The arguments are same as received
-   from the server except for ID's.  If ID is received application receives
-   the corresponding entry to the ID. For example, if Client ID is received
-   application receives SilcClientEntry.  Also, if the notify type is
-   for channel the channel entry is sent to application (even if server
-   does not send it because client library gets the channel entry from
-   the Channel ID in the packet's header). */
-
-static void
-silc_notify(SilcClient client, SilcClientConnection conn,
-	    SilcNotifyType type, ...)
-{
-	va_list va;
-	PurpleConnection *gc = client->application;
-	PurpleConversationManager *manager;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	PurpleAccount *account = purple_connection_get_account(gc);
-	PurpleConversation *chat;
-	SilcClientEntry client_entry, client_entry2;
-	SilcChannelEntry channel;
-	SilcServerEntry server_entry;
-	SilcIdType idtype;
-	void *entry;
-	SilcUInt32 mode;
-	SilcHashTableList htl;
-	SilcChannelUser chu;
-	char buf[512], buf2[512], *tmp, *name;
-	SilcNotifyType notify;
-	PurpleBuddy *b;
-	SilcDList list;
-
-	va_start(va, type);
-	memset(buf, 0, sizeof(buf));
-
-	manager = purple_conversation_manager_get_default();
-
-	switch (type) {
-
-	case SILC_NOTIFY_TYPE_NONE:
-		break;
-
-	case SILC_NOTIFY_TYPE_INVITE:
-		{
-			GHashTable *components;
-			(void)va_arg(va, SilcChannelEntry);
-			name = va_arg(va, char *);
-			client_entry = va_arg(va, SilcClientEntry);
-
-			components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-			g_hash_table_insert(components, g_strdup("channel"), g_strdup(name));
-			purple_serv_got_chat_invite(gc, name, client_entry->nickname, NULL, components);
-		}
-		break;
-
-	case SILC_NOTIFY_TYPE_JOIN:
-		client_entry = va_arg(va, SilcClientEntry);
-		channel = va_arg(va, SilcChannelEntry);
-
-		/* If we joined channel, do nothing */
-		if (client_entry == conn->local_entry)
-			break;
-
-		chat = purple_conversation_manager_find_chat(manager, sg->account,
-		                                             channel->channel_name);
-		if (!chat) {
-			break;
-		}
-
-		/* Join user to channel */
-		g_snprintf(buf, sizeof(buf), "%s@%s",
-			   client_entry->username, client_entry->hostname);
-		purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(chat),
-					  client_entry->nickname, buf, PURPLE_CHAT_USER_NONE, TRUE);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_LEAVE:
-		client_entry = va_arg(va, SilcClientEntry);
-		channel = va_arg(va, SilcChannelEntry);
-
-		chat = purple_conversation_manager_find_chat(manager, sg->account,
-		                                             channel->channel_name);
-		if (!chat) {
-			break;
-		}
-
-		/* Remove user from channel */
-		purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat),
-					     client_entry->nickname, NULL);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_SIGNOFF:
-		client_entry = va_arg(va, SilcClientEntry);
-		tmp = va_arg(va, char *);
-
-		/* Remove from all channels */
-		silc_hash_table_list(client_entry->channels, &htl);
-		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-			chat = purple_conversation_manager_find_chat(manager, sg->account,
-			                                             chu->channel->channel_name);
-			if (!chat) {
-				continue;
-			}
-			purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat),
-						     client_entry->nickname,
-						     tmp);
-		}
-		silc_hash_table_list_reset(&htl);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_TOPIC_SET:
-		{
-			char *esc, *tmp2;
-			idtype = va_arg(va, int);
-			entry = va_arg(va, void *);
-			tmp = va_arg(va, char *);
-			channel = va_arg(va, SilcChannelEntry);
-
-			chat = purple_conversation_manager_find_chat(manager, sg->account,
-			                                             channel->channel_name);
-			if (!chat) {
-				break;
-			}
-
-			if (!tmp) {
-				break;
-			}
-
-			esc = g_markup_escape_text(tmp, -1);
-			tmp2 = purple_markup_linkify(esc);
-			g_free(esc);
-
-			if (idtype == SILC_ID_CLIENT) {
-				client_entry = (SilcClientEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-						_("%s has changed the topic of <I>%s</I> to: %s"),
-						client_entry->nickname, channel->channel_name, tmp2);
-				purple_conversation_write_system_message(
-					PURPLE_CONVERSATION(chat), buf, 0);
-				purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat),
-						client_entry->nickname, tmp);
-			} else if (idtype == SILC_ID_SERVER) {
-				server_entry = (SilcServerEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-						_("%s has changed the topic of <I>%s</I> to: %s"),
-						server_entry->server_name, channel->channel_name, tmp2);
-				purple_conversation_write_system_message(
-					PURPLE_CONVERSATION(chat), buf, 0);
-				purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat),
-						server_entry->server_name, tmp);
-			} else if (idtype == SILC_ID_CHANNEL) {
-				channel = (SilcChannelEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-						_("%s has changed the topic of <I>%s</I> to: %s"),
-						channel->channel_name, channel->channel_name, tmp2);
-				purple_conversation_write_system_message(
-					PURPLE_CONVERSATION(chat), buf, 0);
-				purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat),
-						channel->channel_name, tmp);
-			} else {
-				purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), NULL, tmp);
-			}
-
-			g_free(tmp2);
-
-			break;
-
-		}
-	case SILC_NOTIFY_TYPE_NICK_CHANGE:
-		client_entry = va_arg(va, SilcClientEntry);
-		tmp = va_arg(va, char *);      /* Old nick */
-		name = va_arg(va, char *);     /* New nick */
-
-		if (purple_strequal(tmp, name))
-			break;
-
-		/* Change nick on all channels */
-		silc_hash_table_list(client_entry->channels, &htl);
-		while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-			chat = purple_conversation_manager_find_chat(manager, sg->account,
-			                                             chu->channel->channel_name);
-			if (!chat) {
-				continue;
-			}
-			if (purple_chat_conversation_has_user(PURPLE_CHAT_CONVERSATION(chat), client_entry->nickname)) {
-				purple_chat_conversation_rename_user(PURPLE_CHAT_CONVERSATION(chat),
-							     tmp, name);
-			}
-		}
-		silc_hash_table_list_reset(&htl);
-
-		break;
-
-	case SILC_NOTIFY_TYPE_CMODE_CHANGE:
-		idtype = va_arg(va, int);
-		entry = va_arg(va, void *);
-		mode = va_arg(va, SilcUInt32);
-		(void)va_arg(va, char *);
-		(void)va_arg(va, char *);
-		(void)va_arg(va, char *);
-		(void)va_arg(va, SilcPublicKey);
-		(void)va_arg(va, SilcDList);
-		channel = va_arg(va, SilcChannelEntry);
-
-		chat = purple_conversation_manager_find_chat(manager, sg->account,
-		                                             channel->channel_name);
-		if (!chat) {
-			break;
-		}
-
-		if (idtype == SILC_ID_CLIENT) {
-			name = ((SilcClientEntry)entry)->nickname;
-		} else if (idtype == SILC_ID_SERVER) {
-			name = ((SilcServerEntry)entry)->server_name;
-		} else {
-			name = ((SilcChannelEntry)entry)->channel_name;
-		}
-
-		if (!name) {
-			break;
-		}
-
-		if (mode) {
-			silcpurple_get_chmode_string(mode, buf2, sizeof(buf2));
-			g_snprintf(buf, sizeof(buf),
-				   _("<I>%s</I> set channel <I>%s</I> modes to: %s"), name,
-				   channel->channel_name, buf2);
-		} else {
-			g_snprintf(buf, sizeof(buf),
-				   _("<I>%s</I> removed all channel <I>%s</I> modes"), name,
-				   channel->channel_name);
-		}
-		purple_conversation_write_system_message(PURPLE_CONVERSATION(chat), buf, 0);
-		break;
-
-	case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
-		{
-			PurpleChatUserFlags flags = PURPLE_CHAT_USER_NONE;
-			idtype = va_arg(va, int);
-			entry = va_arg(va, void *);
-			mode = va_arg(va, SilcUInt32);
-			client_entry2 = va_arg(va, SilcClientEntry);
-			channel = va_arg(va, SilcChannelEntry);
-
-			chat = purple_conversation_manager_find_chat(manager, sg->account,
-			                                             channel->channel_name);
-			if (!chat) {
-				break;
-			}
-
-			if (idtype == SILC_ID_CLIENT) {
-				name = ((SilcClientEntry)entry)->nickname;
-			} else if (idtype == SILC_ID_SERVER) {
-				name = ((SilcServerEntry)entry)->server_name;
-			} else {
-				name = ((SilcChannelEntry)entry)->channel_name;
-			}
-
-			if (!name) {
-				break;
-			}
-
-			if (mode) {
-				silcpurple_get_chumode_string(mode, buf2, sizeof(buf2));
-				g_snprintf(buf, sizeof(buf),
-					   _("<I>%s</I> set <I>%s's</I> modes to: %s"), name,
-					   client_entry2->nickname, buf2);
-				if (mode & SILC_CHANNEL_UMODE_CHANFO)
-					flags |= PURPLE_CHAT_USER_FOUNDER;
-				if (mode & SILC_CHANNEL_UMODE_CHANOP)
-					flags |= PURPLE_CHAT_USER_OP;
-			} else {
-				g_snprintf(buf, sizeof(buf),
-					   _("<I>%s</I> removed all <I>%s's</I> modes"), name,
-					   client_entry2->nickname);
-			}
-			purple_conversation_write_system_message(chat, buf, 0);
-			purple_chat_user_set_flags(purple_chat_conversation_find_user(
-					       PURPLE_CHAT_CONVERSATION(chat), client_entry2->nickname), flags);
-			break;
-		}
-
-	case SILC_NOTIFY_TYPE_MOTD:
-		tmp = va_arg(va, char *);
-		silc_free(sg->motd);
-		sg->motd = silc_memdup(tmp, strlen(tmp));
-		break;
-
-	case SILC_NOTIFY_TYPE_KICKED:
-		client_entry = va_arg(va, SilcClientEntry);
-		tmp = va_arg(va, char *);
-		client_entry2 = va_arg(va, SilcClientEntry);
-		channel = va_arg(va, SilcChannelEntry);
-
-		chat = purple_conversation_manager_find_chat(manager, sg->account,
-		                                             channel->channel_name);
-		if (!chat) {
-			break;
-		}
-
-		if (client_entry == conn->local_entry) {
-			/* Remove us from channel */
-			g_snprintf(buf, sizeof(buf),
-				   _("You have been kicked off <I>%s</I> by <I>%s</I> (%s)"),
-				   channel->channel_name, client_entry2->nickname,
-				   tmp ? tmp : "");
-			purple_conversation_write_system_message(chat, buf, 0);
-			purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)));
-		} else {
-			/* Remove user from channel */
-			g_snprintf(buf, sizeof(buf), _("Kicked by %s (%s)"),
-				   client_entry2->nickname, tmp ? tmp : "");
-			purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat),
-						     client_entry->nickname,
-						     buf);
-		}
-
-		break;
-
-	case SILC_NOTIFY_TYPE_KILLED:
-		client_entry = va_arg(va, SilcClientEntry);
-		tmp = va_arg(va, char *);
-		idtype = va_arg(va, int);
-		entry = va_arg(va, SilcClientEntry);
-
-		if (client_entry == conn->local_entry) {
-			if (idtype == SILC_ID_CLIENT) {
-				client_entry2 = (SilcClientEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("You have been killed by %s (%s)"),
-					   client_entry2->nickname, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_SERVER) {
-				server_entry = (SilcServerEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("You have been killed by %s (%s)"),
-					   server_entry->server_name, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_CHANNEL) {
-				channel = (SilcChannelEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("You have been killed by %s (%s)"),
-					   channel->channel_name, tmp ? tmp : "");
-			}
-
-			/* Remove us from all channels */
-			silc_hash_table_list(client_entry->channels, &htl);
-			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-				chat = purple_conversation_manager_find_chat(manager, sg->account,
-				                                             chu->channel->channel_name);
-				if (!chat) {
-					continue;
-				}
-				purple_conversation_write_system_message(chat, buf, 0);
-				purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)));
-			}
-			silc_hash_table_list_reset(&htl);
-
-		} else {
-			if (idtype == SILC_ID_CLIENT) {
-				client_entry2 = (SilcClientEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("Killed by %s (%s)"),
-					   client_entry2->nickname, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_SERVER) {
-				server_entry = (SilcServerEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("Killed by %s (%s)"),
-					   server_entry->server_name, tmp ? tmp : "");
-			} else if (idtype == SILC_ID_CHANNEL) {
-				channel = (SilcChannelEntry)entry;
-				g_snprintf(buf, sizeof(buf),
-					   _("Killed by %s (%s)"),
-					   channel->channel_name, tmp ? tmp : "");
-			}
-
-			/* Remove user from all channels */
-			silc_hash_table_list(client_entry->channels, &htl);
-			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-				chat = purple_conversation_manager_find_chat(manager, sg->account,
-				                                             chu->channel->channel_name);
-				if (!chat) {
-					continue;
-				}
-				purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat),
-							     client_entry->nickname, tmp);
-			}
-			silc_hash_table_list_reset(&htl);
-		}
-
-		break;
-
-	case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
-		break;
-
-	case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
-		(void)va_arg(va, void *);
-		list = va_arg(va, SilcDList);
-
-		silc_dlist_start(list);
-		while ((client_entry = silc_dlist_get(list))) {
-			/* Remove from all channels */
-			silc_hash_table_list(client_entry->channels, &htl);
-			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-				chat = purple_conversation_manager_find_chat(manager, sg->account,
-				                                             chu->channel->channel_name);
-				if (!chat) {
-					continue;
-				}
-				purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat),
-							     client_entry->nickname,
-							     _("Server signoff"));
-			}
-			silc_hash_table_list_reset(&htl);
-		}
-		break;
-
-	case SILC_NOTIFY_TYPE_ERROR:
-		{
-			SilcStatus error = va_arg(va, int);
-			purple_notify_error(gc, "Error Notify",
-					    silc_get_status_message(error),
-					    NULL, purple_request_cpar_from_connection(gc));
-		}
-		break;
-
-	case SILC_NOTIFY_TYPE_WATCH:
-		{
-			SilcPublicKey public_key;
-			unsigned char *pk;
-			SilcUInt32 pk_len;
-			char *fingerprint;
-
-			client_entry = va_arg(va, SilcClientEntry);
-			(void)va_arg(va, char *);
-			mode = va_arg(va, SilcUInt32);
-			notify = va_arg(va, int);
-			public_key = va_arg(va, SilcPublicKey);
-
-			b = NULL;
-			if (public_key) {
-				GSList *buddies;
-				const char *f;
-				gsize i;
-
-				pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-				if (!pk)
-					break;
-				fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-				for (i = 0; i < strlen(fingerprint); i++)
-					if (fingerprint[i] == ' ')
-						fingerprint[i] = '_';
-				g_snprintf(buf, sizeof(buf) - 1,
-					   "%s" G_DIR_SEPARATOR_S "clientkeys"
-					   G_DIR_SEPARATOR_S "clientkey_%s.pub",
-					   silcpurple_silcdir(), fingerprint);
-				silc_free(fingerprint);
-				silc_free(pk);
-
-				/* Find buddy by associated public key */
-				for (buddies = purple_blist_find_buddies(account, NULL); buddies;
-						buddies = g_slist_delete_link(buddies, buddies)) {
-					b = buddies->data;
-					f = purple_blist_node_get_string(PURPLE_BLIST_NODE(b), "public-key");
-					if (purple_strequal(f, buf))
-						goto cont;
-					b = NULL;
-				}
-			}
-		cont:
-			if (!b) {
-				/* Find buddy by nickname */
-				b = purple_blist_find_buddy(sg->account, client_entry->nickname);
-				if (!b) {
-					purple_debug_warning("silc", "WATCH for %s, unknown buddy\n",
-						client_entry->nickname);
-					break;
-				}
-			}
-
-			silc_free(purple_buddy_get_protocol_data(b));
-			purple_buddy_set_protocol_data(b, silc_memdup(&client_entry->id,
-						    sizeof(client_entry->id)));
-			if (notify == SILC_NOTIFY_TYPE_NICK_CHANGE) {
-				break;
-			} else if (notify == SILC_NOTIFY_TYPE_UMODE_CHANGE) {
-				/* See if client was away and is now present */
-				if (!(mode & (SILC_UMODE_GONE | SILC_UMODE_INDISPOSED |
-					      SILC_UMODE_BUSY | SILC_UMODE_PAGE |
-					      SILC_UMODE_DETACHED)) &&
-				    (client_entry->mode & SILC_UMODE_GONE ||
-				     client_entry->mode & SILC_UMODE_INDISPOSED ||
-				     client_entry->mode & SILC_UMODE_BUSY ||
-				     client_entry->mode & SILC_UMODE_PAGE ||
-				     client_entry->mode & SILC_UMODE_DETACHED)) {
-					client_entry->mode = mode;
-					purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
-				}
-				else if ((mode & SILC_UMODE_GONE) ||
-					 (mode & SILC_UMODE_INDISPOSED) ||
-					 (mode & SILC_UMODE_BUSY) ||
-					 (mode & SILC_UMODE_PAGE) ||
-					 (mode & SILC_UMODE_DETACHED)) {
-					client_entry->mode = mode;
-					purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-				}
-			} else if (notify == SILC_NOTIFY_TYPE_SIGNOFF ||
-				   notify == SILC_NOTIFY_TYPE_SERVER_SIGNOFF ||
-				   notify == SILC_NOTIFY_TYPE_KILLED) {
-				client_entry->mode = mode;
-				purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
-			} else if (notify == SILC_NOTIFY_TYPE_NONE) {
-				client_entry->mode = mode;
-				purple_protocol_got_user_status(purple_buddy_get_account(b), purple_buddy_get_name(b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);
-			}
-		}
-		break;
-
-	default:
-		purple_debug_info("silc", "Unhandled notification: %d\n", type);
-		break;
-	}
-
-	va_end(va);
-}
-
-
-/* Command handler. This function is called always after application has
-   called a command.  It will be called to indicate that the command
-   was processed.  It will also be called if error occurs while processing
-   the command.  The `success' indicates whether the command was sent
-   or if error occurred.  The `status' indicates the actual error.
-   The `argc' and `argv' are the command line arguments sent to the
-   command by application.  Note that, this is not reply to the command
-   from server, this is merely and indication to application that the
-   command was processed. */
-
-static void
-silc_command(SilcClient client, SilcClientConnection conn,
-	     SilcBool success, SilcCommand command, SilcStatus status,
-	     SilcUInt32 argc, unsigned char **argv)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-
-	switch (command) {
-
-	case SILC_COMMAND_CMODE:
-		if (argc == 3 && purple_strequal((char *)argv[2], "+C"))
-			sg->chpk = TRUE;
-		else
-			sg->chpk = FALSE;
-		break;
-
-	default:
-		break;
-	}
-}
-
-
-/* Command reply handler.  Delivers a reply to command that was sent
-   earlier.  The `conn' is the associated client connection.  The `command'
-   indicates the command reply type.  If the `status' other than
-   SILC_STATUS_OK an error occurred.  In this case the `error' will indicate
-   the error.  It is possible to receive list of command replies and list
-   of errors.  In this case the `status' will indicate it is an list entry
-   (the `status' is SILC_STATUS_LIST_START, SILC_STATUS_LIST_ITEM and/or
-   SILC_STATUS_LIST_END).
-
-   The arguments received in `ap' are command specific.  See a separate
-   documentation in the Toolkit Reference Manual for the command reply
-   arguments. */
-
-static void
-silc_command_reply(SilcClient client, SilcClientConnection conn,
-		   SilcCommand command, SilcStatus status,
-		   SilcStatus error, va_list ap)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	PurpleConversation *chat;
-	PurpleConversationManager *manager;
-
-	manager = purple_conversation_manager_get_default();
-
-	switch (command) {
-	case SILC_COMMAND_JOIN:
-		{
-			SilcChannelEntry channel;
-			SilcHashTableList *user_list;
-			SilcChannelUser chu;
-			GList *users = NULL, *flags = NULL;
-			char tmp[256], *topic;
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Join Chat"), _("Cannot join channel"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				return;
-			}
-
-			(void)va_arg(ap, char *);
-			channel = va_arg(ap, SilcChannelEntry);
-			(void)va_arg(ap, SilcUInt32);
-			user_list = va_arg(ap, SilcHashTableList *);
-			topic = va_arg(ap, char *);
-
-			/* Add channel to Purple */
-			channel->context = SILC_32_TO_PTR(++sg->channel_ids);
-			purple_serv_got_joined_chat(gc, sg->channel_ids, channel->channel_name);
-			chat = purple_conversation_manager_find_chat(manager, sg->account,
-			                                             channel->channel_name);
-			if (!chat) {
-			  return;
-			}
-
-			/* Add all users to channel */
-			while (silc_hash_table_get(user_list, NULL, (void *)&chu)) {
-			  PurpleChatUserFlags f = PURPLE_CHAT_USER_NONE;
-			  chu->context = SILC_32_TO_PTR(sg->channel_ids);
-
-			  if (chu->mode & SILC_CHANNEL_UMODE_CHANFO)
-			    f |= PURPLE_CHAT_USER_FOUNDER;
-			  if (chu->mode & SILC_CHANNEL_UMODE_CHANOP)
-			    f |= PURPLE_CHAT_USER_OP;
-			  users = g_list_append(users, chu->client->nickname);
-			  flags = g_list_append(flags, GINT_TO_POINTER(f));
-
-			  if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) {
-			    if (chu->client == conn->local_entry)
-				g_snprintf(tmp, sizeof(tmp),
-					   _("You are channel founder on <I>%s</I>"),
-					   channel->channel_name);
-			    else
-				g_snprintf(tmp, sizeof(tmp),
-					   _("Channel founder on <I>%s</I> is <I>%s</I>"),
-					   channel->channel_name, chu->client->nickname);
-
-			   purple_conversation_write_system_message(chat, tmp, 0);
-			  }
-			}
-
-			purple_chat_conversation_add_users(PURPLE_CHAT_CONVERSATION(chat),
-			                                   users, NULL, flags, FALSE);
-			g_list_free(users);
-			g_list_free(flags);
-
-			/* Set topic */
-			if(topic) {
-				purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat),
-				                                   NULL, topic);
-			}
-
-			/* Set nick */
-			purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION(chat),
-			                                  conn->local_entry->nickname);
-		}
-		break;
-
-	case SILC_COMMAND_LEAVE:
-		break;
-
-	case SILC_COMMAND_USERS:
-		break;
-
-	case SILC_COMMAND_WHOIS:
-		{
-			SilcUInt32 *user_modes;
-			SilcDList channels;
-			SilcClientEntry client_entry;
-			char tmp[1024];
-			char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
-			PurpleNotifyUserInfo *user_info;
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("User Information"),
-						_("Cannot get user information"),
-						silc_get_status_message(error),
-						purple_request_cpar_from_connection(gc));
-				break;
-			}
-
-			client_entry = va_arg(ap, SilcClientEntry);
-			(void)va_arg(ap, char *);
-			(void)va_arg(ap, char *);
-			(void)va_arg(ap, char *);
-			channels = va_arg(ap, SilcDList);
-			(void)va_arg(ap, SilcUInt32);
-			(void)va_arg(ap, SilcUInt32); /* idle */
-			(void)va_arg(ap, unsigned char *);
-			user_modes = va_arg(ap, SilcUInt32 *);
-
-			user_info = purple_notify_user_info_new();
-			purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), client_entry->nickname);
-			if (client_entry->realname) {
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), client_entry->realname);
-			}
-			if (*client_entry->hostname) {
-				gchar *tmp2;
-				tmp2 = g_strdup_printf("%s@%s", client_entry->username, client_entry->hostname);
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp2);
-				g_free(tmp2);
-			} else
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), client_entry->username);
-
-			if (client_entry->mode) {
-				memset(tmp, 0, sizeof(tmp));
-				silcpurple_get_umode_string(client_entry->mode,
-							    tmp, sizeof(tmp) - strlen(tmp));
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("User Modes"), tmp);
-			}
-
-			silcpurple_parse_attrs(client_entry->attrs, &moodstr, &statusstr, &contactstr, &langstr, &devicestr, &tzstr, &geostr);
-			if (moodstr) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Mood"), moodstr);
-				g_free(moodstr);
-			}
-
-			if (statusstr) {
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Status Text"), statusstr);
-				g_free(statusstr);
-			}
-
-			if (contactstr) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Preferred Contact"), contactstr);
-				g_free(contactstr);
-			}
-
-			if (langstr) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Preferred Language"), langstr);
-				g_free(langstr);
-			}
-
-			if (devicestr) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Device"), devicestr);
-				g_free(devicestr);
-			}
-
-			if (tzstr) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Timezone"), tzstr);
-				g_free(tzstr);
-			}
-
-			if (geostr) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Geolocation"), geostr);
-				g_free(geostr);
-			}
-
-			if (*client_entry->server) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server);
-			}
-
-			if (channels && user_modes) {
-				SilcChannelPayload entry;
-				int i = 0;
-
-				memset(tmp, 0, sizeof(tmp));
-				silc_dlist_start(channels);
-				while ((entry = silc_dlist_get(channels))) {
-					SilcUInt32 name_len;
-					char *m = silc_client_chumode_char(user_modes[i++]);
-					char *name = (char *)silc_channel_get_name(entry, &name_len);
-					if (m)
-						silc_strncat(tmp, sizeof(tmp) - 1, m, strlen(m));
-					silc_strncat(tmp, sizeof(tmp) - 1, name, name_len);
-					silc_strncat(tmp, sizeof(tmp) - 1, "  ", 1);
-					silc_free(m);
-				}
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Currently on"), tmp);
-			}
-
-			if (client_entry->public_key) {
-				char *fingerprint, *babbleprint;
-				unsigned char *pk;
-				SilcUInt32 pk_len;
-				pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
-				if (pk) {
-					fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-					babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint);
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint);
-					silc_free(fingerprint);
-					silc_free(babbleprint);
-					silc_free(pk);
-				}
-			}
-
-			purple_notify_userinfo(gc, client_entry->nickname, user_info, NULL, NULL);
-			purple_notify_user_info_destroy(user_info);
-		}
-		break;
-
-	case SILC_COMMAND_WHOWAS:
-		{
-			SilcClientEntry client_entry;
-			char *nickname, *realname, *username;
-			PurpleNotifyUserInfo *user_info;
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("User Information"),
-						  _("Cannot get user information"),
-						  silc_get_status_message(error),
-						  purple_request_cpar_from_connection(gc));
-				break;
-			}
-
-			client_entry = va_arg(ap, SilcClientEntry);
-			nickname = va_arg(ap, char *);
-			username = va_arg(ap, char *);
-			realname = va_arg(ap, char *);
-			if (!nickname)
-				break;
-
-			user_info = purple_notify_user_info_new();
-			purple_notify_user_info_add_pair_plaintext(user_info, _("Nickname"), nickname);
-			if (realname)
-				purple_notify_user_info_add_pair_plaintext(user_info, _("Real Name"), realname);
-			if (username) {
-				if (client_entry && *client_entry->hostname) {
-					gchar *tmp;
-					tmp = g_strdup_printf("%s@%s", username, client_entry->hostname);
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp);
-					g_free(tmp);
-				} else
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), username);
-			}
-			if (client_entry && *client_entry->server) {
-				/* TODO: Check whether it's correct to call add_pair_html,
-				         or if we should be using add_pair_plaintext */
-				purple_notify_user_info_add_pair_html(user_info, _("Server"), client_entry->server);
-			}
-
-
-			if (client_entry && client_entry->public_key) {
-				char *fingerprint, *babbleprint;
-				unsigned char *pk;
-				SilcUInt32 pk_len;
-				pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
-				if (pk) {
-					fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-					babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Fingerprint"), fingerprint);
-					purple_notify_user_info_add_pair_plaintext(user_info, _("Public Key Babbleprint"), babbleprint);
-					silc_free(fingerprint);
-					silc_free(babbleprint);
-					silc_free(pk);
-				}
-			}
-
-			purple_notify_userinfo(gc, nickname, user_info, NULL, NULL);
-			purple_notify_user_info_destroy(user_info);
-		}
-		break;
-
-	case SILC_COMMAND_DETACH:
-		{
-			const char *file;
-			SilcBuffer detach_data;
-
-			if (status != SILC_STATUS_OK) {
-			  purple_notify_error(gc, _("Detach From Server"), _("Cannot detach"),
-					      silc_get_status_message(error),
-					      purple_request_cpar_from_connection(gc));
-			  return;
-			}
-
-			detach_data = va_arg(ap, SilcBuffer);
-
-			/* Save the detachment data to file. */
-			file = silcpurple_session_file(purple_account_get_username(sg->account));
-			g_unlink(file);
-			silc_file_writefile(file, (const char *)silc_buffer_data(detach_data),
-					    silc_buffer_len(detach_data));
-		}
-		break;
-
-	case SILC_COMMAND_TOPIC:
-		{
-			SilcChannelEntry channel;
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Topic"), _("Cannot set topic"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				return;
-			}
-
-			channel = va_arg(ap, SilcChannelEntry);
-
-			chat = purple_conversation_manager_find_chat(manager, sg->account,
-			                                             channel->channel_name);
-			if (!chat) {
-				purple_debug_error("silc", "Got a topic for %s, which doesn't exist\n",
-						   channel->channel_name);
-				break;
-			}
-
-			/* Set topic */
-			if (channel->topic) {
-				purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat),
-				                                   NULL, channel->topic);
-			}
-		}
-		break;
-
-	case SILC_COMMAND_NICK:
-		{
-			SilcClientEntry local_entry;
-			SilcHashTableList htl;
-			SilcChannelUser chu;
-			const char *oldnick, *newnick;
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Nick"), _("Failed to change nickname"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				return;
-			}
-
-			local_entry = va_arg(ap, SilcClientEntry);
-			newnick = va_arg(ap, char *);
-
-			/* Change nick on all channels */
-			silc_hash_table_list(local_entry->channels, &htl);
-			while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
-				chat = purple_conversation_manager_find_chat(manager, sg->account,
-				                                             chu->channel->channel_name);
-				if (!chat) {
-					continue;
-				}
-				oldnick = purple_chat_conversation_get_nick(PURPLE_CHAT_CONVERSATION(chat));
-				if (!purple_strequal(oldnick,
-						purple_normalize(purple_conversation_get_account(chat),
-						newnick)))
-				{
-
-					purple_chat_conversation_rename_user(PURPLE_CHAT_CONVERSATION(chat),
-								     oldnick, newnick);
-					purple_chat_conversation_set_nick(PURPLE_CHAT_CONVERSATION(chat), newnick);
-				}
-			}
-			silc_hash_table_list_reset(&htl);
-
-			purple_connection_set_display_name(gc, newnick);
-		}
-		break;
-
-	case SILC_COMMAND_LIST:
-		{
-			char *topic, *name;
-			int usercount;
-			PurpleRoomlistRoom *room;
-
-			if (sg->roomlist_cancelled)
-				break;
-
-			if (error != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Error"), _("Error retrieving room list"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
-				g_object_unref(sg->roomlist);
-				sg->roomlist = NULL;
-				return;
-			}
-
-			(void)va_arg(ap, SilcChannelEntry);
-			name = va_arg(ap, char *);
-			if (!name) {
-				purple_notify_error(gc, _("Roomlist"), _("Cannot get room list"),
-						    _("Network is empty"),
-						    purple_request_cpar_from_connection(gc));
-				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
-				g_object_unref(sg->roomlist);
-				sg->roomlist = NULL;
-				return;
-			}
-			topic = va_arg(ap, char *);
-			usercount = va_arg(ap, int);
-
-			room = purple_roomlist_room_new(name, topic);
-			purple_roomlist_room_set_user_count(room, usercount);
-			purple_roomlist_room_add_field(room, "channel", g_strdup(name));
-			purple_roomlist_room_add(sg->roomlist, room);
-			g_object_unref(room);
-
-			if (status == SILC_STATUS_LIST_END ||
-			    status == SILC_STATUS_OK) {
-				purple_roomlist_set_in_progress(sg->roomlist, FALSE);
-				g_object_unref(sg->roomlist);
-				sg->roomlist = NULL;
-			}
-		}
-		break;
-
-	case SILC_COMMAND_GETKEY:
-		{
-			SilcPublicKey public_key;
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Get Public Key"),
-						    _("Cannot fetch the public key"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				return;
-			}
-
-			(void)va_arg(ap, SilcUInt32);
-			(void)va_arg(ap, void *);
-			public_key = va_arg(ap, SilcPublicKey);
-
-			if (!public_key)
-				purple_notify_error(gc, _("Get Public Key"),
-						    _("Cannot fetch the public key"),
-						    _("No public key was received"),
-						    purple_request_cpar_from_connection(gc));
-		}
-		break;
-
-	case SILC_COMMAND_INFO:
-		{
-
-			char *server_name;
-			char *server_info;
-			char tmp[256];
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Server Information"),
-						    _("Cannot get server information"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				return;
-			}
-
-			(void)va_arg(ap, SilcServerEntry);
-			server_name = va_arg(ap, char *);
-			server_info = va_arg(ap, char *);
-
-			if (server_name && server_info) {
-				g_snprintf(tmp, sizeof(tmp), "Server: %s\n%s",
-					   server_name, server_info);
-				purple_notify_info(gc, NULL, _("Server Information"), tmp,
-					purple_request_cpar_from_connection(gc));
-			}
-		}
-		break;
-
-	case SILC_COMMAND_STATS:
-		{
-			SilcClientStats *stats;
-			char *msg;
-
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Server Statistics"),
-						    _("Cannot get server statistics"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				return;
-			}
-
-			stats = va_arg(ap, SilcClientStats *);
-
-			msg = g_strdup_printf(_("Local server start time: %s\n"
-						"Local server uptime: %s\n"
-						"Local server clients: %d\n"
-						"Local server channels: %d\n"
-						"Local server operators: %d\n"
-						"Local router operators: %d\n"
-						"Local cell clients: %d\n"
-						"Local cell channels: %d\n"
-						"Local cell servers: %d\n"
-						"Total clients: %d\n"
-						"Total channels: %d\n"
-						"Total servers: %d\n"
-						"Total routers: %d\n"
-						"Total server operators: %d\n"
-						"Total router operators: %d\n"),
-					      silc_time_string(stats->starttime),
-					      purple_str_seconds_to_string((int)stats->uptime),
-					      (int)stats->my_clients,
-					      (int)stats->my_channels,
-					      (int)stats->my_server_ops,
-					      (int)stats->my_router_ops,
-					      (int)stats->cell_clients,
-					      (int)stats->cell_channels,
-					      (int)stats->cell_servers,
-					      (int)stats->clients,
-					      (int)stats->channels,
-					      (int)stats->servers,
-					      (int)stats->routers,
-					      (int)stats->server_ops,
-					      (int)stats->router_ops);
-
-			purple_notify_info(gc, NULL,
-					   _("Network Statistics"), msg,
-					   purple_request_cpar_from_connection(gc));
-			g_free(msg);
-		}
-		break;
-
-	case SILC_COMMAND_PING:
-		{
-			if (status != SILC_STATUS_OK) {
-				purple_notify_error(gc, _("Ping"), _("Ping failed"),
-						    silc_get_status_message(error),
-						    purple_request_cpar_from_connection(gc));
-				return;
-			}
-
-			purple_notify_info(gc, _("Ping"), _("Ping reply received from server"),
-					   NULL, purple_request_cpar_from_connection(gc));
-		}
-		break;
-
-	case SILC_COMMAND_KILL:
-		if (status != SILC_STATUS_OK) {
-			purple_notify_error(gc, _("Kill User"),
-					    _("Could not kill user"),
-					    silc_get_status_message(error),
-					    purple_request_cpar_from_connection(gc));
-			return;
-		}
-		break;
-
-	case SILC_COMMAND_CMODE:
-		{
-			SilcChannelEntry channel_entry;
-			SilcDList channel_pubkeys, list;
-			SilcArgumentDecodedList e;
-
-			if (status != SILC_STATUS_OK)
-				return;
-
-			channel_entry = va_arg(ap, SilcChannelEntry);
-			(void)va_arg(ap, SilcUInt32);
-			(void)va_arg(ap, SilcPublicKey);
-			channel_pubkeys = va_arg(ap, SilcDList);
-
-			if (!sg->chpk)
-				break;
-
-			list = silc_dlist_init();
-
-			if (channel_pubkeys) {
-			  silc_dlist_start(channel_pubkeys);
-			  while ((e = silc_dlist_get(channel_pubkeys))) {
-				if (e->arg_type == 0x00 ||
-				    e->arg_type == 0x03)
-				  silc_dlist_add(list, silc_pkcs_public_key_copy(e->argument));
-			  }
-			}
-			silcpurple_chat_chauth_show(sg, channel_entry, list);
-		}
-		break;
-
-	case SILC_COMMAND_WATCH:
-		if (status != SILC_STATUS_OK) {
-			purple_notify_error(gc, _("WATCH"), _("Cannot watch user"),
-				silc_get_status_message(error),
-				purple_request_cpar_from_connection(gc));
-			return;
-		}
-		break;
-
-	default:
-		if (status == SILC_STATUS_OK)
-			purple_debug_info("silc", "Unhandled command: %d (succeeded)\n", command);
-		else
-			purple_debug_info("silc", "Unhandled command: %d (failed: %s)\n", command,
-					  silc_get_status_message(error));
-		break;
-	}
-}
-
-/* Generic command reply callback for silc_client_command_send.  Simply
-   calls the default command_reply client operation callback */
-
-SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn,
-				  SilcCommand command, SilcStatus status,
-				  SilcStatus error, void *context, va_list ap)
-{
-  silc_command_reply(client, conn, command, status, error, ap);
-  return TRUE;
-}
-
-
-typedef struct {
-        union {
-	  SilcAskPassphrase ask_pass;
-	  SilcGetAuthMeth get_auth;
-	} u;
-	void *context;
-} *SilcPurpleAskPassphrase;
-
-static void
-silc_ask_auth_password_cb(const unsigned char *passphrase,
-			  SilcUInt32 passphrase_len, void *context)
-{
-	SilcPurpleAskPassphrase internal = context;
-
-	if (!passphrase || !(*passphrase))
-	  internal->u.get_auth(SILC_AUTH_NONE, NULL, 0, internal->context);
-	else
-	  internal->u.get_auth(SILC_AUTH_PASSWORD,
-			       (unsigned char *)passphrase,
-			       passphrase_len, internal->context);
-	silc_free(internal);
-}
-
-/* Find authentication method and authentication data by hostname and
-   port. The hostname may be IP address as well. The `auth_method' is
-   the authentication method the remote connection requires.  It is
-   however possible that remote accepts also some other authentication
-   method.  Application should use the method that may have been
-   configured for this connection.  If none has been configured it should
-   use the required `auth_method'.  If the `auth_method' is
-   SILC_AUTH_NONE, server does not require any authentication or the
-   required authentication method is not known.  The `completion'
-   callback must be called to deliver the chosen authentication method
-   and data. The `conn' may be NULL. */
-
-static void
-silc_get_auth_method(SilcClient client, SilcClientConnection conn,
-		     char *hostname, SilcUInt16 port,
-		     SilcAuthMethod auth_method,
-		     SilcGetAuthMeth completion, void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcPurpleAskPassphrase internal;
-	const char *password;
-
-	/* Check configuration if we have this connection configured. */
-	if (auth_method == SILC_AUTH_PUBLIC_KEY &&
-	    purple_account_get_bool(sg->account, "pubkey-auth", FALSE)) {
-		completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context);
-		return;
-	}
-	if (auth_method == SILC_AUTH_PASSWORD) {
-		password = purple_connection_get_password(gc);
-		if (password && *password) {
-		  completion(SILC_AUTH_PASSWORD, (unsigned char *)password, strlen(password), context);
-		  return;
-		}
-
-		/* Ask password from user */
-		internal = silc_calloc(1, sizeof(*internal));
-		if (!internal)
-		  return;
-		internal->u.get_auth = completion;
-		internal->context = context;
-		silc_ask_passphrase(client, conn, silc_ask_auth_password_cb,
-				    internal);
-		return;
-	}
-
-	completion(SILC_AUTH_NONE, NULL, 0, context);
-}
-
-
-/* Called to verify received public key. The `conn_type' indicates which
-   entity (server or client) has sent the public key. If user decides to
-   trust the key the application may save the key as trusted public key for
-   later use. The `completion' must be called after the public key has
-   been verified. */
-
-static void
-silc_verify_public_key(SilcClient client, SilcClientConnection conn,
-		       SilcConnectionType conn_type,
-		       SilcPublicKey public_key,
-		       SilcVerifyPublicKey completion, void *context)
-{
-	/* Verify public key */
-	silcpurple_verify_public_key(client, conn, NULL, conn_type,
-				     public_key, completion, context);
-}
-
-static void
-silc_ask_passphrase_cb(SilcPurpleAskPassphrase internal, const char *passphrase)
-{
-	if (!passphrase || !(*passphrase))
-		internal->u.ask_pass(NULL, 0, internal->context);
-	else
-		internal->u.ask_pass((unsigned char *)passphrase,
-				     strlen(passphrase), internal->context);
-	silc_free(internal);
-}
-
-/* Ask (interact, that is) a passphrase from user. The passphrase is
-   returned to the library by calling the `completion' callback with
-   the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
-   if not then the library will attempt to encode. */
-
-static void
-silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
-		    SilcAskPassphrase completion, void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurpleAskPassphrase internal = silc_calloc(1, sizeof(*internal));
-
-	if (!internal)
-		return;
-	internal->u.ask_pass = completion;
-	internal->context = context;
-	purple_request_input(gc, _("Passphrase"), NULL,
-			     _("Passphrase required"), NULL, FALSE, TRUE, NULL,
-			     _("OK"), G_CALLBACK(silc_ask_passphrase_cb),
-			     _("Cancel"), G_CALLBACK(silc_ask_passphrase_cb),
-			     purple_request_cpar_from_connection(gc), internal);
-}
-
-
-/* Called to indicate that incoming key agreement request has been
-   received.  If the application wants to perform key agreement it may
-   call silc_client_perform_key_agreement to initiate key agreement or
-   silc_client_send_key_agreement to provide connection point to the
-   remote client in case the `hostname' is NULL.  If key agreement is
-   not desired this request can be ignored.  The `protocol' is either
-   value 0 for TCP or value 1 for UDP. */
-
-static void
-silc_key_agreement(SilcClient client, SilcClientConnection conn,
-		   SilcClientEntry client_entry,
-		   const char *hostname, SilcUInt16 protocol,
-		   SilcUInt16 port)
-{
-	silcpurple_buddy_keyagr_request(client, conn, client_entry,
-					hostname, port, protocol);
-}
-
-
-/* Notifies application that file transfer protocol session is being
-   requested by the remote client indicated by the `client_entry' from
-   the `hostname' and `port'. The `session_id' is the file transfer
-   session and it can be used to either accept or reject the file
-   transfer request, by calling the silc_client_file_receive or
-   silc_client_file_close, respectively. */
-
-static void
-silc_ftp(SilcClient client, SilcClientConnection conn,
-	 SilcClientEntry client_entry, SilcUInt32 session_id,
-	 const char *hostname, SilcUInt16 port)
-{
-	silcpurple_ftp_request(client, conn, client_entry, session_id,
-			       hostname, port);
-}
-
-SilcClientOperations ops = {
-	silc_say,
-	silc_channel_message,
-	silc_private_message,
-	silc_notify,
-	silc_command,
-	silc_command_reply,
-	silc_get_auth_method,
-	silc_verify_public_key,
-	silc_ask_passphrase,
-	silc_key_agreement,
-	silc_ftp
-};
--- a/libpurple/protocols/silc/pk.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-/*
-
-  silcpurple_pk.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include <glib/gi18n-lib.h>
-#include <glib/gstdio.h>
-
-#include "glibcompat.h" /* for purple_g_stat on win32 */
-#include "silcpurple.h"
-
-/************************* Public Key Verification ***************************/
-
-typedef struct {
-	SilcClient client;
-	SilcClientConnection conn;
-	char *filename;
-	char *entity;
-	char *entity_name;
-	char *fingerprint;
-	char *babbleprint;
-	SilcPublicKey public_key;
-	SilcVerifyPublicKey completion;
-	void *context;
-	gboolean changed;
-} *PublicKeyVerify;
-
-static void silcpurple_verify_ask(const char *entity,
-				  const char *fingerprint,
-				  const char *babbleprint,
-				  PublicKeyVerify verify);
-
-static void silcpurple_verify_cb(PublicKeyVerify verify, gint id)
-{
-	if (id != 2) {
-		if (verify->completion)
-			verify->completion(FALSE, verify->context);
-	} else {
-		if (verify->completion)
-			verify->completion(TRUE, verify->context);
-
-		/* Save the key for future checking */
-		silc_pkcs_save_public_key(verify->filename, verify->public_key,
-					  SILC_PKCS_FILE_BASE64);
-	}
-
-	g_free(verify->filename);
-	g_free(verify->entity);
-	g_free(verify->entity_name);
-	silc_free(verify->fingerprint);
-	silc_free(verify->babbleprint);
-	silc_pkcs_public_key_free(verify->public_key);
-	silc_free(verify);
-}
-
-static void silcpurple_verify_details_cb(PublicKeyVerify verify)
-{
-	/* What a hack.  We have to display the accept dialog _again_
-	   because Purple closes the dialog after you press the button.  Purple
-	   should have option for the dialogs whether the buttons close them
-	   or not. */
-	silcpurple_verify_ask(verify->entity, verify->fingerprint,
-			      verify->babbleprint, verify);
-}
-
-static void silcpurple_verify_details(PublicKeyVerify verify, gint id)
-{
-	PurpleConnection *gc = verify->client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-
-	silcpurple_show_public_key(sg, verify->entity_name, verify->public_key,
-				   G_CALLBACK(silcpurple_verify_details_cb),
-				   verify);
-}
-
-static void silcpurple_verify_ask(const char *entity,
-				  const char *fingerprint,
-				  const char *babbleprint,
-				  PublicKeyVerify verify)
-{
-	PurpleConnection *gc = verify->client->application;
-	char tmp[256], tmp2[256];
-
-	if (verify->changed) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("Received %s's public key. Your local copy does not match this "
-			     "key. Would you still like to accept this public key?"),
-			   entity);
-	} else {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("Received %s's public key. Would you like to accept this "
-			     "public key?"), entity);
-	}
-	g_snprintf(tmp2, sizeof(tmp2),
-		   _("Fingerprint and babbleprint for the %s key are:\n\n"
-		     "%s\n%s\n"), entity, fingerprint, babbleprint);
-
-	purple_request_action(gc, _("Verify Public Key"), tmp, tmp2,
-			      PURPLE_DEFAULT_ACTION_NONE,
-			      purple_request_cpar_from_connection(gc), verify, 3,
-			      _("Yes"), G_CALLBACK(silcpurple_verify_cb),
-			      _("No"), G_CALLBACK(silcpurple_verify_cb),
-			      _("_View..."), G_CALLBACK(silcpurple_verify_details));
-}
-
-void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
-				  const char *name, SilcConnectionType conn_type,
-				  SilcPublicKey public_key,
-				  SilcVerifyPublicKey completion, void *context)
-{
-	PurpleConnection *gc = client->application;
-	gsize i;
-	char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
-	char *fingerprint, *babbleprint;
-	struct passwd *pw;
-	GStatBuf st;
-	char *entity = ((conn_type == SILC_CONN_SERVER ||
-			 conn_type == SILC_CONN_ROUTER) ?
-			"server" : "client");
-	PublicKeyVerify verify;
-	const char *ip, *hostname;
-	SilcUInt16 port;
-	unsigned char *pk;
-	SilcUInt32 pk_len;
-
-	if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) {
-		purple_notify_error(gc, _("Verify Public Key"),
-				    _("Unsupported public key type"), NULL,
-				    purple_request_cpar_from_connection(gc));
-		if (completion)
-			completion(FALSE, context);
-		return;
-	}
-
-	pw = getpwuid(getuid());
-	if (!pw) {
-		if (completion)
-			completion(FALSE, context);
-		return;
-	}
-
-	memset(filename, 0, sizeof(filename));
-	memset(filename2, 0, sizeof(filename2));
-	memset(file, 0, sizeof(file));
-
-	silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream),
-				    NULL, &hostname, &ip, &port);
-
-	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-	if (!pk) {
-		if (completion)
-			completion(FALSE, context);
-		return;
-	}
-
-	if (conn_type == SILC_CONN_SERVER ||
-	    conn_type == SILC_CONN_ROUTER) {
-		if (!name) {
-			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   ip, port);
-			g_snprintf(filename, sizeof(filename) - 1,
-				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-				   silcpurple_silcdir(), entity, file);
-
-			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   hostname, port);
-			g_snprintf(filename2, sizeof(filename2) - 1,
-				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-				   silcpurple_silcdir(), entity, file);
-
-			ipf = filename;
-			hostf = filename2;
-		} else {
-			g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
-				   name, port);
-			g_snprintf(filename, sizeof(filename) - 1,
-				   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-				   silcpurple_silcdir(), entity, file);
-
-			ipf = filename;
-		}
-	} else {
-		/* Replace all whitespaces with `_'. */
-		fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-		for (i = 0; i < strlen(fingerprint); i++)
-			if (fingerprint[i] == ' ')
-				fingerprint[i] = '_';
-
-		g_snprintf(file, sizeof(file) - 1, "%skey_%s.pub", entity, fingerprint);
-		g_snprintf(filename, sizeof(filename) - 1,
-			   "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
-			   silcpurple_silcdir(), entity, file);
-		silc_free(fingerprint);
-
-		ipf = filename;
-	}
-
-	verify = silc_calloc(1, sizeof(*verify));
-	if (!verify)
-		return;
-	verify->client = client;
-	verify->conn = conn;
-	verify->filename = g_strdup(ipf);
-	verify->entity = g_strdup(entity);
-	verify->entity_name = (conn_type != SILC_CONN_CLIENT ?
-			       (name ? g_strdup(name) : g_strdup(hostname))
-			       : NULL);
-	verify->public_key = silc_pkcs_public_key_copy(public_key);
-	verify->completion = completion;
-	verify->context = context;
-	fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-	babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-
-	/* Check whether this key already exists */
-	if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) {
-		/* Key does not exist, ask user to verify the key and save it */
-		silcpurple_verify_ask(name ? name : entity,
-				      fingerprint, babbleprint, verify);
-		return;
-	} else {
-		/* The key already exists, verify it. */
-		SilcPublicKey public_key;
-		unsigned char *encpk;
-		SilcUInt32 encpk_len;
-
-		/* Load the key file, try for both IP filename and hostname filename */
-		if (!silc_pkcs_load_public_key(ipf, &public_key) &&
-		    (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key)))) {
-			silcpurple_verify_ask(name ? name : entity,
-					    fingerprint, babbleprint, verify);
-			return;
-		}
-
-		/* Encode the key data */
-		encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
-		if (!encpk) {
-			silcpurple_verify_ask(name ? name : entity,
-					    fingerprint, babbleprint, verify);
-			return;
-		}
-
-		/* Compare the keys */
-		if (memcmp(encpk, pk, encpk_len)) {
-			/* Ask user to verify the key and save it */
-			verify->changed = TRUE;
-			silcpurple_verify_ask(name ? name : entity,
-					    fingerprint, babbleprint, verify);
-			return;
-		}
-
-		/* Local copy matched */
-		if (completion)
-			completion(TRUE, context);
-		g_free(verify->filename);
-		g_free(verify->entity);
-		g_free(verify->entity_name);
-		silc_free(verify->fingerprint);
-		silc_free(verify->babbleprint);
-		silc_pkcs_public_key_free(verify->public_key);
-		silc_free(verify);
-	}
-}
Binary file libpurple/protocols/silc/resources/icons/16x16/apps/im-silc.png has changed
--- a/libpurple/protocols/silc/resources/icons/16x16/apps/scalable/im-silc.svg	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,173 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="16px"
-   height="16px"
-   id="svg4248"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
-   sodipodi:docname="silc.svg"
-   inkscape:export-filename="/home/hbons/Bureaublad/silc.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4250">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8658">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop8660" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop8662" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient8641">
-      <stop
-         style="stop-color:#ccf4a7;stop-opacity:1"
-         offset="0"
-         id="stop8643" />
-      <stop
-         style="stop-color:#73d216;stop-opacity:1"
-         offset="1"
-         id="stop8645" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient8633">
-      <stop
-         style="stop-color:#346a02;stop-opacity:1;"
-         offset="0"
-         id="stop8635" />
-      <stop
-         style="stop-color:#54ac02;stop-opacity:1"
-         offset="1"
-         id="stop8637" />
-    </linearGradient>
-    <linearGradient
-       id="linearGradient2222"
-       inkscape:collect="always">
-      <stop
-         id="stop2224"
-         offset="0"
-         style="stop-color:#8ae234;stop-opacity:1;" />
-      <stop
-         id="stop2226"
-         offset="1"
-         style="stop-color:#8ae234;stop-opacity:0;" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2222"
-       id="linearGradient5731"
-       gradientUnits="userSpaceOnUse"
-       x1="13.638538"
-       y1="11.020223"
-       x2="13.638538"
-       y2="-28.749279"
-       gradientTransform="matrix(0.797619,0,0,0.940287,-21.494048,-2.875489)" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2222"
-       id="linearGradient5739"
-       gradientUnits="userSpaceOnUse"
-       x1="13.638538"
-       y1="11.020223"
-       x2="13.638538"
-       y2="-28.749279" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8633"
-       id="linearGradient8639"
-       x1="10.13271"
-       y1="9.9967499"
-       x2="7.509789"
-       y2="6.4700642"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8641"
-       id="linearGradient8647"
-       x1="4.010623"
-       y1="5.2489076"
-       x2="10.514683"
-       y2="11.829373"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient8658"
-       id="linearGradient8664"
-       x1="3.8175509"
-       y1="5.2679143"
-       x2="10.938335"
-       y2="10.646874"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="27.3287"
-     inkscape:cx="21.250133"
-     inkscape:cy="8.5563256"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     inkscape:grid-bbox="true"
-     inkscape:document-units="px"
-     inkscape:window-width="1440"
-     inkscape:window-height="847"
-     inkscape:window-x="0"
-     inkscape:window-y="0"
-     inkscape:snap-bbox="true"
-     inkscape:snap-nodes="false"
-     objecttolerance="10"
-     gridtolerance="10">
-    <inkscape:grid
-       type="xygrid"
-       id="grid8623"
-       visible="true"
-       enabled="true" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata4253">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     id="layer1"
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer">
-    <path
-       style="opacity:1;fill:url(#linearGradient8647);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8639);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-       d="M 7.4939374,1.4832176 C 6.9292248,1.4832176 6.489473,1.9229695 6.489473,2.487682 L 6.489473,11.522046 L 1.5714286,11.522046 C 0.98499647,11.522046 0.5,12.007042 0.5,12.593475 L 0.5,13.445354 C 0.5,14.031787 0.98499647,14.516783 1.5714286,14.516783 L 8.4398609,14.516783 C 9.0262932,14.516783 9.5112895,14.031787 9.5112895,13.445354 L 9.5112895,4.4905103 L 14.495536,4.4905103 C 15.060249,4.4905103 15.500001,4.0507584 15.500001,3.4860459 L 15.500001,2.487682 C 15.500001,1.9229694 15.060249,1.4832176 14.495536,1.4832176 L 7.4939374,1.4832176 z"
-       id="rect8625"
-       sodipodi:nodetypes="ccccccccccccccc" />
-    <path
-       style="opacity:1;fill:url(#linearGradient8664);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-       d="M 7.5,2.0000003 C 7.2189639,2.0000003 7,2.2189642 7,2.5000003 L 7,12 L 1.5,12 C 1.2189639,12 1,12.223 1,12.5 C 1,12.777 1.2189639,13 1.5,13 L 7.5,13 C 7.5604228,13 7.6338463,12.987963 7.6875,12.96875 C 7.7482316,12.943516 7.7979041,12.888938 7.84375,12.84375 C 7.8975454,12.794761 7.9400258,12.755638 7.96875,12.6875 C 7.9943521,12.627641 8,12.56925 8,12.5 L 8,3.0000003 L 14.5,3.0000003 C 14.781036,3.0000003 15,2.7810364 15,2.5000003 C 15,2.2189642 14.781036,2.0000003 14.5,2.0000003 C 12.16669,1.9999996 9.8332346,2.0000003 7.5,2.0000003 z"
-       id="rect8649"
-       sodipodi:nodetypes="ccccsccssscccscc" />
-  </g>
-</svg>
Binary file libpurple/protocols/silc/resources/icons/22x22/apps/im-silc.png has changed
--- a/libpurple/protocols/silc/resources/icons/22x22/apps/scalable/im-silc.svg	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="24"
-   height="24"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh"
-   sodipodi:docname="silc.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/silc.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2222">
-      <stop
-         style="stop-color:#8ae234;stop-opacity:1;"
-         offset="0"
-         id="stop2224" />
-      <stop
-         style="stop-color:#8ae234;stop-opacity:0;"
-         offset="1"
-         id="stop2226" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3150">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop3152" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop3154" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3150"
-       id="radialGradient3156"
-       cx="10.748654"
-       cy="10.457643"
-       fx="10.748654"
-       fy="10.457643"
-       r="6.6449099"
-       gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2222"
-       id="linearGradient2228"
-       x1="14.315197"
-       y1="11.002394"
-       x2="13.638538"
-       y2="-28.749279"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="7.3892443"
-     inkscape:cx="17.369816"
-     inkscape:cy="12.086934"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#9db029"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.35;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3140"
-       sodipodi:cx="10.748654"
-       sodipodi:cy="10.457643"
-       sodipodi:rx="6.6449099"
-       sodipodi:ry="2.3675451"
-       d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1  4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1  17.393564 10.457643 z"
-       transform="matrix(1.655403,0,0,1.300982,-5.793351,5.474929)" />
-    <path
-       style="opacity:1;fill:url(#linearGradient2228);fill-opacity:1.0;stroke:#4e9a06;stroke-width:0.99999964;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 10.494577,6.2547874 C 10.494577,6.7069733 10.550854,14.667436 10.504973,15.531249 C 10.504973,15.531249 4.6361995,15.499999 4.5312498,15.499999 C 3.411786,15.499999 2.4999998,16.35618 2.4999998,17.526317 C 2.4999998,18.690466 3.411786,19.504787 4.5312498,19.504787 L 11.27063,19.504787 C 13.660042,19.504787 14.5625,18.376459 14.5625,16.754787 C 14.5625,16.302601 14.434213,7.3539406 14.486856,6.5047874 C 14.486856,6.5047874 20.224476,6.5047874 20.574309,6.5047874 C 21.693773,6.5047874 22.635012,5.5969416 22.635012,4.430623 C 22.635012,3.6010066 21.693772,2.4999998 20.574309,2.4999998 L 13.59375,2.4999998 C 12.029203,2.4999998 10.494577,3.5345411 10.494577,6.2547874 z "
-       id="rect3167"
-       sodipodi:nodetypes="ccssscscssscs" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0003172"
-       inkscape:original="M 13.59375 2.5 C 12.029203 2.5 10.5 3.5297537 10.5 6.25 C 10.5 6.7021859 10.545881 14.667437 10.5 15.53125 C 10.5 15.53125 4.6361997 15.5 4.53125 15.5 C 3.411786 15.5 2.5 16.361113 2.5 17.53125 C 2.5 18.695398 3.4117862 19.5 4.53125 19.5 L 11.28125 19.5 C 13.670662 19.5 14.5625 18.371672 14.5625 16.75 C 14.5625 16.297814 14.447357 7.3491532 14.5 6.5 C 14.5 6.5 20.212667 6.5 20.5625 6.5 C 21.681965 6.5 22.625 5.6038186 22.625 4.4375 C 22.625 3.6078835 21.681963 2.5 20.5625 2.5 L 13.59375 2.5 z "
-       xlink:href="#rect3167"
-       style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999964;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3189"
-       inkscape:href="#rect3167"
-       d="M 13.59375,3.5 C 13.030939,3.5 12.555105,3.6824271 12.1875,4.0625 C 11.819895,4.4425729 11.5,5.0773217 11.5,6.25 C 11.5,6.4422606 11.52551,8.5611209 11.53125,10.71875 C 11.53699,12.876379 11.532515,14.981588 11.5,15.59375 C 11.466751,16.121392 11.028688,16.532076 10.5,16.53125 C 10.5,16.53125 9.0415375,16.539062 7.5625,16.53125 C 6.0834625,16.523438 4.4844395,16.5 4.53125,16.5 C 3.9247614,16.5 3.5,16.880753 3.5,17.53125 C 3.5,18.173084 3.8910974,18.5 4.53125,18.5 L 11.28125,18.5 C 12.318499,18.5 12.844693,18.260508 13.125,18 C 13.405307,17.739492 13.5625,17.377461 13.5625,16.75 C 13.5625,16.608813 13.522223,14.183039 13.5,11.78125 C 13.488888,10.580356 13.503404,9.3752554 13.5,8.40625 C 13.496596,7.4372446 13.478732,6.7805618 13.5,6.4375 C 13.533249,5.9098578 13.971312,5.4991739 14.5,5.5 C 14.5,5.5 20.212667,5.5 20.5625,5.5 C 21.148099,5.5 21.625,5.0646096 21.625,4.4375 C 21.625,4.4017167 21.537161,4.1026393 21.3125,3.875 C 21.087839,3.6473607 20.792241,3.5 20.5625,3.5 L 13.59375,3.5 z " />
-    <image
-       id="image1322"
-       height="58.310913"
-       width="58.310913"
-       sodipodi:absref="/home/hbons/Desktop/Tango-Palette.png"
-       xlink:href="/home/hbons/Desktop/Tango-Palette.png"
-       x="-67.310913"
-       y="-20.310913" />
-  </g>
-</svg>
Binary file libpurple/protocols/silc/resources/icons/48x48/apps/im-silc.png has changed
--- a/libpurple/protocols/silc/resources/icons/scalable/apps/im-silc.svg	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="48"
-   height="48"
-   id="svg2"
-   sodipodi:version="0.32"
-   inkscape:version="0.46"
-   version="1.0"
-   sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
-   sodipodi:docname="silc.svg"
-   inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/silc.png"
-   inkscape:export-xdpi="90"
-   inkscape:export-ydpi="90"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
-  <defs
-     id="defs4">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2193">
-      <stop
-         style="stop-color:#ffffff;stop-opacity:1;"
-         offset="0"
-         id="stop2195" />
-      <stop
-         style="stop-color:#ffffff;stop-opacity:0;"
-         offset="1"
-         id="stop2197" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient2222">
-      <stop
-         style="stop-color:#8ae234;stop-opacity:1;"
-         offset="0"
-         id="stop2224" />
-      <stop
-         style="stop-color:#8ae234;stop-opacity:0;"
-         offset="1"
-         id="stop2226" />
-    </linearGradient>
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient3150">
-      <stop
-         style="stop-color:#2e3436;stop-opacity:1;"
-         offset="0"
-         id="stop3152" />
-      <stop
-         style="stop-color:#2e3436;stop-opacity:0;"
-         offset="1"
-         id="stop3154" />
-    </linearGradient>
-    <radialGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient3150"
-       id="radialGradient3156"
-       cx="10.748654"
-       cy="10.457643"
-       fx="10.748654"
-       fy="10.457643"
-       r="6.6449099"
-       gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
-       gradientUnits="userSpaceOnUse" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2222"
-       id="linearGradient1318"
-       gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(2.08567,0,0,1.999113,-1.709138,-1.492105)"
-       x1="14.315197"
-       y1="11.002394"
-       x2="13.638538"
-       y2="-28.749279" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient2193"
-       id="linearGradient2203"
-       x1="20.834801"
-       y1="17.936523"
-       x2="26.154163"
-       y2="21.007658"
-       gradientUnits="userSpaceOnUse" />
-  </defs>
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="13.788817"
-     inkscape:cx="35.001851"
-     inkscape:cy="20.952874"
-     inkscape:document-units="px"
-     inkscape:current-layer="layer1"
-     showgrid="true"
-     fill="#9db029"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:window-width="1268"
-     inkscape:window-height="971"
-     inkscape:window-x="6"
-     inkscape:window-y="21" />
-  <metadata
-     id="metadata7">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.35;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path3140"
-       sodipodi:cx="10.748654"
-       sodipodi:cy="10.457643"
-       sodipodi:rx="6.6449099"
-       sodipodi:ry="2.3675451"
-       d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1  4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1  17.393564 10.457643 z"
-       transform="matrix(3.461296,0,0,2.111892,-13.20427,14.91459)" />
-    <path
-       style="opacity:1;fill:url(#linearGradient1318);fill-opacity:1;stroke:#4e9a06;stroke-width:0.99999911;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 20.489949,11.011929 C 20.489949,11.915899 20.607326,27.829773 20.511631,29.556634 C 20.511631,29.556634 7.9604471,29.494161 7.7415566,29.494161 C 5.406724,29.494161 3.5050383,31.205765 3.5050383,33.545004 C 3.5050383,35.87227 5.406724,37.500189 7.7415566,37.500189 L 21.797683,37.500189 C 26.78121,37.500189 28.663439,35.244533 28.663439,32.002624 C 28.663439,31.098653 28.395875,13.209261 28.505671,11.511706 C 28.505671,11.511706 40.472455,11.511706 41.202093,11.511706 C 43.536926,11.511706 45.50004,9.6968193 45.50004,7.3652154 C 45.50004,5.7067176 43.536923,3.5056793 41.202093,3.5056793 L 26.642947,3.5056793 C 23.379817,3.5056793 20.489949,5.5738454 20.489949,11.011929 z "
-       id="rect3167"
-       sodipodi:nodetypes="ccssscscssscs" />
-    <path
-       sodipodi:type="inkscape:offset"
-       inkscape:radius="-1.0564219"
-       inkscape:original="M 26.65625 3.5 C 23.393121 3.4999999 20.5 5.5619164 20.5 11 C 20.500001 11.90397 20.595695 27.835639 20.5 29.5625 C 20.5 29.562499 7.9688905 29.5 7.75 29.5 C 5.4151674 29.499999 3.5 31.192011 3.5 33.53125 C 3.5 35.858514 5.4151674 37.5 7.75 37.5 L 21.8125 37.5 C 26.796026 37.499998 28.65625 35.241909 28.65625 32 C 28.65625 31.096028 28.390204 13.197555 28.5 11.5 C 28.5 11.5 40.457862 11.5 41.1875 11.5 C 43.522335 11.5 45.5 9.7066039 45.5 7.375 C 45.500002 5.7165023 43.52233 3.5 41.1875 3.5 L 26.65625 3.5 z "
-       xlink:href="#rect3167"
-       style="opacity:0.5;fill:url(#linearGradient2203);fill-opacity:1.0;stroke:#ffffff;stroke-width:0.99999964;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       id="path1316"
-       inkscape:href="#rect3167"
-       d="M 26.65625,4.53125 C 25.249537,4.53125 24.032886,4.9412683 23.125,5.90625 C 22.217114,6.8712317 21.5625,8.4647612 21.5625,11 C 21.5625,11.415298 21.581781,15.655374 21.59375,19.96875 C 21.605719,24.282126 21.621325,28.562355 21.5625,29.625 C 21.532315,30.188634 21.064428,30.628998 20.5,30.625 C 20.5,30.625 17.347604,30.609375 14.1875,30.59375 C 11.027396,30.578125 7.758935,30.5625 7.75,30.5625 C 5.9336242,30.562499 4.5625,31.79623 4.5625,33.5625 C 4.5625,35.313821 5.8995405,36.4375 7.75,36.4375 L 21.78125,36.4375 C 24.114194,36.4375 25.537737,35.928156 26.375,35.1875 C 27.212263,34.446844 27.59375,33.417796 27.59375,32 C 27.59375,31.65099 27.521563,26.864091 27.46875,22.0625 C 27.442343,19.661704 27.415771,17.24736 27.40625,15.3125 C 27.396729,13.37764 27.400585,12.008829 27.4375,11.4375 C 27.467685,10.873866 27.935572,10.433502 28.5,10.4375 C 28.5,10.4375 40.457735,10.4375 41.1875,10.4375 C 42.9733,10.4375 44.4375,9.0816356 44.4375,7.34375 C 44.4375,6.9328186 44.123387,6.1347887 43.5,5.53125 C 42.876613,4.9277113 42.021185,4.53125 41.1875,4.53125 L 26.65625,4.53125 z " />
-  </g>
-</svg>
--- a/libpurple/protocols/silc/resources/silc.gresource.xml	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<gresources>
-  <gresource prefix="/im/pidgin/libpurple/silc">
-    <file>icons/16x16/apps/im-silc.png</file>
-    <file>icons/16x16/apps/scalable/im-silc.svg</file>
-    <file>icons/22x22/apps/im-silc.png</file>
-    <file>icons/22x22/apps/scalable/im-silc.svg</file>
-    <file>icons/48x48/apps/im-silc.png</file>
-    <file>icons/scalable/apps/im-silc.svg</file>
-  </gresource>
-</gresources>
--- a/libpurple/protocols/silc/silc.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2583 +0,0 @@
-/*
-
-  silcpurple.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include <glib/gi18n-lib.h>
-#include <glib/gstdio.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include "silcpurple.h"
-#include "ft.h"
-#include "wb.h"
-
-struct _SilcProtocol {
-	PurpleProtocol parent;
-};
-
-extern SilcClientOperations ops;
-
-static PurpleProtocol *my_protocol = NULL;
-static GSList *cmds = NULL;
-
-/* Error log message callback */
-
-static SilcBool silcpurple_log_error(SilcLogType type, char *message,
-				     void *context)
-{
-	silc_say(NULL, NULL, SILC_CLIENT_MESSAGE_ERROR, message);
-	return TRUE;
-}
-
-static void
-silcpurple_free(SilcPurple sg)
-{
-	g_return_if_fail(sg != NULL);
-
-	g_cancellable_cancel(sg->cancellable);
-	g_clear_object(&sg->cancellable);
-	g_clear_object(&sg->sockconn);
-
-	g_clear_pointer(&sg->client, silc_client_free);
-	g_clear_pointer(&sg->sha1hash, silc_hash_free);
-	g_clear_pointer(&sg->mimeass, silc_mime_assembler_free);
-
-	g_clear_pointer(&sg->public_key, silc_pkcs_public_key_free);
-	g_clear_pointer(&sg->private_key, silc_pkcs_private_key_free);
-
-	silc_free(sg);
-}
-
-static GList *
-silcpurple_away_states(G_GNUC_UNUSED PurpleProtocol *protocol,
-                       PurpleAccount *account)
-{
-	PurpleStatusType *type;
-	GList *types = NULL;
-
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_AVAILABLE, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AVAILABLE, SILCPURPLE_STATUS_ID_HYPER, _("Hyper Active"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_AWAY, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE, SILCPURPLE_STATUS_ID_BUSY, _("Busy"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_INDISPOSED, _("Indisposed"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_AWAY, SILCPURPLE_STATUS_ID_PAGE, _("Wake Me Up"), TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-	type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, SILCPURPLE_STATUS_ID_OFFLINE, NULL, TRUE, TRUE, FALSE);
-	types = g_list_append(types, type);
-
-	return types;
-}
-
-static void
-silcpurple_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status)
-{
-	PurpleConnection *gc = purple_account_get_connection(account);
-	SilcPurple sg = NULL;
-	SilcUInt32 mode;
-	SilcBuffer idp;
-	unsigned char mb[4];
-	const char *state;
-
-	if (gc != NULL)
-		sg = purple_connection_get_protocol_data(gc);
-
-	if (status == NULL)
-		return;
-
-	state = purple_status_get_id(status);
-
-	if (state == NULL)
-		return;
-
-	if ((sg == NULL) || (sg->conn == NULL))
-		return;
-
-	mode = sg->conn->local_entry->mode;
-	mode &= ~(SILC_UMODE_GONE |
-		  SILC_UMODE_HYPER |
-		  SILC_UMODE_BUSY |
-		  SILC_UMODE_INDISPOSED |
-		  SILC_UMODE_PAGE);
-
-	if (purple_strequal(state, "hyper"))
-		mode |= SILC_UMODE_HYPER;
-	else if (purple_strequal(state, "away"))
-		mode |= SILC_UMODE_GONE;
-	else if (purple_strequal(state, "busy"))
-		mode |= SILC_UMODE_BUSY;
-	else if (purple_strequal(state, "indisposed"))
-		mode |= SILC_UMODE_INDISPOSED;
-	else if (purple_strequal(state, "page"))
-		mode |= SILC_UMODE_PAGE;
-
-	/* Send UMODE */
-	idp = silc_id_payload_encode(sg->conn->local_id, SILC_ID_CLIENT);
-	SILC_PUT32_MSB(mode, mb);
-	silc_client_command_send(sg->client, sg->conn, SILC_COMMAND_UMODE,
-				 silcpurple_command_reply, NULL, 2,
-				 1, idp->data, silc_buffer_len(idp),
-				 2, mb, sizeof(mb));
-	silc_buffer_free(idp);
-}
-
-
-/*************************** Connection Routines *****************************/
-
-static void
-silcpurple_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *gc)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0,
-			 NULL, 0);
-}
-
-typedef struct {
-  SilcPurple sg;
-  SilcUInt32 fd;
-  guint tag;
-} *SilcPurpleTask;
-
-/* A timeout occurred.  Call SILC scheduler. */
-
-static gboolean
-silcpurple_scheduler_timeout(gpointer context)
-{
-	SilcPurpleTask task = (SilcPurpleTask)context;
-	silc_client_run_one(task->sg->client);
-	silc_dlist_del(task->sg->tasks, task);
-	silc_free(task);
-	return FALSE;
-}
-
-/* An fd task event occurred.  Call SILC scheduler. */
-
-static void
-silcpurple_scheduler_fd(gpointer data, gint fd, PurpleInputCondition cond)
-{
-	SilcClient client = (SilcClient)data;
-	silc_client_run_one(client);
-}
-
-/* SILC Scheduler notify callback.  This is called whenever task is added to
-   or deleted from SILC scheduler.  It's also called when fd task events
-   change.  Here we add same tasks to glib's main loop. */
-
-static void
-silcpurple_scheduler(SilcSchedule schedule,
-		     SilcBool added, SilcTask task,
-		     SilcBool fd_task, SilcUInt32 fd,
-		     SilcTaskEvent event,
-		     long seconds, long useconds,
-		     void *context)
-{
-	SilcClient client = (SilcClient)context;
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcPurpleTask ptask = NULL;
-
-	if (added) {
-	  if (fd_task) {
-	    /* Add fd or change fd events */
-	    PurpleInputCondition e = 0;
-
-	    silc_dlist_start(sg->tasks);
-	    while ((ptask = silc_dlist_get(sg->tasks)))
-	      if (ptask->fd == fd) {
-		g_source_remove(ptask->tag);
-		break;
-	      }
-
-	    if (event & SILC_TASK_READ)
-	      e |= PURPLE_INPUT_READ;
-	    if (event & SILC_TASK_WRITE)
-	      e |= PURPLE_INPUT_WRITE;
-
-	    if (e) {
-	      if (!ptask) {
-		ptask = silc_calloc(1, sizeof(*ptask));
-		ptask->fd = fd;
-		silc_dlist_add(sg->tasks, ptask);
-	      }
-	      ptask->tag = purple_input_add(fd, e, silcpurple_scheduler_fd,
-					    client);
-	    } else if (ptask) {
-	      silc_dlist_del(sg->tasks, ptask);
-	      silc_free(ptask);
-	    }
-	  } else {
-	    /* Add timeout */
-	    ptask = silc_calloc(1, sizeof(*ptask));
-	    ptask->sg = sg;
-	    ptask->tag = g_timeout_add((seconds * 1000) +
-					    (useconds / 1000),
-					    silcpurple_scheduler_timeout,
-					    ptask);
-	    silc_dlist_add(sg->tasks, ptask);
-	  }
-	} else {
-	  if (fd_task) {
-	    /* Remove fd */
-	    silc_dlist_start(sg->tasks);
-	    while ((ptask = silc_dlist_get(sg->tasks)))
-	      if (ptask->fd == fd) {
-		g_source_remove(ptask->tag);
-		silc_dlist_del(sg->tasks, ptask);
-		silc_free(ptask);
-		break;
-	      }
-	  }
-	}
-}
-
-static void
-silcpurple_connect_cb(SilcClient client, SilcClientConnection conn,
-		      SilcClientConnectionStatus status, SilcStatus error,
-		      const char *message, void *context)
-{
-	PurpleConnection *gc = context;
-	SilcPurple sg;
-	SilcUInt32 mask;
-	char tz[16];
-	PurpleImage *img;
-#ifdef HAVE_SYS_UTSNAME_H
-	struct utsname u;
-#endif
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	switch (status) {
-	case SILC_CLIENT_CONN_SUCCESS:
-	case SILC_CLIENT_CONN_SUCCESS_RESUME:
-		sg->conn = conn;
-
-		/* Connection created successfully */
-		purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED);
-
-		/* Send the server our buddy list */
-		silcpurple_send_buddylist(gc);
-
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-
-		/* Send any UMODEs configured for account */
-		if (purple_account_get_bool(sg->account, "block-ims", FALSE)) {
-			silc_client_command_call(sg->client, sg->conn, NULL,
-						 "UMODE", "+P", NULL);
-		}
-
-		/* Set default attributes */
-		mask = SILC_ATTRIBUTE_MOOD_NORMAL;
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_STATUS_MOOD,
-					  SILC_32_TO_PTR(mask),
-					  sizeof(SilcUInt32));
-		mask = SILC_ATTRIBUTE_CONTACT_CHAT;
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_PREFERRED_CONTACT,
-					  SILC_32_TO_PTR(mask),
-					  sizeof(SilcUInt32));
-#ifdef HAVE_SYS_UTSNAME_H
-		if (!uname(&u)) {
-			SilcAttributeObjDevice dev;
-			memset(&dev, 0, sizeof(dev));
-			dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
-			dev.version = u.release;
-			dev.model = u.sysname;
-			silc_client_attribute_add(client, conn,
-						  SILC_ATTRIBUTE_DEVICE_INFO,
-						  (void *)&dev, sizeof(dev));
-		}
-#endif
-		silc_timezone(tz, sizeof(tz));
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_TIMEZONE,
-					  (void *)tz, strlen(tz));
-
-		/* Set our buddy icon */
-		img = purple_buddy_icons_find_account_icon(sg->account);
-		silcpurple_buddy_set_icon(NULL, gc, img);
-		g_object_unref(img);
-
-		return;
-		break;
-
-	case SILC_CLIENT_CONN_DISCONNECTED:
-		/* Disconnected */
-		if (sg->resuming && !sg->detaching)
-		  g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-
-		/* Close the connection */
-		if (!sg->detaching)
-		  purple_connection_error(gc,
-		                                 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                                 _("Disconnected by server"));
-		else
-		  /* TODO: Does this work correctly? Maybe we need to set wants_to_die? */
-		  purple_account_disconnect(purple_connection_get_account(gc));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR:
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                             _("Error connecting to SILC Server"));
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_KE:
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-		                             _("Key Exchange failed"));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_AUTH:
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
-		                             _("Authentication failed"));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_RESUME:
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Resuming detached session failed. "
-		                               "Press Reconnect to create new connection."));
-		g_unlink(silcpurple_session_file(purple_account_get_username(sg->account)));
-		break;
-
-	case SILC_CLIENT_CONN_ERROR_TIMEOUT:
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-		                             _("Connection timed out"));
-		break;
-	}
-
-	/* Error */
-	sg->conn = NULL;
-}
-
-static void
-silcpurple_stream_created(SilcSocketStreamStatus status, SilcStream stream,
-			  void *context)
-{
-	PurpleConnection *gc = context;
-	SilcPurple sg;
-	SilcClient client;
-	SilcClientConnectionParams params;
-	const char *dfile;
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (status != SILC_SOCKET_OK) {
-		purple_connection_error(gc,
-			PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-			_("Connection failed"));
-		silcpurple_free(sg);
-		purple_connection_set_protocol_data(gc, NULL);
-		return;
-	}
-
-	client = sg->client;
-
-	/* Get session detachment data, if available */
-	memset(&params, 0, sizeof(params));
-	dfile = silcpurple_session_file(purple_account_get_username(sg->account));
-	params.detach_data = (unsigned char *)silc_file_readfile(dfile, &params.detach_data_len);
-	if (params.detach_data)
-		params.detach_data[params.detach_data_len] = 0;
-	params.ignore_requested_attributes = FALSE;
-	params.pfs = purple_account_get_bool(sg->account, "pfs", FALSE);
-
-	/* Progress */
-	if (params.detach_data) {
-		sg->resuming = TRUE;
-	}
-
-	/* Perform SILC Key Exchange. */
-	silc_client_key_exchange(client, &params, sg->public_key,
-				 sg->private_key, stream, SILC_CONN_SERVER,
-				 silcpurple_connect_cb, gc);
-
-	silc_free(params.detach_data);
-}
-
-static void
-silcpurple_login_connected(GObject *source, GAsyncResult *res, gpointer data)
-{
-	PurpleConnection *gc = data;
-	SilcPurple sg;
-	GSocketConnection *conn;
-	GSocket *socket;
-	gint fd;
-	GError *error = NULL;
-
-	g_return_if_fail(gc != NULL);
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
-			res, &error);
-	if (conn == NULL) {
-		if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
-			purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-						     _("Connection failed"));
-			silcpurple_free(sg);
-			purple_connection_set_protocol_data(gc, NULL);
-		}
-
-		g_clear_error(&error);
-		return;
-	}
-
-	socket = g_socket_connection_get_socket(conn);
-	g_assert(socket != NULL);
-
-	fd = g_socket_get_fd(socket);
-	sg->sockconn = conn;
-
-	silc_hash_alloc((unsigned char *)"sha1", &sg->sha1hash);
-
-	/* Wrap socket to TCP stream */
-	silc_socket_tcp_stream_create(fd, TRUE, FALSE,
-				      sg->client->schedule,
-				      silcpurple_stream_created, gc);
-}
-
-static void silcpurple_continue_running(SilcPurple sg)
-{
-	PurpleConnection *gc = sg->gc;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	GSocketClient *client;
-	GError *error = NULL;
-
-	client = purple_gio_socket_client_new(account, &error);
-	if (client == NULL) {
-		/* Assume it's a proxy error */
-		purple_notify_error(NULL, NULL, _("Invalid proxy settings"),
-			error->message,
-			purple_request_cpar_from_account(account));
-		purple_connection_take_error(gc, error);
-		purple_connection_set_protocol_data(gc, NULL);
-		silcpurple_free(sg);
-		return;
-	}
-
-	/* Connect to the SILC server */
-	g_socket_client_connect_to_host_async(client,
-				 purple_account_get_string(account, "server",
-							   "silc.silcnet.org"),
-				 purple_account_get_int(account, "port", 706),
-				 sg->cancellable, silcpurple_login_connected, gc);
-	g_object_unref(client);
-}
-
-static void silcpurple_got_password_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	PurpleAccount *account = purple_connection_get_account(gc);
-	char pkd[256], prd[256];
-	const char *password;
-	gboolean remember;
-	PurpleCredentialManager *manager;
-
-	/* TODO: the password prompt dialog doesn't get disposed if the account disconnects */
-	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
-
-	password = purple_request_fields_get_string(fields, "password");
-	remember = purple_request_fields_get_bool(fields, "remember");
-
-	if (!password || !*password)
-	{
-		purple_notify_error(gc, NULL,
-			_("Password is required to sign on."), NULL,
-			purple_request_cpar_from_connection(gc));
-		purple_connection_set_protocol_data(gc, NULL);
-		silcpurple_free(sg);
-		return;
-	}
-
-	if (remember)
-		purple_account_set_remember_password(account, TRUE);
-
-	manager = purple_credential_manager_get_default();
-	purple_credential_manager_write_password_async(manager, account, password,
-	                                               NULL, NULL, NULL);
-
-	/* Load SILC key pair */
-	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
-	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
-	if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd),
-				(char *)purple_account_get_string(account, "private-key", prd),
-				password,
-				&sg->public_key, &sg->private_key)) {
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Unable to load SILC key pair"));
-		purple_connection_set_protocol_data(gc, NULL);
-		silcpurple_free(sg);
-		return;
-	}
-	silcpurple_continue_running(sg);
-}
-
-static void silcpurple_no_password_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	SilcPurple sg;
-
-	/* TODO: the password prompt dialog doesn't get disposed if the account disconnects */
-	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
-
-	sg = purple_connection_get_protocol_data(gc);
-	purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-			_("Unable to load SILC key pair"));
-	purple_connection_set_protocol_data(gc, NULL);
-	silcpurple_free(sg);
-}
-
-static void silcpurple_running(SilcClient client, void *context)
-{
-	SilcPurple sg = context;
-	PurpleConnection *gc = sg->gc;
-	PurpleAccount *account = purple_connection_get_account(gc);
-	char pkd[256], prd[256];
-
-
-	/* Load SILC key pair */
-	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
-	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
-	if (!silc_load_key_pair((char *)purple_account_get_string(account, "public-key", pkd),
-				(char *)purple_account_get_string(account, "private-key", prd),
-				(purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
-				&sg->public_key, &sg->private_key)) {
-		if (!purple_connection_get_password(gc)) {
-			purple_account_request_password(account, G_CALLBACK(silcpurple_got_password_cb),
-											G_CALLBACK(silcpurple_no_password_cb), gc);
-			return;
-		}
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Unable to load SILC key pair"));
-		purple_connection_set_protocol_data(gc, NULL);
-		silcpurple_free(sg);
-		return;
-	}
-	silcpurple_continue_running(sg);
-}
-
-static void
-silcpurple_login(G_GNUC_UNUSED PurpleProtocol *protocol,
-                 PurpleAccount *account)
-{
-	SilcClient client;
-	PurpleConnection *gc;
-	SilcPurple sg;
-	SilcClientParams params;
-	const char *cipher, *hmac;
-	char *username, *hostname, *realname, **up;
-	int i;
-
-	gc = purple_account_get_connection(account);
-	if (!gc)
-		return;
-
-	purple_connection_set_protocol_data(gc, NULL);
-
-	memset(&params, 0, sizeof(params));
-	strcat(params.nickname_format, "%n#a");
-
-	/* Allocate SILC client */
-	client = silc_client_alloc(&ops, &params, gc, NULL);
-	if (!client) {
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Out of memory"));
-		return;
-	}
-
-	/* Get username, real name and local hostname for SILC library */
-	if (!purple_account_get_username(account))
-		purple_account_set_username(account, silc_get_username());
-
-	username = (char *)purple_account_get_username(account);
-	up = g_strsplit(username, "@", 2);
-	username = g_strdup(up[0]);
-	g_strfreev(up);
-
-	if (!purple_account_get_user_info(account)) {
-		purple_account_set_user_info(account, silc_get_real_name());
-		if (!purple_account_get_user_info(account))
-			purple_account_set_user_info(account,
-						     "John T. Noname");
-	}
-	realname = (char *)purple_account_get_user_info(account);
-	hostname = silc_net_localhost();
-
-	purple_connection_set_display_name(gc, username);
-
-	/* Register requested cipher and HMAC */
-	cipher = purple_account_get_string(account, "cipher",
-					   SILC_DEFAULT_CIPHER);
-	for (i = 0; silc_default_ciphers[i].name; i++)
-		if (purple_strequal(silc_default_ciphers[i].name, cipher)) {
-			silc_cipher_register(&(silc_default_ciphers[i]));
-			break;
-		}
-	hmac = purple_account_get_string(account, "hmac", SILC_DEFAULT_HMAC);
-	for (i = 0; silc_default_hmacs[i].name; i++)
-		if (purple_strequal(silc_default_hmacs[i].name, hmac)) {
-			silc_hmac_register(&(silc_default_hmacs[i]));
-			break;
-		}
-
-	sg = silc_calloc(1, sizeof(*sg));
-	if (!sg)
-		return;
-	sg->cancellable = g_cancellable_new();
-	sg->client = client;
-	sg->gc = gc;
-	sg->account = account;
-	purple_connection_set_protocol_data(gc, sg);
-
-	/* Init SILC client */
-	if (!silc_client_init(client, username, hostname, realname,
-			      silcpurple_running, sg)) {
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Unable to initialize SILC protocol"));
-		purple_connection_set_protocol_data(gc, NULL);
-		silcpurple_free(sg);
-		silc_free(hostname);
-		g_free(username);
-		return;
-	}
-	silc_free(hostname);
-	g_free(username);
-
-	/* Check the ~/.silc dir and create it, and new key pair if necessary. */
-	if (!silcpurple_check_silc_dir(gc)) {
-		purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-		                             _("Error loading SILC key pair"));
-		purple_connection_set_protocol_data(gc, NULL);
-		silcpurple_free(sg);
-		return;
-	}
-
-	/* Run SILC scheduler */
-	sg->tasks = silc_dlist_init();
-	silc_schedule_set_notify(client->schedule, silcpurple_scheduler,
-				 client);
-	silc_client_run_one(client);
-}
-
-static int
-silcpurple_close_final(gpointer *context)
-{
-	SilcPurple sg = (SilcPurple)context;
-
-	purple_debug_info("silc", "Finalizing SilcPurple %p\n", sg);
-
-	silc_client_stop(sg->client, NULL, NULL);
-
-	silcpurple_free(sg);
-	return 0;
-}
-
-static gchar *
-silcpurple_get_quit_message(void)
-{
-	PurpleUiInfo *ui_info;
-	const char *ui_name = NULL, *ui_website = NULL;
-	char *quit_msg;
-
-	ui_info = purple_core_get_ui_info();
-	if (PURPLE_IS_UI_INFO(ui_info)) {
-		ui_name = purple_ui_info_get_name(ui_info);
-		ui_website = purple_ui_info_get_website(ui_info);
-	}
-
-	if (!ui_name || !ui_website) {
-		ui_name = "Pidgin";
-		ui_website = PURPLE_WEBSITE;
-	}
-
-	quit_msg = g_strdup_printf(_("Download %s: %s"), ui_name, ui_website);
-
-	return quit_msg;
-}
-
-static void
-silcpurple_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection *gc)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcPurpleTask task;
-	char *quit_msg;
-
-	g_return_if_fail(sg != NULL);
-
-	quit_msg = silcpurple_get_quit_message();
-
-	/* Send QUIT */
-	silc_client_command_call(sg->client, sg->conn, NULL,
-	                         "QUIT", quit_msg, NULL);
-	g_free(quit_msg);
-
-	if (sg->conn)
-		silc_client_close_connection(sg->client, sg->conn);
-
-	if (sg->conn)
-	  silc_client_run_one(sg->client);
-	silc_schedule_set_notify(sg->client->schedule, NULL, NULL);
-
-	silc_dlist_start(sg->tasks);
-	while ((task = silc_dlist_get(sg->tasks))) {
-	  g_source_remove(task->tag);
-	  silc_free(task);
-	}
-	silc_dlist_uninit(sg->tasks);
-
-	if (sg->scheduler)
-		g_source_remove(sg->scheduler);
-
-	purple_debug_info("silc", "Scheduling destruction of SilcPurple %p\n", sg);
-	g_timeout_add(1, (GSourceFunc)silcpurple_close_final, sg);
-}
-
-
-/****************************** Protocol Actions *****************************/
-
-static void
-silcpurple_attrs_cancel(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	/* Nothing */
-}
-
-static void
-silcpurple_attrs_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	PurpleRequestField *f;
-	char *tmp;
-	SilcUInt32 tmp_len, mask;
-	SilcAttributeObjService service;
-	SilcAttributeObjDevice dev;
-	SilcVCardStruct vcard;
-	const char *val;
-
-	sg = purple_connection_get_protocol_data(gc);
-	if (!sg)
-		return;
-
-	memset(&service, 0, sizeof(service));
-	memset(&dev, 0, sizeof(dev));
-	memset(&vcard, 0, sizeof(vcard));
-
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_USER_INFO, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_SERVICE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_STATUS_MOOD, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_TIMEZONE, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_GEOLOCATION, NULL);
-	silc_client_attribute_del(client, conn,
-				  SILC_ATTRIBUTE_DEVICE_INFO, NULL);
-
-	/* Set mood */
-	mask = 0;
-	f = purple_request_fields_get_field(fields, "mood_normal");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_NORMAL;
-	f = purple_request_fields_get_field(fields, "mood_happy");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_HAPPY;
-	f = purple_request_fields_get_field(fields, "mood_sad");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_SAD;
-	f = purple_request_fields_get_field(fields, "mood_angry");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_ANGRY;
-	f = purple_request_fields_get_field(fields, "mood_jealous");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_JEALOUS;
-	f = purple_request_fields_get_field(fields, "mood_ashamed");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_ASHAMED;
-	f = purple_request_fields_get_field(fields, "mood_invincible");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE;
-	f = purple_request_fields_get_field(fields, "mood_inlove");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_INLOVE;
-	f = purple_request_fields_get_field(fields, "mood_sleepy");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_SLEEPY;
-	f = purple_request_fields_get_field(fields, "mood_bored");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_BORED;
-	f = purple_request_fields_get_field(fields, "mood_excited");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_EXCITED;
-	f = purple_request_fields_get_field(fields, "mood_anxious");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS;
-	silc_client_attribute_add(client, conn,
-				  SILC_ATTRIBUTE_STATUS_MOOD,
-				  SILC_32_TO_PTR(mask),
-				  sizeof(SilcUInt32));
-
-	/* Set preferred contact */
-	mask = 0;
-	f = purple_request_fields_get_field(fields, "contact_chat");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_CHAT;
-	f = purple_request_fields_get_field(fields, "contact_email");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_EMAIL;
-	f = purple_request_fields_get_field(fields, "contact_call");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_CALL;
-	f = purple_request_fields_get_field(fields, "contact_sms");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_SMS;
-	f = purple_request_fields_get_field(fields, "contact_mms");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_MMS;
-	f = purple_request_fields_get_field(fields, "contact_video");
-	if (f && purple_request_field_bool_get_value(f))
-		mask |= SILC_ATTRIBUTE_CONTACT_VIDEO;
-	if (mask)
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_PREFERRED_CONTACT,
-					  SILC_32_TO_PTR(mask),
-					  sizeof(SilcUInt32));
-
-	/* Set status text */
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "status_text");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_STATUS_FREETEXT,
-					  (void *)val, strlen(val));
-
-	/* Set vcard */
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "vcard");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val) {
-		purple_account_set_string(sg->account, "vcard", val);
-		tmp = silc_file_readfile(val, &tmp_len);
-		if (tmp) {
-			tmp[tmp_len] = 0;
-			if (silc_vcard_decode((unsigned char *)tmp, tmp_len, &vcard))
-				silc_client_attribute_add(client, conn,
-							  SILC_ATTRIBUTE_USER_INFO,
-							  (void *)&vcard,
-							  sizeof(vcard));
-		}
-		silc_vcard_free(&vcard);
-		silc_free(tmp);
-	} else {
-		purple_account_set_string(sg->account, "vcard", "");
-	}
-
-#ifdef HAVE_SYS_UTSNAME_H
-	/* Set device info */
-	f = purple_request_fields_get_field(fields, "device");
-	if (f && purple_request_field_bool_get_value(f)) {
-		struct utsname u;
-		if (!uname(&u)) {
-			dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
-			dev.version = u.release;
-			dev.model = u.sysname;
-			silc_client_attribute_add(client, conn,
-						  SILC_ATTRIBUTE_DEVICE_INFO,
-						  (void *)&dev, sizeof(dev));
-		}
-	}
-#endif
-
-	/* Set timezone */
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "timezone");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		silc_client_attribute_add(client, conn,
-					  SILC_ATTRIBUTE_TIMEZONE,
-					  (void *)val, strlen(val));
-}
-
-static void
-silcpurple_attrs(G_GNUC_UNUSED GSimpleAction *action,
-                 GVariant *parameter,
-                 G_GNUC_UNUSED gpointer data)
-{
-	const gchar *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *gc = NULL;
-	SilcPurple sg = NULL;
-	SilcClient client = NULL;
-	SilcClientConnection conn = NULL;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	SilcHashTable attrs;
-	SilcAttributePayload attr;
-	gboolean mnormal = TRUE, mhappy = FALSE, msad = FALSE,
-		mangry = FALSE, mjealous = FALSE, mashamed = FALSE,
-		minvincible = FALSE, minlove = FALSE, msleepy = FALSE,
-		mbored = FALSE, mexcited = FALSE, manxious = FALSE;
-	gboolean cemail = FALSE, ccall = FALSE, csms = FALSE,
-		cmms = FALSE, cchat = TRUE, cvideo = FALSE;
-#ifdef HAVE_SYS_UTSNAME_H
-	gboolean device = TRUE;
-#endif
-	char status[1024], tz[16];
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("SILC attrs action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-	gc = purple_account_get_connection(account);
-
-	sg = purple_connection_get_protocol_data(gc);
-	if (!sg)
-		return;
-
-	client = sg->client;
-	conn = sg->conn;
-
-	memset(status, 0, sizeof(status));
-
-	attrs = silc_client_attributes_get(client, conn);
-	if (attrs) {
-		if (silc_hash_table_find(attrs,
-					 SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_MOOD),
-					 NULL, (void *)&attr)) {
-			SilcUInt32 mood = 0;
-			silc_attribute_get_object(attr, &mood, sizeof(mood));
-			mnormal = !mood;
-			mhappy = (mood & SILC_ATTRIBUTE_MOOD_HAPPY);
-			msad = (mood & SILC_ATTRIBUTE_MOOD_SAD);
-			mangry = (mood & SILC_ATTRIBUTE_MOOD_ANGRY);
-			mjealous = (mood & SILC_ATTRIBUTE_MOOD_JEALOUS);
-			mashamed = (mood & SILC_ATTRIBUTE_MOOD_ASHAMED);
-			minvincible = (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE);
-			minlove = (mood & SILC_ATTRIBUTE_MOOD_INLOVE);
-			msleepy = (mood & SILC_ATTRIBUTE_MOOD_SLEEPY);
-			mbored = (mood & SILC_ATTRIBUTE_MOOD_BORED);
-			mexcited = (mood & SILC_ATTRIBUTE_MOOD_EXCITED);
-			manxious = (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS);
-		}
-
-		if (silc_hash_table_find(attrs,
-					 SILC_32_TO_PTR(SILC_ATTRIBUTE_PREFERRED_CONTACT),
-					 NULL, (void *)&attr)) {
-			SilcUInt32 contact = 0;
-			silc_attribute_get_object(attr, &contact, sizeof(contact));
-			cemail = (contact & SILC_ATTRIBUTE_CONTACT_EMAIL);
-			ccall = (contact & SILC_ATTRIBUTE_CONTACT_CALL);
-			csms = (contact & SILC_ATTRIBUTE_CONTACT_SMS);
-			cmms = (contact & SILC_ATTRIBUTE_CONTACT_MMS);
-			cchat = (contact & SILC_ATTRIBUTE_CONTACT_CHAT);
-			cvideo = (contact & SILC_ATTRIBUTE_CONTACT_VIDEO);
-		}
-
-		if (silc_hash_table_find(attrs,
-					 SILC_32_TO_PTR(SILC_ATTRIBUTE_STATUS_FREETEXT),
-					 NULL, (void *)&attr))
-			silc_attribute_get_object(attr, &status, sizeof(status));
-
-#ifdef HAVE_SYS_UTSNAME_H
-		if (!silc_hash_table_find(attrs,
-					  SILC_32_TO_PTR(SILC_ATTRIBUTE_DEVICE_INFO),
-					  NULL, (void *)&attr))
-			device = FALSE;
-#endif
-	}
-
-	fields = purple_request_fields_new();
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_label_new("l3", _("Your Current Mood"));
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_normal", _("Normal"), mnormal);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_happy", _("Happy"), mhappy);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_sad", _("Sad"), msad);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_angry", _("Angry"), mangry);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_jealous", _("Jealous"), mjealous);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_ashamed", _("Ashamed"), mashamed);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_invincible", _("Invincible"), minvincible);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_inlove", _("In love"), minlove);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_sleepy", _("Sleepy"), msleepy);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_bored", _("Bored"), mbored);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_excited", _("Excited"), mexcited);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("mood_anxious", _("Anxious"), manxious);
-	purple_request_field_group_add_field(g, f);
-
-	f = purple_request_field_label_new("l4", _("\nYour Preferred Contact Methods"));
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_chat", _("Chat"), cchat);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_email", _("Email"), cemail);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_call", _("Phone"), ccall);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_sms", _("SMS"), csms);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_mms", _("MMS"), cmms);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_bool_new("contact_video", _("Video conferencing"), cvideo);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("status_text", _("Your Current Status"),
-					  status[0] ? status : NULL, TRUE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-#ifdef HAVE_SYS_UTSNAME_H
-	f = purple_request_field_bool_new("device",
-					_("Let others see what computer you are using"),
-					device);
-	purple_request_field_group_add_field(g, f);
-#endif
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("vcard", _("Your VCard File"),
-					  purple_account_get_string(sg->account, "vcard", ""),
-					  FALSE);
-	purple_request_field_group_add_field(g, f);
-
-	silc_timezone(tz, sizeof(tz));
-	f = purple_request_field_string_new("timezone", _("Timezone (UTC)"), tz, FALSE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	purple_request_fields(gc, _("User Online Status Attributes"),
-			    _("User Online Status Attributes"),
-			    _("You can let other users see your online status information "
-			      "and your personal information. Please fill the information "
-			      "you would like other users to see about yourself."),
-			    fields,
-			    _("OK"), G_CALLBACK(silcpurple_attrs_cb),
-			    _("Cancel"), G_CALLBACK(silcpurple_attrs_cancel),
-			    purple_request_cpar_from_connection(gc), gc);
-}
-
-static void
-silcpurple_detach(G_GNUC_UNUSED GSimpleAction *action,
-                  GVariant *parameter,
-                  G_GNUC_UNUSED gpointer data)
-{
-	const gchar *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *connection = NULL;
-	SilcPurple sg = NULL;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("SILC detach action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-	connection = purple_account_get_connection(account);
-	if (!connection) {
-		return;
-	}
-
-	sg = purple_connection_get_protocol_data(connection);
-	if (!sg) {
-		return;
-	}
-
-	/* Call DETACH */
-	silc_client_command_call(sg->client, sg->conn, "DETACH");
-	sg->detaching = TRUE;
-}
-
-static void
-silcpurple_view_motd(G_GNUC_UNUSED GSimpleAction *action,
-                     GVariant *parameter,
-                     G_GNUC_UNUSED gpointer data)
-{
-	const gchar *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *connection = NULL;
-	SilcPurple sg = NULL;
-	char *tmp;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("SILC view MOTD action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-	connection = purple_account_get_connection(account);
-	if (!connection) {
-		return;
-	}
-
-	sg = purple_connection_get_protocol_data(connection);
-	if (!sg) {
-		return;
-	}
-
-	if (!sg->motd) {
-		purple_notify_error(connection, _("Message of the Day"), _("No Message "
-			"of the Day available"), _("There is no Message of the "
-			"Day associated with this connection"),
-			purple_request_cpar_from_connection(connection));
-		return;
-	}
-
-	tmp = g_markup_escape_text(sg->motd, -1);
-	purple_notify_formatted(connection, NULL, _("Message of the Day"), NULL,
-			      tmp, NULL, NULL);
-	g_free(tmp);
-}
-
-static void
-silcpurple_create_keypair_cancel(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	/* Nothing */
-}
-
-static void
-silcpurple_create_keypair_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
-	SilcPurple sg;
-	PurpleRequestField *f;
-	const char *val, *pkfile = NULL, *prfile = NULL;
-	const char *pass1 = NULL, *pass2 = NULL, *un = NULL, *hn = NULL;
-	const char *rn = NULL, *e = NULL, *o = NULL, *c = NULL;
-	char *identifier;
-	int keylen = SILCPURPLE_DEF_PKCS_LEN;
-	SilcPublicKey public_key;
-
-	sg = purple_connection_get_protocol_data(gc);
-	if (!sg)
-		return;
-
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "pass1");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		pass1 = val;
-	else
-		pass1 = "";
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "pass2");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		pass2 = val;
-	else
-		pass2 = "";
-
-	if (!purple_strequal(pass1, pass2)) {
-		purple_notify_error(gc, _("Create New SILC Key Pair"),
-			_("Passphrases do not match"), NULL,
-			purple_request_cpar_from_connection(gc));
-		return;
-	}
-
-	val = NULL;
-	f = purple_request_fields_get_field(fields, "key");
-	if (f)
-		val = purple_request_field_string_get_value(f);
-	if (val && *val)
-		keylen = atoi(val);
-	f = purple_request_fields_get_field(fields, "pkfile");
-	if (f)
-		pkfile = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "prfile");
-	if (f)
-		prfile = purple_request_field_string_get_value(f);
-
-	f = purple_request_fields_get_field(fields, "un");
-	if (f)
-		un = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "hn");
-	if (f)
-		hn = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "rn");
-	if (f)
-		rn = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "e");
-	if (f)
-		e = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "o");
-	if (f)
-		o = purple_request_field_string_get_value(f);
-	f = purple_request_fields_get_field(fields, "c");
-	if (f)
-		c = purple_request_field_string_get_value(f);
-
-	identifier = silc_pkcs_silc_encode_identifier((char *)un, (char *)hn,
-						      (char *)rn, (char *)e,
-						      (char *)o, (char *)c,
-						      NULL);
-
-	/* Create the key pair */
-	if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS, keylen, pkfile, prfile,
-				  identifier, pass1, &public_key, NULL,
-				  FALSE)) {
-		purple_notify_error(gc, _("Create New SILC Key Pair"),
-			_("Key Pair Generation failed"), NULL,
-			purple_request_cpar_from_connection(gc));
-		return;
-	}
-
-	silcpurple_show_public_key(sg, NULL, public_key, NULL, NULL);
-
-	silc_pkcs_public_key_free(public_key);
-	silc_free(identifier);
-}
-
-static void
-silcpurple_create_keypair(G_GNUC_UNUSED GSimpleAction *action,
-                          GVariant *parameter,
-                          G_GNUC_UNUSED gpointer data)
-{
-	const gchar *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-	PurpleConnection *connection = NULL;
-	PurpleRequestFields *fields;
-	PurpleRequestFieldGroup *g;
-	PurpleRequestField *f;
-	const char *username, *realname;
-	char *hostname, **u;
-	char tmp[256], pkd[256], pkd2[256], prd[256], prd2[256];
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("SILC create keypair action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-	connection = purple_account_get_connection(account);
-
-	username = purple_account_get_username(account);
-	u = g_strsplit(username, "@", 2);
-	username = u[0];
-	realname = purple_account_get_user_info(account);
-	hostname = silc_net_localhost();
-	g_snprintf(tmp, sizeof(tmp), "%s@%s", username, hostname);
-
-	g_snprintf(pkd2, sizeof(pkd2), "%s" G_DIR_SEPARATOR_S"public_key.pub", silcpurple_silcdir());
-	g_snprintf(prd2, sizeof(prd2), "%s" G_DIR_SEPARATOR_S"private_key.prv", silcpurple_silcdir());
-	g_snprintf(pkd, sizeof(pkd) - 1, "%s",
-	           purple_account_get_string(account, "public-key", pkd2));
-	g_snprintf(prd, sizeof(prd) - 1, "%s",
-	           purple_account_get_string(account, "private-key", prd2));
-
-	fields = purple_request_fields_new();
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("key", _("Key length"), "2048", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("pkfile", _("Public key file"), pkd, FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("prfile", _("Private key file"), prd, FALSE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("un", _("Username"), username ? username : "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("hn", _("Hostname"), hostname ? hostname : "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("rn", _("Real name"), realname ? realname : "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("e", _("Email"), tmp, FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("o", _("Organization"), "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("c", _("Country"), "", FALSE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	g = purple_request_field_group_new(NULL);
-	f = purple_request_field_string_new("pass1", _("Passphrase"), "", FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-	f = purple_request_field_string_new("pass2", _("Passphrase (retype)"), "", FALSE);
-	purple_request_field_string_set_masked(f, TRUE);
-	purple_request_field_group_add_field(g, f);
-	purple_request_fields_add_group(fields, g);
-
-	purple_request_fields(connection, _("Create New SILC Key Pair"),
-			      _("Create New SILC Key Pair"), NULL, fields,
-			      _("Generate Key Pair"), G_CALLBACK(silcpurple_create_keypair_cb),
-			      _("Cancel"), G_CALLBACK(silcpurple_create_keypair_cancel),
-			      purple_request_cpar_from_connection(connection), connection);
-
-	g_strfreev(u);
-	silc_free(hostname);
-}
-
-static void
-silcpurple_change_pass(G_GNUC_UNUSED GSimpleAction *action,
-                       GVariant *parameter,
-                       G_GNUC_UNUSED gpointer data)
-{
-	const gchar *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("SILC change password action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-
-	purple_account_request_change_password(account);
-}
-
-static void
-silcpurple_change_passwd(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *old, const char *new)
-{
-	char prd[256];
-	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.pub", silcpurple_silcdir());
-	silc_change_private_key_passphrase(purple_account_get_string(purple_connection_get_account(gc),
-								     "private-key",
-								     prd), old ? old : "", new ? new : "");
-}
-
-static void
-silcpurple_show_set_info(G_GNUC_UNUSED GSimpleAction *action,
-                         GVariant *parameter,
-                         G_GNUC_UNUSED gpointer data)
-{
-	const gchar *account_id = NULL;
-	PurpleAccountManager *manager = NULL;
-	PurpleAccount *account = NULL;
-
-	if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
-		g_critical("SILC change password action parameter is of incorrect type %s",
-		           g_variant_get_type_string(parameter));
-	}
-
-	account_id = g_variant_get_string(parameter, NULL);
-	manager = purple_account_manager_get_default();
-	account = purple_account_manager_find_by_id(manager, account_id);
-
-	purple_account_request_change_user_info(account);
-}
-
-static void
-silcpurple_set_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *text)
-{
-}
-
-static const gchar *
-silcpurple_protocol_actions_get_prefix(PurpleProtocolActions *actions) {
-	return "prpl-silc";
-}
-
-static GActionGroup *
-silcpurple_protocol_actions_get_action_group(PurpleProtocolActions *actions,
-                                             PurpleConnection *connection)
-{
-	GSimpleActionGroup *group = NULL;
-	GActionEntry entries[] = {
-		{
-			.name = "attrs",
-			.activate = silcpurple_attrs,
-			.parameter_type = "s",
-		},
-		{
-			.name = "detach",
-			.activate = silcpurple_detach,
-			.parameter_type = "s",
-		},
-		{
-			.name = "view-motd",
-			.activate = silcpurple_view_motd,
-			.parameter_type = "s",
-		},
-		{
-			.name = "create-keypair",
-			.activate = silcpurple_create_keypair,
-			.parameter_type = "s",
-		},
-		{
-			.name = "change-password",
-			.activate = silcpurple_change_pass,
-			.parameter_type = "s",
-		},
-		{
-			.name = "set-user-info",
-			.activate = silcpurple_show_set_info,
-			.parameter_type = "s",
-		},
-	};
-	gsize nentries = G_N_ELEMENTS(entries);
-
-	group = g_simple_action_group_new();
-	g_action_map_add_action_entries(G_ACTION_MAP(group), entries, nentries,
-	                                connection);
-
-	return G_ACTION_GROUP(group);
-}
-
-static GMenu *
-silcpurple_protocol_actions_get_menu(PurpleProtocolActions *actions)
-{
-	GMenu *menu = NULL;
-	GMenuItem *item = NULL;
-
-	menu = g_menu_new();
-
-	item = g_menu_item_new(_("Online Status"), "prpl-silc.attrs");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	item = g_menu_item_new(_("Detach From Server"), "prpl-silc.detach");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	item = g_menu_item_new(_("View Message of the Day"), "prpl-silc.view-motd");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	item = g_menu_item_new(_("Create SILC Key Pair..."),
-	                       "prpl-silc.create-keypair");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	item = g_menu_item_new(_("Change Password..."),
-	                       "prpl-silc.change-password");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	item = g_menu_item_new(_("Set User Info..."), "prpl-silc.set-user-info");
-	g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
-	                          "account");
-	g_menu_append_item(menu, item);
-	g_object_unref(item);
-
-	return menu;
-}
-
-
-/******************************* IM Routines *********************************/
-
-typedef struct {
-	char *nick;
-	char *message;
-	SilcUInt32 message_len;
-	SilcMessageFlags flags;
-	PurpleMessageFlags gflags;
-} *SilcPurpleIM;
-
-static void
-silcpurple_send_im_resolved(SilcClient client,
-			    SilcClientConnection conn,
-			    SilcStatus status,
-			    SilcDList clients,
-			    void *context)
-{
-	PurpleConnection *gc = client->application;
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcPurpleIM im = context;
-	PurpleConversation *convo;
-	PurpleConversationManager *manager;
-	char tmp[256];
-	SilcClientEntry client_entry;
-	SilcDList list;
-	gboolean free_list = FALSE;
-	const gchar *me;
-	PurpleMessage *msg;
-
-	manager = purple_conversation_manager_get_default();
-	convo = purple_conversation_manager_find_im(manager, sg->account, im->nick);
-	if (!convo) {
-		return;
-	}
-
-	if (!clients) {
-		goto err;
-	}
-
-	if (silc_dlist_count(clients) > 1) {
-		/* Find the correct one. The im->nick might be a formatted nick
-		   so this will find the correct one. */
-		clients = silc_client_get_clients_local(client, conn,
-							im->nick, FALSE);
-		if (!clients)
-			goto err;
-
-		free_list = TRUE;
-	}
-
-	silc_dlist_start(clients);
-	client_entry = silc_dlist_get(clients);
-
-	me = purple_account_get_name_for_display(sg->account);
-
-	/* Check for images */
-	if (im->gflags & PURPLE_MESSAGE_IMAGES) {
-		list = silcpurple_image_message(im->message, &im->flags);
-		if (list) {
-			/* Send one or more MIME message.  If more than one, they
-			   are MIME fragments due to over large message */
-			SilcBuffer buf;
-
-			silc_dlist_start(list);
-			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
-				silc_client_send_private_message(client, conn,
-								 client_entry, im->flags, sg->sha1hash,
-								 buf->data,
-								 silc_buffer_len(buf));
-			silc_mime_partial_free(list);
-			msg = purple_message_new_outgoing(me, conn->local_entry->nickname, im->message, 0);
-			purple_conversation_write_message(convo, msg);
-			g_object_unref(G_OBJECT(msg));
-			goto out;
-		}
-	}
-
-	/* Send the message */
-	silc_client_send_private_message(client, conn, client_entry, im->flags,
-					 sg->sha1hash, (unsigned char *)im->message, im->message_len);
-	msg = purple_message_new_outgoing(me, conn->local_entry->nickname, im->message, 0);
-	purple_conversation_write_message(convo, msg);
-	g_object_unref(G_OBJECT(msg));
-	goto out;
-
- err:
-	g_snprintf(tmp, sizeof(tmp),
-		   _("User <I>%s</I> is not present in the network"), im->nick);
-	purple_conversation_write_system_message(
-		convo, tmp, 0);
-
- out:
-	if (free_list) {
-		silc_client_list_free(client, conn, clients);
-	}
-	g_free(im->nick);
-	g_free(im->message);
-	silc_free(im);
-}
-
-static int
-silcpurple_send_im(PurpleProtocolIM *pim, PurpleConnection *gc,
-		   PurpleMessage *pmsg)
-{
-	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	SilcClient client = sg->client;
-	SilcClientConnection conn = sg->conn;
-	SilcDList clients;
-	SilcClientEntry client_entry;
-	SilcMessageFlags mflags;
-	char *msg, *tmp;
-	int ret = 0;
-	gboolean sign = purple_account_get_bool(sg->account, "sign-verify", FALSE);
-	SilcDList list;
-	const gchar *rcpt = purple_message_get_recipient(pmsg);
-	const gchar *message = purple_message_get_contents(pmsg);
-	PurpleMessageFlags flags = purple_message_get_flags(pmsg);
-
-	if (!rcpt || purple_message_is_empty(pmsg))
-		return 0;
-
-	mflags = SILC_MESSAGE_FLAG_UTF8;
-
-	tmp = msg = purple_unescape_html(message);
-
-	if (!g_ascii_strncasecmp(msg, "/me ", 4)) {
-		msg += 4;
-		if (!*msg) {
-			g_free(tmp);
-			return 0;
-		}
-		mflags |= SILC_MESSAGE_FLAG_ACTION;
-	} else if (strlen(msg) > 1 && msg[0] == '/') {
-		if (!silc_client_command_call(client, conn, msg + 1))
-			purple_notify_error(gc, _("Call Command"),
-					    _("Cannot call command"),
-					    _("Unknown command"),
-					    purple_request_cpar_from_connection(gc));
-		g_free(tmp);
-		return 0;
-	}
-
-	if (sign)
-		mflags |= SILC_MESSAGE_FLAG_SIGNED;
-
-	/* Find client entry */
-	clients = silc_client_get_clients_local(client, conn, rcpt, FALSE);
-	if (!clients) {
-		/* Resolve unknown user */
-		SilcPurpleIM im = silc_calloc(1, sizeof(*im));
-		if (!im) {
-			g_free(tmp);
-			return 0;
-		}
-		im->nick = g_strdup(rcpt);
-		im->message = g_strdup(message);
-		im->message_len = strlen(im->message);
-		im->flags = mflags;
-		im->gflags = flags;
-		silc_client_get_clients(client, conn, rcpt, NULL,
-					silcpurple_send_im_resolved, im);
-		g_free(tmp);
-		return 0;
-	}
-	silc_dlist_start(clients);
-	client_entry = silc_dlist_get(clients);
-
-	/* Check for images */
-	if (flags & PURPLE_MESSAGE_IMAGES) {
-		list = silcpurple_image_message(message, &mflags);
-		if (list) {
-			/* Send one or more MIME message.  If more than one, they
-			   are MIME fragments due to over large message */
-			SilcBuffer buf;
-
-			silc_dlist_start(list);
-			while ((buf = silc_dlist_get(list)) != SILC_LIST_END)
-				ret =
-			 	silc_client_send_private_message(client, conn,
-								 client_entry, mflags, sg->sha1hash,
-								 buf->data,
-								 silc_buffer_len(buf));
-			silc_mime_partial_free(list);
-			g_free(tmp);
-			silc_client_list_free(client, conn, clients);
-			return ret;
-		}
-	}
-
-	/* Send private message directly */
-	ret = silc_client_send_private_message(client, conn, client_entry,
-					       mflags, sg->sha1hash,
-					       (unsigned char *)msg,
-					       strlen(msg));
-
-	g_free(tmp);
-	silc_client_list_free(client, conn, clients);
-	return ret;
-}
-
-
-static GList *silcpurple_blist_node_menu(PurpleProtocolClient *client, PurpleBlistNode *node) {
-	/* split this single menu building function back into the two
-	   original: one for buddies and one for chats */
-	if(PURPLE_IS_CHAT(node)) {
-		return silcpurple_chat_menu((PurpleChat *) node);
-	} else if(PURPLE_IS_BUDDY(node)) {
-		return silcpurple_buddy_menu((PurpleBuddy *) node);
-	} else {
-		g_return_val_if_reached(NULL);
-	}
-}
-
-/********************************* Commands **********************************/
-
-static PurpleCmdRet silcpurple_cmd_chat_part(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	PurpleConversation *chat = conv;
-	int id = 0;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	if(args && args[0]) {
-		PurpleConversationManager *manager;
-
-		manager = purple_conversation_manager_get_default();
-
-		chat = purple_conversation_manager_find_chat(manager,
-		                                             purple_connection_get_account(gc),
-		                                             args[0]);
-	}
-
-	if (chat != NULL)
-		id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat));
-
-	if (id == 0)
-		return PURPLE_CMD_RET_FAILED;
-
-	silcpurple_chat_leave(NULL, gc, id);
-
-	return PURPLE_CMD_RET_OK;
-
-}
-
-static PurpleCmdRet silcpurple_cmd_chat_topic(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	int id = 0;
-	char *buf, *tmp, *tmp2;
-	const char *topic;
-
-	gc = purple_conversation_get_connection(conv);
-	id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv));
-
-	if (gc == NULL || id == 0)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!args || !args[0]) {
-		topic = purple_chat_conversation_get_topic(PURPLE_CHAT_CONVERSATION(conv));
-		if (topic) {
-			tmp = g_markup_escape_text(topic, -1);
-			tmp2 = purple_markup_linkify(tmp);
-			buf = g_strdup_printf(_("current topic is: %s"), tmp2);
-			g_free(tmp);
-			g_free(tmp2);
-		} else
-			buf = g_strdup(_("No topic is set"));
-		purple_conversation_write_system_message(conv,
-			buf, PURPLE_MESSAGE_NO_LOG);
-		g_free(buf);
-
-	}
-
-	if (args && args[0] && (strlen(args[0]) > 255)) {
-		*error = g_strdup(_("Topic too long"));
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	silcpurple_chat_set_topic(NULL, gc, id, args ? args[0] : NULL);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_chat_join(PurpleConversation *conv,
-        const char *cmd, char **args, char **error, void *data)
-{
-	GHashTable *comp;
-
-	if(!args || !args[0])
-		return PURPLE_CMD_RET_FAILED;
-
-	comp = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
-
-	g_hash_table_replace(comp, "channel", args[0]);
-	if(args[1])
-		g_hash_table_replace(comp, "passphrase", args[1]);
-
-	silcpurple_chat_join(NULL, purple_conversation_get_connection(conv), comp);
-
-	g_hash_table_destroy(comp);
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_chat_list(PurpleConversation *conv,
-        const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	gc = purple_conversation_get_connection(conv);
-	purple_roomlist_show_with_account(purple_connection_get_account(gc));
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_whois(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	silcpurple_get_info(NULL, gc, args[0]);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_msg(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	int ret;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	const gchar *me;
-	PurpleMessage *msg;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	account = purple_connection_get_account(gc);
-	me = purple_account_get_name_for_display(account);
-	msg = purple_message_new_outgoing(me, args[0], args[1], 0);
-	ret = silcpurple_send_im(NULL, gc, msg);
-	g_object_unref(G_OBJECT(msg));
-
-	if (ret)
-		return PURPLE_CMD_RET_OK;
-	else
-		return PURPLE_CMD_RET_FAILED;
-}
-
-static PurpleCmdRet silcpurple_cmd_query(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	int ret = 1;
-	PurpleConversation *im;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-
-	if (!args || !args[0]) {
-		*error = g_strdup(_("You must specify a nick"));
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	account = purple_connection_get_account(gc);
-
-	im = purple_im_conversation_new(account, args[0]);
-
-	if (args[1]) {
-		const gchar *me = purple_account_get_name_for_display(account);
-		PurpleMessage *msg = purple_message_new_outgoing(
-		        me, args[0], args[1], 0);
-
-		ret = silcpurple_send_im(NULL, gc, msg);
-		purple_conversation_write_message(im, msg);
-		g_object_unref(G_OBJECT(msg));
-	}
-
-	if (ret)
-		return PURPLE_CMD_RET_OK;
-	else
-		return PURPLE_CMD_RET_FAILED;
-}
-
-static PurpleCmdRet silcpurple_cmd_motd(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	char *tmp;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!sg->motd) {
-		*error = g_strdup(_("There is no Message of the Day associated with this connection"));
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	tmp = g_markup_escape_text(sg->motd, -1);
-	purple_notify_formatted(gc, NULL, _("Message of the Day"), NULL,
-			tmp, NULL, NULL);
-	g_free(tmp);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_detach(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	silc_client_command_call(sg->client, sg->conn, "DETACH");
-	sg->detaching = TRUE;
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_cmode(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	SilcChannelEntry channel;
-	char *silccmd, *silcargs, *msg, tmp[256];
-	const char *chname;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL || !args || purple_connection_get_protocol_data(gc) == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (args[0])
-		chname = args[0];
-	else
-		chname = purple_conversation_get_name(conv);
-
-	if (!args[1]) {
-		channel = silc_client_get_channel(sg->client, sg->conn,
-										  (char *)chname);
-		if (!channel) {
-			*error = g_strdup_printf(_("channel %s not found"), chname);
-			return PURPLE_CMD_RET_FAILED;
-		}
-		if (channel->mode) {
-			silcpurple_get_chmode_string(channel->mode, tmp, sizeof(tmp));
-			msg = g_strdup_printf(_("channel modes for %s: %s"), chname, tmp);
-		} else {
-			msg = g_strdup_printf(_("no channel modes are set on %s"), chname);
-		}
-		purple_conversation_write_system_message(conv, msg, PURPLE_MESSAGE_NO_LOG);
-		g_free(msg);
-		return PURPLE_CMD_RET_OK;
-	}
-
-	silcargs = g_strjoinv(" ", args);
-	silccmd = g_strconcat(cmd, " ", silcargs, NULL);
-	g_free(silcargs);
-	if (!silc_client_command_call(sg->client, sg->conn, silccmd)) {
-		g_free(silccmd);
-		*error = g_strdup_printf(_("Failed to set cmodes for %s"), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-	g_free(silccmd);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_generic(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	char *silccmd, *silcargs;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	silcargs = g_strjoinv(" ", args);
-	silccmd = g_strconcat(cmd, " ", args ? silcargs : NULL, NULL);
-	g_free(silcargs);
-	if (!silc_client_command_call(sg->client, sg->conn, silccmd)) {
-		g_free(silccmd);
-		*error = g_strdup_printf(_("Unknown command: %s, (may be a client bug)"), cmd);
-		return PURPLE_CMD_RET_FAILED;
-	}
-	g_free(silccmd);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_quit(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-	char *quit_msg;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (args && args[0]) {
-		quit_msg = g_strdup(args[0]);
-	} else {
-		quit_msg = silcpurple_get_quit_message();
-	}
-
-	silc_client_command_call(sg->client, sg->conn, NULL,
-	                         "QUIT", quit_msg, NULL);
-	g_free(quit_msg);
-
-	return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet silcpurple_cmd_call(PurpleConversation *conv,
-		const char *cmd, char **args, char **error, void *data)
-{
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	gc = purple_conversation_get_connection(conv);
-
-	if (gc == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	sg = purple_connection_get_protocol_data(gc);
-
-	if (sg == NULL)
-		return PURPLE_CMD_RET_FAILED;
-
-	if (!silc_client_command_call(sg->client, sg->conn, args[0])) {
-		*error = g_strdup_printf(_("Unknown command: %s"), args[0]);
-		return PURPLE_CMD_RET_FAILED;
-	}
-
-	return PURPLE_CMD_RET_OK;
-}
-
-
-/************************** Plugin Initialization ****************************/
-
-static void
-silcpurple_register_commands(void)
-{
-	PurpleCmdId id;
-
-	id = purple_cmd_register("part", "w", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
-			"prpl-silc", silcpurple_cmd_chat_part, _("part [channel]:  Leave the chat"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("leave", "w", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
-			"prpl-silc", silcpurple_cmd_chat_part, _("leave [channel]:  Leave the chat"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("topic", "s", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
-			silcpurple_cmd_chat_topic, _("topic [&lt;new topic&gt;]:  View or change the topic"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("join", "ws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
-			PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
-			"prpl-silc", silcpurple_cmd_chat_join,
-			_("join &lt;channel&gt; [&lt;password&gt;]:  Join a chat on this network"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
-			silcpurple_cmd_chat_list, _("list:  List channels on this network"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("whois", "w", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc",
-			silcpurple_cmd_whois, _("whois &lt;nick&gt;:  View nick's information"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("msg", "ws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_msg,
-			_("msg &lt;nick&gt; &lt;message&gt;:  Send a private message to a user"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("query", "ws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_query,
-			_("query &lt;nick&gt; [&lt;message&gt;]:  Send a private message to a user"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("motd", "", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_motd,
-			_("motd:  View the server's Message Of The Day"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("detach", "", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_detach,
-			_("detach:  Detach this session"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("quit", "s", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_quit,
-			_("quit [message]:  Disconnect from the server, with an optional message"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("call", "s", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_call,
-			_("call &lt;command&gt;:  Call any silc client command"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	/* These below just get passed through for the silc client library to deal
-	 * with */
-	id = purple_cmd_register("kill", "ws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("kill &lt;nick&gt; [-pubkey|&lt;reason&gt;]:  Kill nick"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("nick", "w", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("nick &lt;newnick&gt;:  Change your nickname"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("whowas", "ww", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("whowas &lt;nick&gt;:  View nick's information"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("cmode", "wws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_cmode,
-			_("cmode &lt;channel&gt; [+|-&lt;modes&gt;] [arguments]:  Change or display channel modes"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("cumode", "wws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("cumode &lt;channel&gt; +|-&lt;modes&gt; &lt;nick&gt;:  Change nick's modes on channel"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("umode", "w", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("umode &lt;usermodes&gt;:  Set your modes in the network"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("oper", "s", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("oper &lt;nick&gt; [-pubkey]:  Get server operator privileges"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("invite", "ws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("invite &lt;channel&gt; [-|+]&lt;nick&gt;:  invite nick or add/remove from channel invite list"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("kick", "wws", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("kick &lt;channel&gt; &lt;nick&gt; [comment]:  Kick client from channel"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("info", "w", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("info [server]:  View server administrative details"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("ban", "ww", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY |
-			PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc", silcpurple_cmd_generic,
-			_("ban [&lt;channel&gt; +|-&lt;nick&gt;]:  Ban client from channel"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("getkey", "w", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("getkey &lt;nick|server&gt;:  Retrieve client's or server's public key"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("stats", "", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("stats:  View server and network statistics"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-
-	id = purple_cmd_register("ping", "", PURPLE_CMD_P_PROTOCOL,
-			PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PROTOCOL_ONLY,
-			"prpl-silc", silcpurple_cmd_generic,
-			_("ping:  Send PING to the connected server"), NULL);
-	cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id));
-}
-
-static void
-silcpurple_unregister_commands(void)
-{
-	while (cmds) {
-		PurpleCmdId id = GPOINTER_TO_UINT(cmds->data);
-		purple_cmd_unregister(id);
-		cmds = g_slist_delete_link(cmds, cmds);
-	}
-}
-
-static PurpleWhiteboardOps silcpurple_wb_ops =
-{
-	silcpurple_wb_start,
-	silcpurple_wb_end,
-	silcpurple_wb_get_dimensions,
-	silcpurple_wb_set_dimensions,
-	silcpurple_wb_get_brush,
-	silcpurple_wb_set_brush,
-	silcpurple_wb_send,
-	silcpurple_wb_clear,
-
-	/* padding */
-	{ NULL, NULL, NULL, NULL }
-};
-
-static GList *
-silcpurple_protocol_get_user_splits(G_GNUC_UNUSED PurpleProtocol *protocol)
-{
-	PurpleAccountUserSplit *split = purple_account_user_split_new(_("Network"), "silcnet.org", '@');
-
-	return g_list_append(NULL, split);
-}
-
-static GList *
-silcpurple_protocol_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol)
-{
-	PurpleAccountOption *option;
-	GList *account_options = NULL;
-	GList *list;
-	char tmp[256];
-
-	option = purple_account_option_string_new(_("Connect server"), "server", "silc.silcnet.org");
-	account_options = g_list_append(account_options, option);
-
-	option = purple_account_option_int_new(_("Port"), "port", 706);
-	account_options = g_list_append(account_options, option);
-
-	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
-	option = purple_account_option_string_new(_("Public Key file"), "public-key", tmp);
-	account_options = g_list_append(account_options, option);
-
-	g_snprintf(tmp, sizeof(tmp), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
-	option = purple_account_option_string_new(_("Private Key file"), "private-key", tmp);
-	account_options = g_list_append(account_options, option);
-
-	list = NULL;
-	for (int i = 0; silc_default_ciphers[i].name; i++) {
-		PurpleKeyValuePair *kvp = purple_key_value_pair_new_full(silc_default_ciphers[i].name,
-		                                                         g_strdup(silc_default_ciphers[i].name), g_free);
-		list = g_list_append(list, kvp);
-	}
-	option = purple_account_option_list_new(_("Cipher"), "cipher", list);
-	account_options = g_list_append(account_options, option);
-
-	list = NULL;
-	for (int i = 0; silc_default_hmacs[i].name; i++) {
-		PurpleKeyValuePair *kvp = purple_key_value_pair_new_full(silc_default_hmacs[i].name,
-		                                                         g_strdup(silc_default_hmacs[i].name), g_free);
-		list = g_list_append(list, kvp);
-	}
-	option = purple_account_option_list_new(_("HMAC"), "hmac", list);
-	account_options = g_list_append(account_options, option);
-
-	option = purple_account_option_bool_new(_("Use Perfect Forward Secrecy"), "pfs", FALSE);
-	account_options = g_list_append(account_options, option);
-
-	option = purple_account_option_bool_new(_("Public key authentication"), "pubkey-auth", FALSE);
-	account_options = g_list_append(account_options, option);
-
-	option = purple_account_option_bool_new(_("Block IMs without Key Exchange"), "block-ims", FALSE);
-	account_options = g_list_append(account_options, option);
-
-	option = purple_account_option_bool_new(_("Block messages to whiteboard"), "block-wb", FALSE);
-	account_options = g_list_append(account_options, option);
-
-	option = purple_account_option_bool_new(_("Automatically open whiteboard"), "open-wb", FALSE);
-	account_options = g_list_append(account_options, option);
-
-	option = purple_account_option_bool_new(_("Digitally sign and verify all messages"), "sign-verify", FALSE);
-	account_options = g_list_append(account_options, option);
-
-	return account_options;
-}
-
-static PurpleBuddyIconSpec *
-silcpurple_protocol_get_buddy_icon_spec(G_GNUC_UNUSED PurpleProtocol *protocol)
-{
-	return purple_buddy_icon_spec_new("jpeg,gif,png,bmp",
-	                                  0, 0, 96, 96, 0,
-	                                  PURPLE_ICON_SCALE_DISPLAY);
-}
-
-static PurpleWhiteboardOps *
-silcpurple_protocol_get_whiteboard_ops(G_GNUC_UNUSED PurpleProtocol *protocol)
-{
-	return &silcpurple_wb_ops;
-}
-
-static void
-silcpurple_protocol_init(G_GNUC_UNUSED SilcProtocol *self)
-{
-}
-
-static void
-silcpurple_protocol_class_init(SilcProtocolClass *klass)
-{
-	PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
-
-	protocol_class->login = silcpurple_login;
-	protocol_class->close = silcpurple_close;
-	protocol_class->status_types = silcpurple_away_states;
-
-	protocol_class->get_user_splits = silcpurple_protocol_get_user_splits;
-	protocol_class->get_account_options = silcpurple_protocol_get_account_options;
-	protocol_class->get_buddy_icon_spec = silcpurple_protocol_get_buddy_icon_spec;
-	protocol_class->get_whiteboard_ops = silcpurple_protocol_get_whiteboard_ops;
-}
-
-static void
-silcpurple_protocol_class_finalize(G_GNUC_UNUSED SilcProtocolClass *klass)
-{
-}
-
-static void
-silcpurple_protocol_actions_iface_init(PurpleProtocolActionsInterface *iface)
-{
-	iface->get_prefix = silcpurple_protocol_actions_get_prefix;
-	iface->get_action_group = silcpurple_protocol_actions_get_action_group;
-	iface->get_menu = silcpurple_protocol_actions_get_menu;
-}
-
-static void
-silcpurple_protocol_client_iface_init(PurpleProtocolClientInterface *client_iface)
-{
-	client_iface->status_text     = silcpurple_status_text;
-	client_iface->tooltip_text    = silcpurple_tooltip_text;
-	client_iface->blist_node_menu = silcpurple_blist_node_menu;
-}
-
-static void
-silcpurple_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface)
-{
-	server_iface->set_info       = silcpurple_set_info;
-	server_iface->get_info       = silcpurple_get_info;
-	server_iface->set_status     = silcpurple_set_status;
-	server_iface->set_idle       = silcpurple_idle_set;
-	server_iface->change_passwd  = silcpurple_change_passwd;
-	server_iface->add_buddy      = silcpurple_add_buddy;
-	server_iface->remove_buddy   = silcpurple_remove_buddy;
-	server_iface->keepalive      = silcpurple_keepalive;
-	server_iface->set_buddy_icon = silcpurple_buddy_set_icon;
-}
-
-static void
-silcpurple_protocol_im_iface_init(PurpleProtocolIMInterface *im_iface)
-{
-	im_iface->send = silcpurple_send_im;
-}
-
-static void
-silcpurple_protocol_chat_iface_init(PurpleProtocolChatInterface *chat_iface)
-{
-	chat_iface->info          = silcpurple_chat_info;
-	chat_iface->info_defaults = silcpurple_chat_info_defaults;
-	chat_iface->join          = silcpurple_chat_join;
-	chat_iface->get_name      = silcpurple_get_chat_name;
-	chat_iface->invite        = silcpurple_chat_invite;
-	chat_iface->leave         = silcpurple_chat_leave;
-	chat_iface->send          = silcpurple_chat_send;
-	chat_iface->set_topic     = silcpurple_chat_set_topic;
-}
-
-static void
-silcpurple_protocol_roomlist_iface_init(PurpleProtocolRoomlistInterface *roomlist_iface)
-{
-	roomlist_iface->get_list = silcpurple_roomlist_get_list;
-	roomlist_iface->cancel   = silcpurple_roomlist_cancel;
-}
-
-static void
-silcpurple_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
-{
-	xfer_iface->send_file = silcpurple_ftp_send_file;
-	xfer_iface->new_xfer  = silcpurple_ftp_new_xfer;
-}
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
-        SilcProtocol, silcpurple_protocol, PURPLE_TYPE_PROTOCOL, 0,
-
-        G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ACTIONS,
-                                      silcpurple_protocol_actions_iface_init)
-
-        G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,
-                                      silcpurple_protocol_client_iface_init)
-
-        G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
-                                      silcpurple_protocol_server_iface_init)
-
-        G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM,
-                                      silcpurple_protocol_im_iface_init)
-
-        G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT,
-                                      silcpurple_protocol_chat_iface_init)
-
-        G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ROOMLIST,
-                                      silcpurple_protocol_roomlist_iface_init)
-
-        G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_XFER,
-                                      silcpurple_protocol_xfer_iface_init));
-
-static PurpleProtocol *
-silcpurple_protocol_new(void) {
-	return PURPLE_PROTOCOL(g_object_new(
-	        SILCPURPLE_TYPE_PROTOCOL,
-	        "id", "prpl-silc",
-	        "name", "SILC",
-	        "description", _("Secure Internet Live Conferencing protocol."),
-	        "icon-name", "im-silc",
-	        "icon-resource-path", "/im/pidgin/libpurple/silc/icons",
-	        "options", OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
-	                   OPT_PROTO_PASSWORD_OPTIONAL |
-	                   OPT_PROTO_SLASH_COMMANDS_NATIVE,
-	        NULL));
-}
-
-static GPluginPluginInfo *
-silc_query(GError **error)
-{
-	const gchar * const authors[] = {
-		"Pekka Riikonen",
-		NULL
-	};
-
-	return purple_plugin_info_new(
-		"id",           "prpl-silc",
-		"name",         "SILC Protocol",
-		"version",      "1.1",
-		"category",     N_("Protocol"),
-		"summary",      N_("SILC Protocol Plugin"),
-		"description",  N_("Secure Internet Live Conferencing (SILC) Protocol"),
-		"authors",      authors,
-		"website",      "http://silcnet.org/",
-		"abi-version",  PURPLE_ABI_VERSION,
-		"flags",        PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
-		                PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
-		NULL
-	);
-}
-
-static gboolean
-silc_load(GPluginPlugin *plugin, GError **error)
-{
-	PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
-	silcpurple_protocol_register_type(G_TYPE_MODULE(plugin));
-
-	silcpurple_xfer_register(G_TYPE_MODULE(plugin));
-
-	my_protocol = silcpurple_protocol_new();
-	if(!purple_protocol_manager_register(manager, my_protocol, error)) {
-		g_clear_object(&my_protocol);
-
-		return FALSE;
-	}
-
-	purple_prefs_remove("/plugins/prpl/silc");
-
-	silc_log_set_callback(SILC_LOG_ERROR, silcpurple_log_error, NULL);
-	silcpurple_register_commands();
-
-	return TRUE;
-}
-
-static gboolean
-silc_unload(GPluginPlugin *plugin, gboolean shutdown, GError **error)
-{
-	PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
-	if(!purple_protocol_manager_unregister(manager, my_protocol, error)) {
-		return FALSE;
-	}
-
-	silcpurple_unregister_commands();
-
-	g_clear_object(&my_protocol);
-
-	return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(silc)
--- a/libpurple/protocols/silc/silcpurple.h	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
-
-  silcpurple.h
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#ifndef PURPLE_SILC_SILCPURPLE_H
-#define PURPLE_SILC_SILCPURPLE_H
-
-#include <silc.h>
-#include <silcclient.h>
-
-/* Purple includes */
-#include <purple.h>
-
-#define SILCPURPLE_TYPE_PROTOCOL (silcpurple_protocol_get_type())
-G_DECLARE_FINAL_TYPE(SilcProtocol, silcpurple_protocol, SILC, PROTOCOL,
-                     PurpleProtocol)
-
-/* Default public and private key file names */
-#define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub"
-#define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv"
-
-/* Default settings for creating key pair */
-#define SILCPURPLE_DEF_PKCS "rsa"
-#define SILCPURPLE_DEF_PKCS_LEN 2048
-
-#define SILCPURPLE_PRVGRP 0x001fffff
-
-/* Status IDs */
-#define SILCPURPLE_STATUS_ID_OFFLINE	"offline"
-#define SILCPURPLE_STATUS_ID_AVAILABLE "available"
-#define SILCPURPLE_STATUS_ID_HYPER	"hyper"
-#define SILCPURPLE_STATUS_ID_AWAY		"away"
-#define SILCPURPLE_STATUS_ID_BUSY		"busy"
-#define SILCPURPLE_STATUS_ID_INDISPOSED "indisposed"
-#define SILCPURPLE_STATUS_ID_PAGE		"page"
-
-typedef struct {
-	unsigned long id;
-	const char *channel;
-	unsigned long chid;
-	const char *parentch;
-	SilcChannelPrivateKey key;
-} *SilcPurplePrvgrp;
-
-/* The SILC Purple plugin context */
-typedef struct SilcPurpleStruct {
-	GCancellable *cancellable;
-	GSocketConnection *sockconn;
-
-	SilcClient client;
-	SilcClientConnection conn;
-	SilcPublicKey public_key;
-	SilcPrivateKey private_key;
-	SilcHash sha1hash;
-
-	SilcDList tasks;
-	guint scheduler;
-	PurpleConnection *gc;
-	PurpleAccount *account;
-	unsigned long channel_ids;
-	GList *grps;
-
-	char *motd;
-	PurpleRoomlist *roomlist;
-	SilcMimeAssembler mimeass;
-	unsigned int detaching            : 1;
-	unsigned int resuming             : 1;
-	unsigned int roomlist_cancelled   : 1;
-	unsigned int chpk                 : 1;
-} *SilcPurple;
-
-void silc_say(SilcClient client, SilcClientConnection conn,
-	      SilcClientMessageType type, char *msg, ...);
-SilcBool silcpurple_command_reply(SilcClient client, SilcClientConnection conn,
-				  SilcCommand command, SilcStatus status,
-				  SilcStatus error, void *context, va_list ap);
-gboolean silcpurple_check_silc_dir(PurpleConnection *gc);
-const char *silcpurple_silcdir(void);
-const char *silcpurple_session_file(const char *account);
-void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
-				  const char *name,
-				  SilcConnectionType conn_type,
-				  SilcPublicKey public_key,
-				  SilcVerifyPublicKey completion,
-				  void *context);
-GList *silcpurple_buddy_menu(PurpleBuddy *buddy);
-void silcpurple_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message);
-void silcpurple_send_buddylist(PurpleConnection *gc);
-void silcpurple_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
-void silcpurple_buddy_keyagr_request(SilcClient client,
-				     SilcClientConnection conn,
-				     SilcClientEntry client_entry,
-				     const char *hostname, SilcUInt16 port,
-				     SilcUInt16 protocol);
-void silcpurple_idle_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc, int idle);
-void silcpurple_tooltip_text(PurpleProtocolClient *ppclient, PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
-char *silcpurple_status_text(PurpleProtocolClient *ppclient, PurpleBuddy *b);
-gboolean silcpurple_ip_is_private(const char *ip);
-void silcpurple_ftp_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name, const char *file);
-PurpleXfer *silcpurple_ftp_new_xfer(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *name);
-void silcpurple_ftp_request(SilcClient client, SilcClientConnection conn,
-			  SilcClientEntry client_entry, SilcUInt32 session_id,
-			  const char *hostname, SilcUInt16 port);
-void silcpurple_show_public_key(SilcPurple sg,
-			      const char *name, SilcPublicKey public_key,
-			      GCallback callback, void *context);
-void silcpurple_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who);
-SilcAttributePayload
-silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute);
-void silcpurple_get_umode_string(SilcUInt32 mode, char *buf,
-			       SilcUInt32 buf_size);
-void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
-				SilcUInt32 buf_size);
-void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
-				 SilcUInt32 buf_size);
-GList *silcpurple_chat_info(PurpleProtocolChat *protocol_chat, PurpleConnection *gc);
-GHashTable *silcpurple_chat_info_defaults(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, const char *chat_name);
-GList *silcpurple_chat_menu(PurpleChat *);
-void silcpurple_chat_join(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, GHashTable *data);
-char *silcpurple_get_chat_name(PurpleProtocolChat *protocol_chat, GHashTable *data);
-void silcpurple_chat_invite(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *msg,
-			  const char *name);
-void silcpurple_chat_leave(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id);
-int silcpurple_chat_send(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, PurpleMessage *msg);
-void silcpurple_chat_set_topic(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int id, const char *topic);
-PurpleRoomlist *silcpurple_roomlist_get_list(PurpleProtocolRoomlist *protocol_roomlist, PurpleConnection *gc);
-void silcpurple_roomlist_cancel(PurpleProtocolRoomlist *protocol_roomlist, PurpleRoomlist *list);
-void silcpurple_chat_chauth_show(SilcPurple sg, SilcChannelEntry channel,
-				 SilcDList channel_pubkeys);
-void silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
-					 char **contactstr, char **langstr, char **devicestr,
-					 char **tzstr, char **geostr);
-void silcpurple_buddy_set_icon(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img);
-SilcDList silcpurple_image_message(const char *msg, SilcMessageFlags *mflags);
-
-#ifdef _WIN32
-typedef int uid_t;
-
-struct passwd {
-	char	*pw_name;	/* user name */
-	char	*pw_passwd;	/* user password */
-	int		pw_uid;		/* user id */
-	int		pw_gid;		/* group id */
-	char	*pw_gecos;	/* real name */
-	char	*pw_dir;	/* home directory */
-	char	*pw_shell;	/* shell program */
-};
-
-struct passwd *getpwuid(int uid);
-int getuid(void);
-int geteuid(void);
-#endif
-
-#endif /* PURPLE_SILC_SILCPURPLE_H */
--- a/libpurple/protocols/silc/util.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,733 +0,0 @@
-/*
-
-  silcpurple_util.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2004 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#include <glib/gi18n-lib.h>
-#include <glib/gstdio.h>
-
-#include "silcpurple.h"
-
-/**************************** Utility Routines *******************************/
-
-static char str[256], str2[256];
-
-const char *silcpurple_silcdir(void)
-{
-	const char *hd = purple_home_dir();
-	memset(str, 0, sizeof(str));
-	g_snprintf(str, sizeof(str) - 1, "%s" G_DIR_SEPARATOR_S ".silc", hd ? hd : "/tmp");
-	return (const char *)str;
-}
-
-const char *silcpurple_session_file(const char *account)
-{
-	memset(str2, 0, sizeof(str2));
-	g_snprintf(str2, sizeof(str2) - 1, "%s" G_DIR_SEPARATOR_S "%s_session",
-		   silcpurple_silcdir(), account);
-	return (const char *)str2;
-}
-
-gboolean silcpurple_ip_is_private(const char *ip)
-{
-	if (silc_net_is_ip4(ip)) {
-		if (!strncmp(ip, "10.", 3)) {
-			return TRUE;
-		} else if (!strncmp(ip, "172.", 4) && strlen(ip) > 6) {
-			char tmp[3];
-			int s;
-			memset(tmp, 0, sizeof(tmp));
-			strncpy(tmp, ip + 4, 2);
-			s = atoi(tmp);
-			if (s >= 16 && s <= 31)
-				return TRUE;
-		} else if (!strncmp(ip, "192.168.", 8)) {
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-/* A fstat alternative, like g_stat for stat. */
-static int
-silcpurple_fstat(int fd, GStatBuf *st)
-{
-	int ret;
-
-	g_return_val_if_fail(st != NULL, -1);
-
-#ifdef _WIN32
-	ret = _fstat(fd, st);
-#else
-	ret = fstat(fd, st);
-#endif
-
-	return ret;
-}
-
-/* This checks stats for various SILC files and directories. First it
-   checks if ~/.silc directory exist and is owned by the correct user. If
-   it doesn't exist, it will create the directory. After that it checks if
-   user's Public and Private key files exists and creates them if needed. */
-
-gboolean silcpurple_check_silc_dir(PurpleConnection *gc)
-{
-	char filename[256], file_public_key[256], file_private_key[256];
-	char servfilename[256], clientfilename[256], friendsfilename[256];
-	char pkd[256], prd[256];
-	GStatBuf st;
-	struct passwd *pw;
-	int fd;
-
-	pw = getpwuid(getuid());
-	if (!pw) {
-		purple_debug_error("silc", "silc: %s\n", g_strerror(errno));
-		return FALSE;
-	}
-
-	g_snprintf(filename, sizeof(filename) - 1, "%s", silcpurple_silcdir());
-	g_snprintf(servfilename, sizeof(servfilename) - 1, "%s" G_DIR_SEPARATOR_S "serverkeys",
-		   silcpurple_silcdir());
-	g_snprintf(clientfilename, sizeof(clientfilename) - 1, "%s" G_DIR_SEPARATOR_S "clientkeys",
-		   silcpurple_silcdir());
-	g_snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s" G_DIR_SEPARATOR_S "friends",
-		   silcpurple_silcdir());
-
-	if (pw->pw_uid != geteuid()) {
-		purple_debug_error("silc", "Couldn't create directories due to wrong uid!\n");
-		return FALSE;
-	}
-
-	/*
-	 * Check ~/.silc directory
-	 */
-	if (g_mkdir(filename, 0755) != 0 && errno != EEXIST) {
-		purple_debug_error("silc", "Couldn't create '%s' directory\n", filename);
-		return FALSE;
-	}
-
-#ifndef _WIN32
-	if ((g_stat(filename, &st)) == -1) {
-		purple_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, g_strerror(errno));
-		return FALSE;
-	} else {
-		/* Check the owner of the dir */
-		if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-			purple_debug_error("silc", "You don't seem to own '%s' directory\n",
-				filename);
-			return FALSE;
-		}
-	}
-#endif
-
-	/*
-	 * Check ~./silc/serverkeys directory
-	 */
-	if (g_mkdir(servfilename, 0755) != 0 && errno != EEXIST) {
-		purple_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
-		return FALSE;
-	}
-
-	/*
-	 * Check ~./silc/clientkeys directory
-	 */
-	if (g_mkdir(clientfilename, 0755) != 0 && errno != EEXIST) {
-		purple_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
-		return FALSE;
-	}
-
-	/*
-	 * Check ~./silc/friends directory
-	 */
-	if (g_mkdir(friendsfilename, 0755) != 0 && errno != EEXIST) {
-		purple_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
-		return FALSE;
-	}
-
-	/*
-	 * Check Public and Private keys
-	 */
-	g_snprintf(pkd, sizeof(pkd), "%s" G_DIR_SEPARATOR_S "public_key.pub", silcpurple_silcdir());
-	g_snprintf(prd, sizeof(prd), "%s" G_DIR_SEPARATOR_S "private_key.prv", silcpurple_silcdir());
-	g_snprintf(file_public_key, sizeof(file_public_key) - 1, "%s",
-		   purple_account_get_string(purple_connection_get_account(gc), "public-key", pkd));
-	g_snprintf(file_private_key, sizeof(file_public_key) - 1, "%s",
-		   purple_account_get_string(purple_connection_get_account(gc), "private-key", prd));
-
-	if ((g_stat(file_public_key, &st)) == -1) {
-		/* If file doesn't exist */
-		if (errno == ENOENT) {
-			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
-						  SILCPURPLE_DEF_PKCS_LEN,
-						  file_public_key,
-						  file_private_key, NULL,
-						  (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
-						  NULL, NULL, FALSE)) {
-				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-				                             _("Unable to create SILC key pair"));
-				return FALSE;
-			}
-
-			if ((g_stat(file_public_key, &st)) == -1) {
-				purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
-						   file_public_key, g_strerror(errno));
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
-					   file_public_key, g_strerror(errno));
-			return FALSE;
-		}
-	}
-
-#ifndef _WIN32
-	/* Check the owner of the public key */
-	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-		purple_debug_error("silc", "You don't seem to own your public key!?\n");
-		return FALSE;
-	}
-#endif
-
-	if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
-		if (silcpurple_fstat(fd, &st) == -1) {
-			purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-					   file_private_key, g_strerror(errno));
-			close(fd);
-			return FALSE;
-		}
-	} else {
-		/* If file doesn't exist */
-		if (errno == ENOENT) {
-			if (!silc_create_key_pair(SILCPURPLE_DEF_PKCS,
-						  SILCPURPLE_DEF_PKCS_LEN,
-						  file_public_key,
-						  file_private_key, NULL,
-						  (purple_connection_get_password(gc) == NULL) ? "" : purple_connection_get_password(gc),
-						  NULL, NULL, FALSE)) {
-				purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-				                             _("Unable to create SILC key pair"));
-				return FALSE;
-			}
-
-			if ((fd = g_open(file_private_key, O_RDONLY, 0)) != -1) {
-				if (silcpurple_fstat(fd, &st) == -1) {
-					purple_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
-							   file_private_key, g_strerror(errno));
-					close(fd);
-					return FALSE;
-				}
-			} else {
-				purple_debug_error("silc", "Couldn't open '%s' "
-					"private key, error: %s\n",
-					file_private_key, g_strerror(errno));
-				return FALSE;
-			}
-		} else {
-			purple_debug_error("silc", "Couldn't open '%s' private key, error: %s\n",
-					   file_private_key, g_strerror(errno));
-			return FALSE;
-		}
-	}
-
-#ifndef _WIN32
-	/* Check the owner of the private key */
-	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-		purple_debug_error("silc", "You don't seem to own your private key!?\n");
-		if (fd != -1)
-			close(fd);
-		return FALSE;
-	}
-
-	/* Check the permissions for the private key */
-	if ((st.st_mode & 0777) != 0600) {
-		purple_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n"
-			"Trying to change them ...\n", file_private_key);
-		if ((fd == -1) || (fchmod(fd, S_IRUSR | S_IWUSR) == -1)) {
-			purple_debug_error("silc",
-				"Failed to change permissions for private key file!\n"
-				"Permissions for your private key file must be 0600.\n");
-			if (fd != -1)
-				close(fd);
-			return FALSE;
-		}
-		purple_debug_warning("silc", "Done.\n\n");
-	}
-#endif
-
-	if (fd != -1)
-		close(fd);
-
-#ifdef _WIN32
-	/* on win32, we calloc pw so pass it to free
-	 * (see the getpwuid code below)
-	 */
-	free(pw);
-#endif
-
-	return TRUE;
-}
-
-#ifdef _WIN32
-struct passwd *getpwuid(uid_t uid) {
-	struct passwd *pwd = calloc(1, sizeof(struct passwd));
-	return pwd;
-}
-
-uid_t getuid() {
-	return 0;
-}
-
-uid_t geteuid() {
-	return 0;
-}
-#endif
-
-void silcpurple_show_public_key(SilcPurple sg,
-				const char *name, SilcPublicKey public_key,
-				GCallback callback, void *context)
-{
-	SilcPublicKeyIdentifier ident;
-	SilcSILCPublicKey silc_pubkey;
-	char *fingerprint, *babbleprint;
-	unsigned char *pk;
-	SilcUInt32 pk_len, key_len = 0;
-	GString *s;
-
-	/* We support showing only SILC public keys for now */
-	if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC)
-	  return;
-
-	silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key);
-	ident = &silc_pubkey->identifier;
-	key_len = silc_pkcs_public_key_get_len(public_key);
-
-	pk = silc_pkcs_public_key_encode(public_key, &pk_len);
-	if (!pk)
-	  return;
-	fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
-	babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
-	if (!fingerprint || !babbleprint)
-	  return;
-
-	s = g_string_new("");
-	if (ident->realname)
-		/* Hint for translators: Please check the tabulator width here and in
-		   the next strings (short strings: 2 tabs, longer strings 1 tab,
-		   sum: 3 tabs or 24 characters) */
-		g_string_append_printf(s, _("Real Name: \t%s\n"), ident->realname);
-	if (ident->username)
-		g_string_append_printf(s, _("User Name: \t%s\n"), ident->username);
-	if (ident->email)
-		g_string_append_printf(s, _("Email: \t\t%s\n"), ident->email);
-	if (ident->host)
-		g_string_append_printf(s, _("Host Name: \t%s\n"), ident->host);
-	if (ident->org)
-		g_string_append_printf(s, _("Organization: \t%s\n"), ident->org);
-	if (ident->country)
-		g_string_append_printf(s, _("Country: \t%s\n"), ident->country);
-	g_string_append_printf(s, _("Algorithm: \t%s\n"), silc_pubkey->pkcs->name);
-	g_string_append_printf(s, _("Key Length: \t%d bits\n"), (int)key_len);
-	if (ident->version)
-	  g_string_append_printf(s, _("Version: \t%s\n"), ident->version);
-	g_string_append_printf(s, "\n");
-	g_string_append_printf(s, _("Public Key Fingerprint:\n%s\n\n"), fingerprint);
-	g_string_append_printf(s, _("Public Key Babbleprint:\n%s"), babbleprint);
-
-	purple_request_action(sg->gc, _("Public Key Information"),
-			      _("Public Key Information"),
-			      s->str, 0, purple_request_cpar_from_connection(sg->gc),
-			      context, 1, _("Close"), callback);
-
-	g_string_free(s, TRUE);
-	silc_free(fingerprint);
-	silc_free(babbleprint);
-	silc_free(pk);
-}
-
-SilcAttributePayload
-silcpurple_get_attr(SilcDList attrs, SilcAttribute attribute)
-{
-	SilcAttributePayload attr = NULL;
-
-	if (!attrs)
-		return NULL;
-
-	silc_dlist_start(attrs);
-	while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END)
-		if (attribute == silc_attribute_get_attribute(attr))
-			break;
-
-	return attr;
-}
-
-void silcpurple_get_umode_string(SilcUInt32 mode, char *buf,
-				 SilcUInt32 buf_size)
-{
-	memset(buf, 0, buf_size);
-	if ((mode & SILC_UMODE_SERVER_OPERATOR) ||
-	    (mode & SILC_UMODE_ROUTER_OPERATOR)) {
-		strcat(buf, (mode & SILC_UMODE_SERVER_OPERATOR) ?
-		       "[server operator] " :
-		       (mode & SILC_UMODE_ROUTER_OPERATOR) ?
-		       "[SILC operator] " : "[unknown mode] ");
-	}
-	if (mode & SILC_UMODE_GONE)
-		strcat(buf, "[away] ");
-	if (mode & SILC_UMODE_INDISPOSED)
-		strcat(buf, "[indisposed] ");
-	if (mode & SILC_UMODE_BUSY)
-		strcat(buf, "[busy] ");
-	if (mode & SILC_UMODE_PAGE)
-		strcat(buf, "[wake me up] ");
-	if (mode & SILC_UMODE_HYPER)
-		strcat(buf, "[hyperactive] ");
-	if (mode & SILC_UMODE_ROBOT)
-		strcat(buf, "[robot] ");
-	if (mode & SILC_UMODE_ANONYMOUS)
-		strcat(buf, "[anonymous] ");
-	if (mode & SILC_UMODE_BLOCK_PRIVMSG)
-		strcat(buf, "[blocks private messages] ");
-	if (mode & SILC_UMODE_DETACHED)
-		strcat(buf, "[detached] ");
-	if (mode & SILC_UMODE_REJECT_WATCHING)
-		strcat(buf, "[rejects watching] ");
-	if (mode & SILC_UMODE_BLOCK_INVITE)
-		strcat(buf, "[blocks invites] ");
-	g_strchomp(buf);
-}
-
-void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
-				  SilcUInt32 buf_size)
-{
-	memset(buf, 0, buf_size);
-	if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
-		strcat(buf, "[permanent] ");
-	if (mode & SILC_CHANNEL_MODE_PRIVATE)
-		strcat(buf, "[private] ");
-	if (mode & SILC_CHANNEL_MODE_SECRET)
-		strcat(buf, "[secret] ");
-	if (mode & SILC_CHANNEL_MODE_PRIVKEY)
-		strcat(buf, "[private key] ");
-	if (mode & SILC_CHANNEL_MODE_INVITE)
-		strcat(buf, "[invite only] ");
-	if (mode & SILC_CHANNEL_MODE_TOPIC)
-		strcat(buf, "[topic restricted] ");
-	if (mode & SILC_CHANNEL_MODE_ULIMIT)
-		strcat(buf, "[user count limit] ");
-	if (mode & SILC_CHANNEL_MODE_PASSPHRASE)
-		strcat(buf, "[passphrase auth] ");
-	if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
-		strcat(buf, "[public key auth] ");
-	if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
-		strcat(buf, "[users silenced] ");
-	if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
-		strcat(buf, "[operators silenced] ");
-	g_strchomp(buf);
-}
-
-void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
-				 SilcUInt32 buf_size)
-{
-	memset(buf, 0, buf_size);
-	if (mode & SILC_CHANNEL_UMODE_CHANFO)
-		strcat(buf, "[founder] ");
-	if (mode & SILC_CHANNEL_UMODE_CHANOP)
-		strcat(buf, "[operator] ");
-	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)
-		strcat(buf, "[blocks messages] ");
-	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)
-		strcat(buf, "[blocks user messages] ");
-	if (mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)
-		strcat(buf, "[blocks robot messages] ");
-	if (mode & SILC_CHANNEL_UMODE_QUIET)
-		strcat(buf, "[quieted] ");
-	g_strchomp(buf);
-}
-
-void
-silcpurple_parse_attrs(SilcDList attrs, char **moodstr, char **statusstr,
-		       char **contactstr, char **langstr, char **devicestr,
-		       char **tzstr, char **geostr)
-{
-	SilcAttributePayload attr;
-	SilcAttributeMood mood = 0;
-	SilcAttributeContact contact;
-	SilcAttributeObjDevice device;
-	SilcAttributeObjGeo geo;
-
-	char tmp[1024];
-	GString *s;
-
-	*moodstr = NULL;
-	*statusstr = NULL;
-	*contactstr = NULL;
-	*langstr = NULL;
-	*devicestr = NULL;
-	*tzstr = NULL;
-	*geostr = NULL;
-
-	if (!attrs)
-		return;
-
-	s = g_string_new("");
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_MOOD);
-	if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
-		if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
-			g_string_append_printf(s, "[%s] ", _("Happy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SAD)
-			g_string_append_printf(s, "[%s] ", _("Sad"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANGRY)
-			g_string_append_printf(s, "[%s] ", _("Angry"));
-		if (mood & SILC_ATTRIBUTE_MOOD_JEALOUS)
-			g_string_append_printf(s, "[%s] ", _("Jealous"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ASHAMED)
-			g_string_append_printf(s, "[%s] ", _("Ashamed"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
-			g_string_append_printf(s, "[%s] ", _("Invincible"));
-		if (mood & SILC_ATTRIBUTE_MOOD_INLOVE)
-			g_string_append_printf(s, "[%s] ", _("In Love"));
-		if (mood & SILC_ATTRIBUTE_MOOD_SLEEPY)
-			g_string_append_printf(s, "[%s] ", _("Sleepy"));
-		if (mood & SILC_ATTRIBUTE_MOOD_BORED)
-			g_string_append_printf(s, "[%s] ", _("Bored"));
-		if (mood & SILC_ATTRIBUTE_MOOD_EXCITED)
-			g_string_append_printf(s, "[%s] ", _("Excited"));
-		if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
-			g_string_append_printf(s, "[%s] ", _("Anxious"));
-	}
-	if (*s->str != '\0') {
-		*moodstr = g_string_free(s, FALSE);
-		g_strchomp(*moodstr);
-	} else
-		g_string_free(s, TRUE);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_STATUS_FREETEXT);
-	memset(tmp, 0, sizeof(tmp));
-	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		*statusstr = g_strdup(tmp);
-
-	s = g_string_new("");
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT);
-	if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) {
-		if (contact & SILC_ATTRIBUTE_CONTACT_CHAT)
-			g_string_append_printf(s, "[%s] ", _("Chat"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL)
-			g_string_append_printf(s, "[%s] ", _("Email"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_CALL)
-			g_string_append_printf(s, "[%s] ", _("Phone"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_PAGE)
-			g_string_append_printf(s, "[%s] ", _("Paging"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_SMS)
-			g_string_append_printf(s, "[%s] ", _("SMS"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_MMS)
-			g_string_append_printf(s, "[%s] ", _("MMS"));
-		if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO)
-			g_string_append_printf(s, "[%s] ", _("Video Conferencing"));
-	}
-	if (*s->str != '\0') {
-		*contactstr = g_string_free(s, FALSE);
-		g_strchomp(*contactstr);
-	} else
-		g_string_free(s, TRUE);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE);
-	memset(tmp, 0, sizeof(tmp));
-	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		*langstr = g_strdup(tmp);
-
-	s = g_string_new("");
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_DEVICE_INFO);
-	memset(&device, 0, sizeof(device));
-	if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) {
-		if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER)
-			g_string_append_printf(s, "%s: ", _("Computer"));
-		if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE)
-			g_string_append_printf(s, "%s: ", _("Mobile Phone"));
-		if (device.type == SILC_ATTRIBUTE_DEVICE_PDA)
-			g_string_append_printf(s, "%s: ", _("PDA"));
-		if (device.type == SILC_ATTRIBUTE_DEVICE_TERMINAL)
-			g_string_append_printf(s, "%s: ", _("Terminal"));
-		g_string_append_printf(s, "%s %s %s %s",
-				device.manufacturer ? device.manufacturer : "",
-				device.version ? device.version : "",
-				device.model ? device.model : "",
-				device.language ? device.language : "");
-	}
-	if (*s->str != '\0')
-		*devicestr = g_string_free(s, FALSE);
-	else
-		g_string_free(s, TRUE);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_TIMEZONE);
-	memset(tmp, 0, sizeof(tmp));
-	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		*tzstr = g_strdup(tmp);
-
-	attr = silcpurple_get_attr(attrs, SILC_ATTRIBUTE_GEOLOCATION);
-	memset(&geo, 0, sizeof(geo));
-	if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo)))
-		*geostr = g_strdup_printf("%s %s %s (%s)",
-				geo.longitude ? geo.longitude : "",
-				geo.latitude ? geo.latitude : "",
-				geo.altitude ? geo.altitude : "",
-				geo.accuracy ? geo.accuracy : "");
-}
-
-/* Checks if message has images, and assembles MIME message if it has.
-   If only one image is present, creates simple MIME image message.  If
-   there are multiple images and/or text with images multipart MIME
-   message is created. */
-
-SilcDList silcpurple_image_message(const char *msg, SilcMessageFlags *mflags)
-{
-	SilcMime mime = NULL, p;
-	SilcDList list, parts = NULL;
-	const char *start, *end, *last;
-	GData *attribs;
-	gboolean images = FALSE;
-
-	last = msg;
-	while (last && *last && purple_markup_find_tag("img", last, &start,
-						     &end, &attribs)) {
-		PurpleImage *image = NULL;
-		const gchar *uri;
-
-		/* Check if there is text before image */
-		if (start - last) {
-			char *text, *tmp;
-			p = silc_mime_alloc();
-
-			/* Add content type */
-			silc_mime_add_field(p, "Content-Type",
-					    "text/plain; charset=utf-8");
-
-			tmp = g_strndup(last, start - last);
-			text = purple_unescape_html(tmp);
-			g_free(tmp);
-
-			/* Add text */
-			silc_mime_add_data(p, (const unsigned char *)text, strlen(text));
-			g_free(text);
-
-			if (!parts)
-				parts = silc_dlist_init();
-			silc_dlist_add(parts, p);
-		}
-
-		uri = g_datalist_get_data(&attribs, "src");
-		if (uri)
-			image = purple_image_store_get_from_uri(uri);
-		if (uri) {
-			unsigned long imglen = purple_image_get_data_size(image);
-			gconstpointer img = purple_image_get_data(image);
-			const gchar *type;
-
-			p = silc_mime_alloc();
-
-			/* Add content type */
-			type = purple_image_get_mimetype(image);
-			if (!type) {
-				g_datalist_clear(&attribs);
-				last = end + 1;
-				continue;
-			}
-			silc_mime_add_field(p, "Content-Type", type);
-
-			/* Add content transfer encoding */
-			silc_mime_add_field(p, "Content-Transfer-Encoding", "binary");
-
-			/* Add image data */
-			silc_mime_add_data(p, img, imglen);
-
-			if (!parts)
-				parts = silc_dlist_init();
-			silc_dlist_add(parts, p);
-			images = TRUE;
-		}
-
-		g_datalist_clear(&attribs);
-
-		/* Continue after tag */
-		last = end + 1;
-	}
-
-	/* Check for text after the image(s) */
-	if (images && last && *last) {
-		char *tmp = purple_unescape_html(last);
-		p = silc_mime_alloc();
-
-		/* Add content type */
-		silc_mime_add_field(p, "Content-Type",
-				    "text/plain; charset=utf-8");
-
-		/* Add text */
-		silc_mime_add_data(p, (const unsigned char *)tmp, strlen(tmp));
-		g_free(tmp);
-
-		if (!parts)
-			parts = silc_dlist_init();
-		silc_dlist_add(parts, p);
-	}
-
-	/* If there weren't any images, don't return anything. */
-	if (!images) {
-		if (parts)
-			silc_dlist_uninit(parts);
-		return NULL;
-	}
-
-	if (silc_dlist_count(parts) > 1) {
-		/* Multipart MIME message */
-		char b[32];
-		mime = silc_mime_alloc();
-		silc_mime_add_field(mime, "MIME-Version", "1.0");
-		g_snprintf(b, sizeof(b), "b%4X%4X",
-			   (unsigned int)time(NULL),
-			   silc_dlist_count(parts));
-		silc_mime_set_multipart(mime, "mixed", b);
-		silc_dlist_start(parts);
-		while ((p = silc_dlist_get(parts)) != SILC_LIST_END)
-			silc_mime_add_multipart(mime, p);
-	} else {
-		/* Simple MIME message */
-		silc_dlist_start(parts);
-		mime = silc_dlist_get(parts);
-		silc_mime_add_field(mime, "MIME-Version", "1.0");
-	}
-
-	*mflags &= ~SILC_MESSAGE_FLAG_UTF8;
-	*mflags |= SILC_MESSAGE_FLAG_DATA;
-
-	/* Encode message. Fragment if it is too large */
-	list = silc_mime_encode_partial(mime, 0xfc00);
-
-	silc_dlist_uninit(parts);
-
-	/* Added multiparts gets freed here */
-	silc_mime_free(mime);
-
-	return list;
-}
--- a/libpurple/protocols/silc/wb.c	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,547 +0,0 @@
-/*
-
-  wb.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2005 - 2007 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#include <glib/gi18n-lib.h>
-
-#include "silcpurple.h"
-#include "wb.h"
-
-/*
-  SILC Whiteboard packet:
-
-  1 byte	command
-  2 bytes	width
-  2 bytes	height
-  4 bytes	brush color
-  2 bytes	brush size
-  n bytes	data
-
-  Data:
-
-  4 bytes	x
-  4 bytes	y
-
-  Commands:
-
-  0x01		draw
-  0x02		clear
-
-  MIME:
-
-  MIME-Version: 1.0
-  Content-Type: application/x-wb
-  Content-Transfer-Encoding: binary
-
-*/
-
-#define SILCPURPLE_WB_MIME "MIME-Version: 1.0\r\nContent-Type: application/x-wb\r\nContent-Transfer-Encoding: binary\r\n\r\n"
-#define SILCPURPLE_WB_HEADER strlen(SILCPURPLE_WB_MIME) + 11
-
-#define SILCPURPLE_WB_WIDTH 500
-#define SILCPURPLE_WB_HEIGHT 400
-#define SILCPURPLE_WB_WIDTH_MAX 1024
-#define SILCPURPLE_WB_HEIGHT_MAX 1024
-
-/* Commands */
-typedef enum {
-	SILCPURPLE_WB_DRAW 	= 0x01,
-	SILCPURPLE_WB_CLEAR	= 0x02,
-} SilcPurpleWbCommand;
-
-/* Brush size */
-typedef enum {
-	SILCPURPLE_WB_BRUSH_SMALL = 2,
-	SILCPURPLE_WB_BRUSH_MEDIUM = 5,
-	SILCPURPLE_WB_BRUSH_LARGE = 10,
-} SilcPurpleWbBrushSize;
-
-/* Brush color (XXX Purple should provide default colors) */
-typedef enum {
-	SILCPURPLE_WB_COLOR_BLACK		= 0,
-	SILCPURPLE_WB_COLOR_RED		= 13369344,
-	SILCPURPLE_WB_COLOR_GREEN		= 52224,
-	SILCPURPLE_WB_COLOR_BLUE		= 204,
-	SILCPURPLE_WB_COLOR_YELLOW 	= 15658496,
-	SILCPURPLE_WB_COLOR_ORANGE	= 16737792,
-	SILCPURPLE_WB_COLOR_CYAN		= 52428,
-	SILCPURPLE_WB_COLOR_VIOLET	= 5381277,
-	SILCPURPLE_WB_COLOR_PURPLE	= 13369548,
-	SILCPURPLE_WB_COLOR_TAN		= 12093547,
-	SILCPURPLE_WB_COLOR_BROWN		= 5256485,
-	SILCPURPLE_WB_COLOR_GREY		= 11184810,
-	SILCPURPLE_WB_COLOR_WHITE		= 16777215,
-} SilcPurpleWbColor;
-
-typedef struct {
-	int type;		/* 0 = buddy, 1 = channel */
-	union {
-		SilcClientEntry client;
-		SilcChannelEntry channel;
-	} u;
-	int width;
-	int height;
-	int brush_size;
-	int brush_color;
-} *SilcPurpleWb;
-
-/* Initialize whiteboard */
-
-PurpleWhiteboard *silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry)
-{
-	PurpleWhiteboard *wb;
-	PurpleWhiteboardManager *manager;
-	SilcPurpleWb wbs;
-	gchar *id = NULL;
-
-	manager = purple_whiteboard_manager_get_default();
-
-	id = g_strdup_printf("silc-client-%s", client_entry->nickname);
-	wb = purple_whiteboard_manager_find(manager, id);
-	if(!PURPLE_IS_WHITEBOARD(wb)) {
-		wb = purple_whiteboard_new(sg->account, id, 0);
-		purple_whiteboard_manager_register(manager, wb, NULL);
-	}
-
-	g_free(id);
-
-	if(!PURPLE_IS_WHITEBOARD(wb)) {
-		return NULL;
-	}
-
-	if (!purple_whiteboard_get_protocol_data(wb)) {
-		wbs = silc_calloc(1, sizeof(*wbs));
-		if (!wbs)
-			return NULL;
-		wbs->type = 0;
-		wbs->u.client = client_entry;
-		wbs->width = SILCPURPLE_WB_WIDTH;
-		wbs->height = SILCPURPLE_WB_HEIGHT;
-		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
-		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
-		purple_whiteboard_set_protocol_data(wb, wbs);
-
-		/* Start the whiteboard */
-		purple_whiteboard_start(wb);
-		purple_whiteboard_clear(wb);
-	}
-
-	return wb;
-}
-
-PurpleWhiteboard *silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel)
-{
-	PurpleWhiteboardManager *manager = NULL;
-	PurpleWhiteboard *wb;
-	SilcPurpleWb wbs;
-	gchar *id;
-
-	manager = purple_whiteboard_manager_get_default();
-
-	id = g_strdup_printf("silc-channel-%s", channel->channel_name);
-	wb = purple_whiteboard_manager_find(manager, id);
-	if(!PURPLE_IS_WHITEBOARD(wb)) {
-		wb = purple_whiteboard_new(sg->account, id, 0);
-	}
-
-	g_free(id);
-
-	if(!PURPLE_IS_WHITEBOARD(wb)) {
-		return NULL;
-	}
-
-	if (!purple_whiteboard_get_protocol_data(wb)) {
-		wbs = silc_calloc(1, sizeof(*wbs));
-		if (!wbs)
-			return NULL;
-		wbs->type = 1;
-		wbs->u.channel = channel;
-		wbs->width = SILCPURPLE_WB_WIDTH;
-		wbs->height = SILCPURPLE_WB_HEIGHT;
-		wbs->brush_size = SILCPURPLE_WB_BRUSH_SMALL;
-		wbs->brush_color = SILCPURPLE_WB_COLOR_BLACK;
-		purple_whiteboard_set_protocol_data(wb, wbs);
-
-		/* Start the whiteboard */
-		purple_whiteboard_start(wb);
-		purple_whiteboard_clear(wb);
-	}
-
-	return wb;
-}
-
-static void
-silcpurple_wb_parse(PurpleWhiteboard *wb,
-		  unsigned char *message, SilcUInt32 message_len)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
-	SilcUInt8 command;
-	SilcUInt16 width, height, brush_size;
-	SilcUInt32 brush_color, x, y, dx, dy;
-	SilcBufferStruct buf;
-	int ret;
-
-	/* Parse the packet */
-	silc_buffer_set(&buf, message, message_len);
-	ret = silc_buffer_unformat(&buf,
-				   SILC_STR_UI_CHAR(&command),
-				   SILC_STR_UI_SHORT(&width),
-				   SILC_STR_UI_SHORT(&height),
-				   SILC_STR_UI_INT(&brush_color),
-				   SILC_STR_UI_SHORT(&brush_size),
-				   SILC_STR_END);
-	if (ret < 0)
-		return;
-	silc_buffer_pull(&buf, ret);
-
-	/* Update whiteboard if its dimensions changed */
-	if (width != wbs->width || height != wbs->height)
-		silcpurple_wb_set_dimensions(wb, width, height);
-
-	if (command == SILCPURPLE_WB_DRAW) {
-		/* Parse data and draw it */
-		ret = silc_buffer_unformat(&buf,
-					   SILC_STR_UI_INT(&dx),
-					   SILC_STR_UI_INT(&dy),
-					   SILC_STR_END);
-		if (ret < 0)
-			return;
-		silc_buffer_pull(&buf, 8);
-		x = dx;
-		y = dy;
-		while (silc_buffer_len(&buf) > 0) {
-			ret = silc_buffer_unformat(&buf,
-						   SILC_STR_UI_INT(&dx),
-						   SILC_STR_UI_INT(&dy),
-						   SILC_STR_END);
-			if (ret < 0)
-				return;
-			silc_buffer_pull(&buf, 8);
-
-			purple_whiteboard_draw_line(wb, x, y, x + dx, y + dy,
-						    brush_color, brush_size);
-			x += dx;
-			y += dy;
-		}
-	}
-
-	if (command == SILCPURPLE_WB_CLEAR)
-		purple_whiteboard_clear(wb);
-}
-
-typedef struct {
-  unsigned char *message;
-  SilcUInt32 message_len;
-  SilcPurple sg;
-  SilcClientEntry sender;
-  SilcChannelEntry channel;
-} *SilcPurpleWbRequest;
-
-static void
-silcpurple_wb_request_cb(SilcPurpleWbRequest req, gint id)
-{
-	PurpleWhiteboard *wb;
-
-	if (id != 1)
-		goto out;
-
-	if (!req->channel)
-		wb = silcpurple_wb_init(req->sg, req->sender);
-	else
-		wb = silcpurple_wb_init_ch(req->sg, req->channel);
-
-	silcpurple_wb_parse(wb, req->message, req->message_len);
-
-  out:
-	silc_free(req->message);
-	silc_free(req);
-}
-
-static void
-silcpurple_wb_request(SilcClient client, const unsigned char *message,
-		      SilcUInt32 message_len, SilcClientEntry sender,
-		      SilcChannelEntry channel)
-{
-	char tmp[256];
-	SilcPurpleWbRequest req;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	gc = client->application;
-	sg = purple_connection_get_protocol_data(gc);
-
-	/* Open whiteboard automatically if requested */
-	if (purple_account_get_bool(sg->account, "open-wb", FALSE)) {
-		PurpleWhiteboard *wb;
-
-		if (!channel)
-			wb = silcpurple_wb_init(sg, sender);
-		else
-			wb = silcpurple_wb_init_ch(sg, channel);
-
-		silcpurple_wb_parse(wb,
-				    (unsigned char *)message,
-				    message_len);
-		return;
-	}
-
-	/* Close any previous unaccepted requests */
-	purple_request_close_with_handle(sender);
-
-	if (!channel) {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("%s sent message to whiteboard. Would you like "
-			     "to open the whiteboard?"), sender->nickname);
-	} else {
-		g_snprintf(tmp, sizeof(tmp),
-			   _("%s sent message to whiteboard on %s channel. "
-			     "Would you like to open the whiteboard?"),
-			   sender->nickname, channel->channel_name);
-	}
-
-	req = silc_calloc(1, sizeof(*req));
-	if (!req)
-		return;
-	req->message = silc_memdup(message, message_len);
-	req->message_len = message_len;
-	req->sender = sender;
-	req->channel = channel;
-	req->sg = sg;
-
-	purple_request_action(gc, _("Whiteboard"), tmp, NULL, 1,
-		purple_request_cpar_from_connection(gc), req, 2,
-			    _("Yes"), G_CALLBACK(silcpurple_wb_request_cb),
-			    _("No"), G_CALLBACK(silcpurple_wb_request_cb));
-}
-
-/* Process incoming whiteboard message */
-
-void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn,
-			 SilcClientEntry sender, SilcMessagePayload payload,
-			 SilcMessageFlags flags, const unsigned char *message,
-			 SilcUInt32 message_len)
-{
-	PurpleWhiteboard *wb;
-	PurpleWhiteboardManager *manager;
-	gchar *id = NULL;
-
-	manager = purple_whiteboard_manager_get_default();
-
-	id = g_strdup_printf("silc-client-%s", sender->nickname);
-	wb = purple_whiteboard_manager_find(manager, id);
-	g_free(id);
-
-	if(!PURPLE_IS_WHITEBOARD(wb)) {
-		/* Ask user if they want to open the whiteboard */
-		silcpurple_wb_request(client, message, message_len, sender, NULL);
-		return;
-	}
-
-	silcpurple_wb_parse(wb, (unsigned char *)message, message_len);
-}
-
-/* Process incoming whiteboard message on channel */
-
-void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn,
-			    SilcClientEntry sender, SilcChannelEntry channel,
-			    SilcMessagePayload payload,
-			    SilcMessageFlags flags,
-			    const unsigned char *message,
-			    SilcUInt32 message_len)
-{
-	PurpleWhiteboard *wb;
-	PurpleWhiteboardManager *manager;
-	gchar *id;
-
-	manager = purple_whiteboard_manager_get_default();
-
-	id = g_strdup_printf("silc-channel-%s", channel->channel_name);
-	wb = purple_whiteboard_manager_find(manager, id);
-	g_free(id);
-
-	if(!PURPLE_IS_WHITEBOARD(wb)) {
-		/* Ask user if they want to open the whiteboard */
-		silcpurple_wb_request(client, message, message_len, sender, channel);
-
-		return;
-	}
-
-	silcpurple_wb_parse(wb, (unsigned char *)message, message_len);
-}
-
-/* Send whiteboard message */
-
-void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
-	SilcBuffer packet;
-	GList *list;
-	int len;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	g_return_if_fail(draw_list);
-	gc = purple_account_get_connection(purple_whiteboard_get_account(wb));
-	g_return_if_fail(gc);
- 	sg = purple_connection_get_protocol_data(gc);
-	g_return_if_fail(sg);
-
-	len = SILCPURPLE_WB_HEADER;
-	for (list = draw_list; list; list = list->next)
-		len += 4;
-
-	packet = silc_buffer_alloc_size(len);
-	if (!packet)
-		return;
-
-	/* Assmeble packet */
-	silc_buffer_format(packet,
-			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),
-			   SILC_STR_UI_CHAR(SILCPURPLE_WB_DRAW),
-			   SILC_STR_UI_SHORT(wbs->width),
-			   SILC_STR_UI_SHORT(wbs->height),
-			   SILC_STR_UI_INT(wbs->brush_color),
-			   SILC_STR_UI_SHORT(wbs->brush_size),
-			   SILC_STR_END);
-	silc_buffer_pull(packet, SILCPURPLE_WB_HEADER);
-	for (list = draw_list; list; list = list->next) {
-		silc_buffer_format(packet,
-				   SILC_STR_UI_INT(GPOINTER_TO_INT(list->data)),
-				   SILC_STR_END);
-		silc_buffer_pull(packet, 4);
-	}
-
-	/* Send the message */
-	if (wbs->type == 0) {
-		/* Private message */
-		silc_client_send_private_message(sg->client, sg->conn,
-						 wbs->u.client,
-						 SILC_MESSAGE_FLAG_DATA, NULL,
-						 packet->head, len);
-	} else if (wbs->type == 1) {
-		/* Channel message. Channel private keys are not supported. */
-		silc_client_send_channel_message(sg->client, sg->conn,
-						 wbs->u.channel, NULL,
-						 SILC_MESSAGE_FLAG_DATA, NULL,
-						 packet->head, len);
-	}
-
-	silc_buffer_free(packet);
-}
-
-/* Purple Whiteboard operations */
-
-void silcpurple_wb_start(PurpleWhiteboard *wb)
-{
-	/* Nothing here.  Everything is in initialization */
-}
-
-void silcpurple_wb_end(PurpleWhiteboard *wb)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
-	PurpleWhiteboardManager *manager;
-
-	manager = purple_whiteboard_manager_get_default();
-
-	silc_free(wbs);
-	purple_whiteboard_set_protocol_data(wb, NULL);
-
-	purple_whiteboard_manager_unregister(manager, wb, NULL);
-}
-
-void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data((PurpleWhiteboard *)wb);
-	*width = wbs->width;
-	*height = wbs->height;
-}
-
-void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
-	wbs->width = width > SILCPURPLE_WB_WIDTH_MAX ? SILCPURPLE_WB_WIDTH_MAX :
-			width;
-	wbs->height = height > SILCPURPLE_WB_HEIGHT_MAX ? SILCPURPLE_WB_HEIGHT_MAX :
-			height;
-
-	/* Update whiteboard */
-	purple_whiteboard_set_dimensions(wb, wbs->width, wbs->height);
-}
-
-void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data((PurpleWhiteboard *)wb);
-	*size = wbs->brush_size;
-	*color = wbs->brush_color;
-}
-
-void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
-	wbs->brush_size = size;
-	wbs->brush_color = color;
-
-	/* Update whiteboard */
-	purple_whiteboard_set_brush(wb, size, color);
-}
-
-void silcpurple_wb_clear(PurpleWhiteboard *wb)
-{
-	SilcPurpleWb wbs = purple_whiteboard_get_protocol_data(wb);
-	SilcBuffer packet;
-	int len;
-	PurpleConnection *gc;
-	SilcPurple sg;
-
-	gc = purple_account_get_connection(purple_whiteboard_get_account(wb));
-	g_return_if_fail(gc);
- 	sg = purple_connection_get_protocol_data(gc);
-	g_return_if_fail(sg);
-
-	len = SILCPURPLE_WB_HEADER;
-	packet = silc_buffer_alloc_size(len);
-	if (!packet)
-		return;
-
-	/* Assmeble packet */
-	silc_buffer_format(packet,
-			   SILC_STR_UI32_STRING(SILCPURPLE_WB_MIME),
-			   SILC_STR_UI_CHAR(SILCPURPLE_WB_CLEAR),
-			   SILC_STR_UI_SHORT(wbs->width),
-			   SILC_STR_UI_SHORT(wbs->height),
-			   SILC_STR_UI_INT(wbs->brush_color),
-			   SILC_STR_UI_SHORT(wbs->brush_size),
-			   SILC_STR_END);
-
-	/* Send the message */
-	if (wbs->type == 0) {
-		/* Private message */
-		silc_client_send_private_message(sg->client, sg->conn,
-						 wbs->u.client,
-						 SILC_MESSAGE_FLAG_DATA, NULL,
-						 packet->head, len);
-	} else if (wbs->type == 1) {
-		/* Channel message */
-		silc_client_send_channel_message(sg->client, sg->conn,
-						 wbs->u.channel, NULL,
-						 SILC_MESSAGE_FLAG_DATA, NULL,
-						 packet->head, len);
-	}
-
-	silc_buffer_free(packet);
-}
--- a/libpurple/protocols/silc/wb.h	Wed Oct 26 01:13:45 2022 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
-
-  silcpurple.h
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2005 Pekka Riikonen
-
-  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; version 2 of the License.
-
-  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.
-
-*/
-
-#ifndef PURPLE_SILC_WB_H
-#define PURPLE_SILC_WB_H
-
-#include "silcpurple.h"
-
-PurpleWhiteboard *
-silcpurple_wb_init(SilcPurple sg, SilcClientEntry client_entry);
-PurpleWhiteboard *
-silcpurple_wb_init_ch(SilcPurple sg, SilcChannelEntry channel);
-void silcpurple_wb_receive(SilcClient client, SilcClientConnection conn,
-			 SilcClientEntry sender, SilcMessagePayload payload,
-			 SilcMessageFlags flags, const unsigned char *message,
-			 SilcUInt32 message_len);
-void silcpurple_wb_receive_ch(SilcClient client, SilcClientConnection conn,
-			    SilcClientEntry sender, SilcChannelEntry channel,
-			    SilcMessagePayload payload,
-			    SilcMessageFlags flags,
-			    const unsigned char *message,
-			    SilcUInt32 message_len);
-void silcpurple_wb_start(PurpleWhiteboard *wb);
-void silcpurple_wb_end(PurpleWhiteboard *wb);
-void silcpurple_wb_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height);
-void silcpurple_wb_set_dimensions(PurpleWhiteboard *wb, int width, int height);
-void silcpurple_wb_get_brush(const PurpleWhiteboard *wb, int *size, int *color);
-void silcpurple_wb_set_brush(PurpleWhiteboard *wb, int size, int color);
-void silcpurple_wb_send(PurpleWhiteboard *wb, GList *draw_list);
-void silcpurple_wb_clear(PurpleWhiteboard *wb);
-
-#endif /* PURPLE_SILC_WB_H */
--- a/meson.build	Wed Oct 26 01:13:45 2022 -0500
+++ b/meson.build	Wed Oct 26 01:22:53 2022 -0500
@@ -340,12 +340,6 @@
 	enable_avahi = avahi_client.found() and avahi_glib.found()
 endif
 
-
-#######################################################################
-# Check for SILC client includes and libraries
-#######################################################################
-silc = dependency('silcclient', version : '>= 1.1.1', required : get_option('silc'))
-
 #######################################################################
 # Check for Gadu-Gadu protocol library (libgadu)
 #######################################################################
@@ -370,7 +364,7 @@
 
 
 DEFAULT_PRPLS = ['bonjour', 'demo', 'facebook', 'gg', 'irc', 'ircv3', 'jabber',
-                 'novell', 'null', 'sametime', 'silc', 'zephyr']
+                 'novell', 'null', 'sametime', 'zephyr']
 ALL_PRPLS = DEFAULT_PRPLS + ['null']
 
 dynamic_list = get_option('dynamic-prpls').split(',')
@@ -385,8 +379,6 @@
 		# Do nothing.
 	elif prpl == 'bonjour' and not enable_avahi
 		# Do nothing.
-	elif prpl == 'silc' and not silc.found()
-		# Do nothing.
 	elif prpl == 'gg' and not libgadu.found()
 		# Do nothing.
 	elif prpl == 'zephyr' and IS_WIN32
@@ -406,7 +398,6 @@
 DYNAMIC_NOVELL = DYNAMIC_PRPLS.contains('novell')
 DYNAMIC_NULL = DYNAMIC_PRPLS.contains('null')
 DYNAMIC_SAMETIME = DYNAMIC_PRPLS.contains('sametime')
-DYNAMIC_SILC = DYNAMIC_PRPLS.contains('silc')
 DYNAMIC_ZEPHYR = DYNAMIC_PRPLS.contains('zephyr')
 
 conf.set('HAVE_SYS_UTSNAME_H',
--- a/meson_options.txt	Wed Oct 26 01:13:45 2022 -0500
+++ b/meson_options.txt	Wed Oct 26 01:22:53 2022 -0500
@@ -46,9 +46,6 @@
 option('meanwhile', type : 'feature',
        description : 'compile with meanwhile')
 
-option('silc', type : 'feature',
-       description : 'compile with SILC plugin')
-
 option('zephyr', type : 'feature',
        description : 'compile Zephyr plugin against external libzephyr')
 
--- a/pidgin/data/im.pidgin.Pidgin3.desktop.in.in	Wed Oct 26 01:13:45 2022 -0500
+++ b/pidgin/data/im.pidgin.Pidgin3.desktop.in.in	Wed Oct 26 01:22:53 2022 -0500
@@ -4,7 +4,7 @@
 X-GNOME-FullName=Pidgin Internet Messenger
 Comment=Chat over IM.  Supports XMPP, IRC, and more
 # TRANSLATORS: Search terms to find this application. Do NOT translate or localize the semicolons! The list MUST also end with a semicolon!
-Keywords=chat;talk;im;message;bonjour;gadu-gadu;irc;groupwise;jabber;sametime;silc;simple;xmpp;zephyr
+Keywords=chat;talk;im;message;bonjour;gadu-gadu;irc;groupwise;jabber;sametime;simple;xmpp;zephyr
 Exec=pidgin3 %U
 Icon=im.pidgin.Pidgin3
 StartupNotify=true
--- a/po/POTFILES.in	Wed Oct 26 01:13:45 2022 -0500
+++ b/po/POTFILES.in	Wed Oct 26 01:22:53 2022 -0500
@@ -174,14 +174,6 @@
 libpurple/protocols/sametime/im_mime.c
 libpurple/protocols/sametime/sametime.c
 libpurple/protocols/sametime/tests/test_sametime_im_mime.c
-libpurple/protocols/silc/buddy.c
-libpurple/protocols/silc/chat.c
-libpurple/protocols/silc/ft.c
-libpurple/protocols/silc/ops.c
-libpurple/protocols/silc/pk.c
-libpurple/protocols/silc/silc.c
-libpurple/protocols/silc/util.c
-libpurple/protocols/silc/wb.c
 libpurple/protocols/zephyr/ZAsyncLocate.c
 libpurple/protocols/zephyr/ZCkAuth.c
 libpurple/protocols/zephyr/ZCkIfNot.c

mercurial