diff -r 76e16990aee5 libpurple/protocols/silc/buddy.c
--- a/libpurple/protocols/silc/buddy.c	Mon May 26 23:00:08 2014 +0200
+++ b/libpurple/protocols/silc/buddy.c	Wed May 28 12:19:44 2014 +0300
@@ -441,7 +441,7 @@
 	SilcDList clients;
 	SilcClientEntry client_entry;
 
-	if (!name)
+	if (!sg->conn || !name)
 		return;
 
 	/* Find client entry */
@@ -572,7 +572,7 @@
 	SilcPurpleBuddyGetkey g;
 	SilcUInt16 cmd_ident;
 
-	if (!name)
+	if (!sg->conn || !name)
 		return;
 
 	/* Find client entry */
@@ -1556,13 +1556,9 @@
 	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);
+	purple_notify_user_info_add_pair_plaintext(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);
+	purple_notify_user_info_add_pair_plaintext(user_info, _("Username"), tmp);
 	if (client_entry->mode) {
 		memset(tmp, 0, sizeof(tmp));
 		silcpurple_get_umode_string(client_entry->mode,
@@ -1573,52 +1569,38 @@
 	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);
+		purple_notify_user_info_add_pair_plaintext(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);
+			purple_notify_user_info_add_pair_plaintext(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);
+			purple_notify_user_info_add_pair_plaintext(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);
+			purple_notify_user_info_add_pair_plaintext(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);
+			purple_notify_user_info_add_pair_plaintext(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);
+			purple_notify_user_info_add_pair_plaintext(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);
+			purple_notify_user_info_add_pair_plaintext(user_info, _("Geolocation"), geostr);
 			g_free(geostr);
 		}
 	}
diff -r 76e16990aee5 libpurple/protocols/silc/ops.c
--- a/libpurple/protocols/silc/ops.c	Mon May 26 23:00:08 2014 +0200
+++ b/libpurple/protocols/silc/ops.c	Wed May 28 12:19:44 2014 +0300
@@ -53,30 +53,67 @@
 {
 	char tmp[256];
 	va_list va;
-	PurpleConnection *gc = NULL;
+	PurpleConnection *gc = client ? client->application : NULL;
 	PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+	PurpleIMConversation *convo = NULL;
+	PurpleChatConversation *chat = NULL;
+	SilcPurple sg = NULL;
 
 	va_start(va, msg);
 	silc_vsnprintf(tmp, sizeof(tmp), msg, va);
 	va_end(va);
 
-	if (type != SILC_CLIENT_MESSAGE_ERROR) {
+	if (type == SILC_CLIENT_MESSAGE_AUDIT) {
 		purple_debug_misc("silc", "silc_say (%d) %s\n", type, tmp);
 		return;
+	} else if (type == SILC_CLIENT_MESSAGE_COMMAND_ERROR) {
+		/* Ignore error messages from commands as they are really
+		   meant for command line clients.  The error is delivered
+		   also to the silc_command_reply() callback which is the
+		   correct place to handle it. */
+		purple_debug_error("silc", "silc_say error: %s\n", tmp);
+		return;
+	} else if (type != SILC_CLIENT_MESSAGE_INFO) {
+		purple_debug_error("silc", "silc_say error: %s\n", tmp);
 	}
 
-	purple_debug_error("silc", "silc_say error: %s\n", tmp);
+#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,11)
+	if (gc && conn) {
+		sg = purple_connection_get_protocol_data(gc);
+		switch (conn->context_type) {
+			case SILC_ID_CLIENT:
+				if (!conn->client_entry->nickname[0])
+					break;
+				convo = purple_conversations_find_im_with_account(
+						conn->client_entry->nickname, sg->account);
+				break;
 
-	if (!strcmp(tmp, "Authentication failed"))
-		reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+			case SILC_ID_CHANNEL:
+				chat = purple_conversations_find_chat_with_account(
+						conn->channel_entry->channel_name, sg->account);
+				break;
+		}
+	}
+#endif /* __SILC_TOOLKIT_VERSION >= 1.1.11 */
 
-	if (client != NULL)
-		gc = client->application;
+	if (convo) {
+		purple_conversation_write_system_message(
+					PURPLE_CONVERSATION(convo), tmp, 0);
+	} else if (chat) {
+		purple_conversation_write_system_message(
+					PURPLE_CONVERSATION(chat), tmp, 0);
+	} else if (type != SILC_CLIENT_MESSAGE_INFO) {
+		if (!strcmp(tmp, "Authentication failed"))
+			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 
-	if (gc != NULL)
-		purple_connection_error(gc, reason, tmp);
-	else
-		purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp, NULL);
+		if (gc != NULL) {
+			purple_connection_error(gc, reason, tmp);
+		} else {
+			purple_notify_error(NULL, _("Error"), _("Error occurred"), tmp, NULL);
+		}
+	} else {
+		purple_notify_info(NULL, _("Info"), _("Information"), tmp, NULL);
+	}
 }
 
 /* Processes incoming MIME message.  Can be private message or channel
@@ -1101,7 +1138,10 @@
 			GList *users = NULL, *flags = NULL;
 			char tmp[256], *topic;
 
-			if (status != SILC_STATUS_OK) {
+			if (status == SILC_STATUS_ERR_USER_ON_CHANNEL) {
+				/* Already joined */
+				return;
+			} else 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));
@@ -1177,7 +1217,7 @@
 			char *moodstr, *statusstr, *contactstr, *langstr, *devicestr, *tzstr, *geostr;
 			PurpleNotifyUserInfo *user_info;
 
-			if (status != SILC_STATUS_OK) {
+			if (SILC_STATUS_IS_ERROR(status)) {
 				purple_notify_error(gc, _("User Information"),
 						_("Cannot get user information"),
 						silc_get_status_message(error),
@@ -1212,16 +1252,12 @@
 				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);
+				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 (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);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Mood"), moodstr);
 				g_free(moodstr);
 			}
 
@@ -1231,44 +1267,32 @@
 			}
 
 			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);
+				purple_notify_user_info_add_pair_plaintext(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);
+				purple_notify_user_info_add_pair_plaintext(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);
+				purple_notify_user_info_add_pair_plaintext(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);
+				purple_notify_user_info_add_pair_plaintext(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);
+				purple_notify_user_info_add_pair_plaintext(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);
+				purple_notify_user_info_add_pair_plaintext(user_info, _("Server"), client_entry->server);
 			}
 
 			if (channels && user_modes) {
diff -r 76e16990aee5 libpurple/protocols/silc/pk.c
--- a/libpurple/protocols/silc/pk.c	Mon May 26 23:00:08 2014 +0200
+++ b/libpurple/protocols/silc/pk.c	Wed May 28 12:19:44 2014 +0300
@@ -211,6 +211,12 @@
 		ipf = filename;
 	}
 
+#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,12)
+	if (!name && conn->context_type == SILC_ID_CLIENT) {
+		name = conn->client_entry->nickname;
+	}
+#endif /* __SILC_TOOLKIT_VERSION >= 1.1.12 */
+
 	verify = silc_calloc(1, sizeof(*verify));
 	if (!verify)
 		return;
diff -r 76e16990aee5 libpurple/protocols/silc/silc.c
--- a/libpurple/protocols/silc/silc.c	Mon May 26 23:00:08 2014 +0200
+++ b/libpurple/protocols/silc/silc.c	Wed May 28 12:19:44 2014 +0300
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2004 - 2007 Pekka Riikonen
+  Copyright (C) 2004 - 2007, 2014 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
@@ -127,8 +127,10 @@
 silcpurple_keepalive(PurpleConnection *gc)
 {
 	SilcPurple sg = purple_connection_get_protocol_data(gc);
-	silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0,
-			 NULL, 0);
+	if (sg->conn) {
+		silc_packet_send(sg->conn->stream, SILC_PACKET_HEARTBEAT, 0,
+				 NULL, 0);
+	}
 }
 
 #if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1)
@@ -565,6 +567,7 @@
 
 	memset(&params, 0, sizeof(params));
 	strcat(params.nickname_format, "%n#a");
+	params.dont_register_crypto_library = TRUE;
 
 	/* Allocate SILC client */
 	client = silc_client_alloc(&ops, &params, gc, NULL);
@@ -659,7 +662,6 @@
 
 	purple_debug_info("silc", "Finalizing SilcPurple %p\n", sg);
 
-	silc_client_stop(sg->client, NULL, NULL);
 	silc_client_free(sg->client);
 	if (sg->sha1hash)
 		silc_hash_free(sg->sha1hash);
@@ -705,9 +707,12 @@
 	if (sg->conn)
 		silc_client_close_connection(sg->client, sg->conn);
 
+	/* Client must be stopped before it is freed and all connections
+	   must be closed for this to succeed immediately. */
+	silc_client_stop(sg->client, NULL, NULL);
+
 #if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
-	if (sg->conn)
-	  silc_client_run_one(sg->client);
+	silc_client_run_one(sg->client);
 	silc_schedule_set_notify(sg->client->schedule, NULL, NULL);
 
 	silc_dlist_start(sg->tasks);
@@ -718,6 +723,8 @@
 	silc_dlist_uninit(sg->tasks);
 #endif /* __SILC_TOOLKIT_VERSION */
 
+	sg->conn = NULL;
+
 	if (sg->scheduler)
 		purple_timeout_remove(sg->scheduler);
 
@@ -1081,7 +1088,7 @@
 	if (!gc)
 		return;
 	sg = purple_connection_get_protocol_data(gc);
-	if (!sg)
+	if (!sg || !sg->conn)
 		return;
 
 	/* Call DETACH */
@@ -2260,6 +2267,11 @@
 	silc_log_set_callback(SILC_LOG_ERROR, silcpurple_log_error, NULL);
 	silcpurple_register_commands();
 
+	silc_cipher_register_default();
+	silc_pkcs_register_default();
+	silc_hash_register_default();
+	silc_hmac_register_default();
+
 #if 0
 silc_log_debug(TRUE);
 silc_log_set_debug_string("*client*");
diff -r 76e16990aee5 libpurple/protocols/silc/silcpurple.h
--- a/libpurple/protocols/silc/silcpurple.h	Mon May 26 23:00:08 2014 +0200
+++ b/libpurple/protocols/silc/silcpurple.h	Wed May 28 12:19:44 2014 +0300
@@ -44,7 +44,7 @@
 
 /* Default settings for creating key pair */
 #define SILCPURPLE_DEF_PKCS "rsa"
-#define SILCPURPLE_DEF_PKCS_LEN 2048
+#define SILCPURPLE_DEF_PKCS_LEN 4096
 
 #define SILCPURPLE_PRVGRP 0x001fffff
 
