Index: src/protocols/silc/buddy.c
===================================================================
RCS file: /cvsroot/gaim/gaim/src/protocols/silc/buddy.c,v
retrieving revision 1.8
diff -u -p -r1.8 buddy.c
--- src/protocols/silc/buddy.c	30 May 2004 20:53:02 -0000	1.8
+++ src/protocols/silc/buddy.c	5 Jun 2004 14:18:11 -0000
@@ -1471,23 +1471,23 @@ char *silcgaim_tooltip_text(GaimBuddy *b
 	  return NULL;
 
 	if (client_entry->nickname)
-	  g_string_append_printf(s, "%s: %s\n", _("Nickname"),
+	  g_string_append_printf(s, "\n%s: %s", _("Nickname"),
 				 client_entry->nickname);
 	if (client_entry->username && client_entry->hostname)
-	  g_string_append_printf(s, "%s: %s@%s\n", _("Username"),
+	  g_string_append_printf(s, "\n%s: %s@%s", _("Username"),
 				 client_entry->username, client_entry->hostname);
 	if (client_entry->mode) {
-	  g_string_append_printf(s, "%s: ", _("Modes"));
+	  g_string_append_printf(s, "\n%s: ", _("Modes"));
 	  memset(tmp, 0, sizeof(tmp));
 	  silcgaim_get_umode_string(client_entry->mode,
 				    tmp, sizeof(tmp) - strlen(tmp));
-	  g_string_append_printf(s, "%s\n", tmp);
+	  g_string_append_printf(s, "%s", tmp);
 	}
 
 	attr = silcgaim_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_MOOD);
 	if (attr && silc_attribute_get_object(attr, &mood, sizeof(mood))) {
 		if (mood)
-			g_string_append_printf(s, "%s: ", _("Mood"));
+			g_string_append_printf(s, "\n%s: ", _("Mood"));
 		if (mood & SILC_ATTRIBUTE_MOOD_HAPPY)
 			g_string_append_printf(s, "[%s] ", _("Happy"));
 		if (mood & SILC_ATTRIBUTE_MOOD_SAD)
@@ -1510,19 +1510,17 @@ char *silcgaim_tooltip_text(GaimBuddy *b
 			g_string_append_printf(s, "[%s] ", _("Excited"));
 		if (mood & SILC_ATTRIBUTE_MOOD_ANXIOUS)
 			g_string_append_printf(s, "[%s] ", _("Anxious"));
-		if (mood)
-			g_string_append_printf(s, "\n");
 	}
 
 	attr = silcgaim_get_attr(client_entry->attrs, SILC_ATTRIBUTE_STATUS_FREETEXT);
 	memset(tmp, 0, sizeof(tmp));
 	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		g_string_append_printf(s, "%s: %s\n", _("Status Text"), tmp);
+		g_string_append_printf(s, "\n%s: %s", _("Status Text"), tmp);
 
 	attr = silcgaim_get_attr(client_entry->attrs, SILC_ATTRIBUTE_PREFERRED_CONTACT);
 	if (attr && silc_attribute_get_object(attr, &contact, sizeof(contact))) {
 		if (contact)
-			g_string_append_printf(s, "%s: ", _("Preferred Contact"));
+			g_string_append_printf(s, "\n%s: ", _("Preferred Contact"));
 		if (contact & SILC_ATTRIBUTE_CONTACT_CHAT)
 			g_string_append_printf(s, "[%s] ", _("Chat"));
 		if (contact & SILC_ATTRIBUTE_CONTACT_EMAIL)
@@ -1537,18 +1535,17 @@ char *silcgaim_tooltip_text(GaimBuddy *b
 			g_string_append_printf(s, "[%s] ", _("MMS"));
 		if (contact & SILC_ATTRIBUTE_CONTACT_VIDEO)
 			g_string_append_printf(s, "[%s] ", _("Video Conferencing"));
-		g_string_append_printf(s, "\n");
 	}
 
 	attr = silcgaim_get_attr(client_entry->attrs, SILC_ATTRIBUTE_PREFERRED_LANGUAGE);
 	memset(tmp, 0, sizeof(tmp));
 	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		g_string_append_printf(s, "%s: %s\n", _("Preferred Language"), tmp);
+		g_string_append_printf(s, "\n%s: %s", _("Preferred Language"), tmp);
 
 	attr = silcgaim_get_attr(client_entry->attrs, SILC_ATTRIBUTE_DEVICE_INFO);
 	memset(&device, 0, sizeof(device));
 	if (attr && silc_attribute_get_object(attr, &device, sizeof(device))) {
-		g_string_append_printf(s, "%s: ", _("Device"));
+		g_string_append_printf(s, "\n%s: ", _("Device"));
 		if (device.type == SILC_ATTRIBUTE_DEVICE_COMPUTER)
 		    g_string_append_printf(s, "%s: ", _("Computer"));
 		if (device.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE)
@@ -1557,7 +1554,7 @@ char *silcgaim_tooltip_text(GaimBuddy *b
 		    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\n",
+		g_string_append_printf(s, "%s %s %s %s",
 				       device.manufacturer ? device.manufacturer : "",
 				       device.version ? device.version : "",
 				       device.model ? device.model : "",
@@ -1567,12 +1564,12 @@ char *silcgaim_tooltip_text(GaimBuddy *b
 	attr = silcgaim_get_attr(client_entry->attrs, SILC_ATTRIBUTE_TIMEZONE);
 	memset(tmp, 0, sizeof(tmp));
 	if (attr && silc_attribute_get_object(attr, tmp, sizeof(tmp)))
-		g_string_append_printf(s, "%s: %s\n", _("Timezone"), tmp);
+		g_string_append_printf(s, "\n%s: %s", _("Timezone"), tmp);
 
 	attr = silcgaim_get_attr(client_entry->attrs, SILC_ATTRIBUTE_GEOLOCATION);
 	memset(&geo, 0, sizeof(geo));
 	if (attr && silc_attribute_get_object(attr, &geo, sizeof(geo)))
-		g_string_append_printf(s, "%s: %s %s %s (%s)\n",
+		g_string_append_printf(s, "\n%s: %s %s %s (%s)",
 				       _("Geolocation"),
 				       geo.longitude ? geo.longitude : "",
 				       geo.latitude ? geo.latitude : "",
Index: src/protocols/silc/ops.c
===================================================================
RCS file: /cvsroot/gaim/gaim/src/protocols/silc/ops.c,v
retrieving revision 1.5
diff -u -p -r1.5 ops.c
--- src/protocols/silc/ops.c	23 May 2004 20:06:10 -0000	1.5
+++ src/protocols/silc/ops.c	5 Jun 2004 14:18:11 -0000
@@ -653,7 +653,7 @@ silc_notify(SilcClient client, SilcClien
 				/* Find buddy by nickname */
 				b = gaim_find_buddy(sg->account, client_entry->nickname);
 				if (!b) {
-					fprintf(stderr, "WATCH for %s, unknown buddy",
+					gaim_debug_warning("silc", "WATCH for %s, unknown buddy",
 						client_entry->nickname);
 					break;
 				}
Index: src/protocols/silc/silc.c
===================================================================
RCS file: /cvsroot/gaim/gaim/src/protocols/silc/silc.c,v
retrieving revision 1.10
diff -u -p -r1.10 silc.c
--- src/protocols/silc/silc.c	23 May 2004 20:06:10 -0000	1.10
+++ src/protocols/silc/silc.c	5 Jun 2004 14:18:11 -0000
@@ -278,8 +278,8 @@ silcgaim_login(GaimAccount *account)
 	/* Load SILC key pair */
 	if (!silc_load_key_pair(gaim_prefs_get_string("/plugins/prpl/silc/pubkey"),
 				gaim_prefs_get_string("/plugins/prpl/silc/privkey"),
-				"", &client->pkcs, &client->public_key,
-				&client->private_key)) {
+				(account->password == NULL) ? "" : account->password, &client->pkcs,
+				&client->public_key, &client->private_key)) {
 		gaim_connection_error(gc, ("Could not load SILC key pair"));
 		return;
 	}
@@ -318,21 +318,21 @@ silcgaim_close_final(gpointer *context)
 }
 
 static void
-silcgaim_close_convos(GaimConversation *convo)
-{
-	if (convo)
-		gaim_conversation_destroy(convo);
-}
-
-static void
 silcgaim_close(GaimConnection *gc)
 {
+	GList *l;
+	GaimConversation *conv;
 	SilcGaim sg = gc->proto_data;
 	if (!sg)
 		return;
 
-	/* Close all conversations */
-	gaim_conversation_foreach(silcgaim_close_convos);
+	/* Close all conversations for this connection */
+	for (l = gaim_get_conversations(); l; l = l->next)
+	{
+		conv = l->data;
+		if (gc == conv->account->gc)
+			gaim_conversation_destroy(conv);
+	}
 
 	/* Send QUIT */
 	silc_client_command_call(sg->client, sg->conn, NULL,
@@ -729,6 +729,31 @@ silcgaim_view_motd(GaimPluginAction *act
 			      sg->motd, NULL, NULL);
 }
 
+static void
+silcgaim_change_pass(GaimPluginAction *action)
+{
+	GaimConnection *gc = (GaimConnection *) action->context;
+	gaim_account_request_change_password(gaim_connection_get_account(gc));
+}
+
+static void
+silcgaim_change_passwd(GaimConnection *gc, const char *old, const char *new)
+{
+	silc_change_private_key_passphrase(gaim_prefs_get_string("/plugins/prpl/silc/privkey"), old, new);
+}
+
+static void
+silcgaim_show_set_info(GaimPluginAction *action)
+{
+	GaimConnection *gc = (GaimConnection *) action->context;
+	gaim_account_request_change_user_info(gaim_connection_get_account(gc));
+}
+
+static void
+silcgaim_set_info(GaimConnection *gc, const char *text)
+{
+}
+
 static GList *
 silcgaim_actions(GaimPlugin *plugin, gpointer context)
 {
@@ -750,6 +775,14 @@ silcgaim_actions(GaimPlugin *plugin, gpo
 			silcgaim_view_motd);
 	list = g_list_append(list, act);
 
+	act = gaim_plugin_action_new(_("Change Password..."),
+			silcgaim_change_pass);
+	list = g_list_append(list, act);
+
+	act = gaim_plugin_action_new(_("Set User Info..."),
+			silcgaim_show_set_info);
+	list = g_list_append(list, act);
+
 	return list;
 }
 
@@ -893,9 +926,87 @@ GList *silcgaim_blist_node_menu(GaimBlis
 	}	
 }
 
+/********************************* Commands **********************************/
+
+static GaimCmdRet silcgaim_cmd_chat_part(GaimConversation *conv,
+		const char *cmd, char **args, char **error)
+{
+	GaimConnection *gc;
+	int id = 0;
+
+	gc = gaim_conversation_get_gc(conv);
+	id = gaim_conv_chat_get_id(GAIM_CONV_CHAT(conv));
+
+	if (gc == NULL || id == 0)
+		return GAIM_CMD_RET_FAILED;
+
+	silcgaim_chat_leave(gc, id);
+
+	return GAIM_CMD_RET_OK;
+
+}
+
+static GaimCmdRet silcgaim_cmd_chat_topic(GaimConversation *conv,
+		const char *cmd, char **args, char **error)
+{
+	GaimConnection *gc;
+	int id = 0;
+
+	gc = gaim_conversation_get_gc(conv);
+	id = gaim_conv_chat_get_id(GAIM_CONV_CHAT(conv));
+
+	if (gc == NULL || id == 0)
+		return GAIM_CMD_RET_FAILED;
+
+	silcgaim_chat_set_topic(gc, id, args ? args[0] : NULL);
+
+	return GAIM_CMD_RET_OK;
+}
+
+static GaimCmdRet silcgaim_cmd_chat_join(GaimConversation *conv,
+        const char *cmd, char **args, char **error)
+{
+	GHashTable *comp;
+
+	if(!args || !args[0])
+		return GAIM_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]);
+
+	silcgaim_chat_join(gaim_conversation_get_gc(conv), comp);
+
+	g_hash_table_destroy(comp);
+	return GAIM_CMD_RET_OK;
+}
+
+
 
 /************************** Plugin Initialization ****************************/
 
+static void
+silcgaim_register_commands(void)
+{
+	gaim_cmd_register("part", "", GAIM_CMD_P_PRPL,
+			GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcgaim_cmd_chat_part, _("Leave the chat"));
+	gaim_cmd_register("leave", "", GAIM_CMD_P_PRPL,
+			GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY,
+			"prpl-silc", silcgaim_cmd_chat_part, _("Leave the chat"));
+	gaim_cmd_register("topic", "s", GAIM_CMD_P_PRPL,
+			GAIM_CMD_FLAG_CHAT | GAIM_CMD_FLAG_PRPL_ONLY |
+			GAIM_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-silc",
+			silcgaim_cmd_chat_topic, _("View or change the topic"));
+	gaim_cmd_register("join", "ws", GAIM_CMD_P_PRPL,
+			GAIM_CMD_FLAG_IM | GAIM_CMD_FLAG_CHAT |
+			GAIM_CMD_FLAG_PRPL_ONLY | GAIM_CMD_FLAG_ALLOW_WRONG_ARGS,
+			"prpl-silc", silcgaim_cmd_chat_join,
+			_("Join a chat on this network"));
+}
+
 static GaimPluginPrefFrame *
 silcgaim_pref_frame(GaimPlugin *plugin)
 {
@@ -968,12 +1079,12 @@ static GaimPluginProtocolInfo prpl_info 
 	silcgaim_login,
 	silcgaim_close,
 	silcgaim_send_im,
-	NULL,
+	silcgaim_set_info,
 	NULL,
 	silcgaim_get_info,
 	silcgaim_set_away,
 	silcgaim_idle_set,
-	NULL,
+	silcgaim_change_passwd,
 	silcgaim_add_buddy,
 	silcgaim_add_buddies,
 	silcgaim_remove_buddy,
@@ -1094,6 +1205,8 @@ init_plugin(GaimPlugin *plugin)
 	g_snprintf(tmp, sizeof(tmp), "%s/private_key.prv", silcgaim_silcdir());
 	gaim_prefs_add_string("/plugins/prpl/silc/privkey", tmp);
 	gaim_prefs_add_string("/plugins/prpl/silc/vcard", "");
+
+	silcgaim_register_commands();
 }
 
 GAIM_INIT_PLUGIN(silc, init_plugin, info);
Index: src/protocols/silc/silcgaim.h
===================================================================
RCS file: /cvsroot/gaim/gaim/src/protocols/silc/silcgaim.h,v
retrieving revision 1.2
diff -u -p -r1.2 silcgaim.h
--- src/protocols/silc/silcgaim.h	23 May 2004 19:40:55 -0000	1.2
+++ src/protocols/silc/silcgaim.h	5 Jun 2004 14:18:11 -0000
@@ -33,6 +33,7 @@
 #include "util.h"
 #include "roomlist.h"
 #include "ft.h"
+#include "cmds.h"
 
 /* Default public and private key file names */
 #define SILCGAIM_PUBLIC_KEY_NAME "public_key.pub"
Index: src/protocols/silc/util.c
===================================================================
RCS file: /cvsroot/gaim/gaim/src/protocols/silc/util.c,v
retrieving revision 1.3
diff -u -p -r1.3 util.c
--- src/protocols/silc/util.c	23 May 2004 20:06:10 -0000	1.3
+++ src/protocols/silc/util.c	5 Jun 2004 14:18:11 -0000
@@ -76,7 +76,7 @@ gboolean silcgaim_check_silc_dir(GaimCon
 
 	pw = getpwuid(getuid());
 	if (!pw) {
-		fprintf(stderr, "silc: %s\n", strerror(errno));
+		gaim_debug_error("silc", "silc: %s\n", strerror(errno));
 		return FALSE;
 	}
 
@@ -96,22 +96,22 @@ gboolean silcgaim_check_silc_dir(GaimCon
 		if (errno == ENOENT) {
 			if (pw->pw_uid == geteuid()) {
 				if ((mkdir(filename, 0755)) == -1) {
-					fprintf(stderr, "Couldn't create `%s' directory\n", filename);
+					gaim_debug_error("silc", "Couldn't create '%s' directory\n", filename);
 					return FALSE;
 				}
 			} else {
-				fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
+				gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
 					filename);
 				return FALSE;
 			}
 		} else {
-			fprintf(stderr, "%s\n", strerror(errno));
+			gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n", filename, strerror(errno));
 			return FALSE;
 		}
 	} else {
 		/* Check the owner of the dir */
 		if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-			fprintf(stderr, "You don't seem to own `%s' directory\n",
+			gaim_debug_error("silc", "You don't seem to own '%s' directory\n",
 				filename);
 			return FALSE;
 		}
@@ -125,16 +125,17 @@ gboolean silcgaim_check_silc_dir(GaimCon
 		if (errno == ENOENT) {
 			if (pw->pw_uid == geteuid()) {
 				if ((mkdir(servfilename, 0755)) == -1) {
-					fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
+					gaim_debug_error("silc", "Couldn't create '%s' directory\n", servfilename);
 					return FALSE;
 				}
 			} else {
-				fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
+				gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
 					servfilename);
 				return FALSE;
 			}
 		} else {
-			fprintf(stderr, "%s\n", strerror(errno));
+			gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+							 servfilename, strerror(errno));
 			return FALSE;
 		}
 	}
@@ -147,16 +148,17 @@ gboolean silcgaim_check_silc_dir(GaimCon
 		if (errno == ENOENT) {
 			if (pw->pw_uid == geteuid()) {
 				if ((mkdir(clientfilename, 0755)) == -1) {
-					fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
+					gaim_debug_error("silc", "Couldn't create '%s' directory\n", clientfilename);
 					return FALSE;
 				}
 			} else {
-				fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
+				gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
 					clientfilename);
 				return FALSE;
 			}
 		} else {
-			fprintf(stderr, "%s\n", strerror(errno));
+			gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+							 clientfilename, strerror(errno));
 			return FALSE;
 		}
 	}
@@ -169,16 +171,17 @@ gboolean silcgaim_check_silc_dir(GaimCon
 		if (errno == ENOENT) {
 			if (pw->pw_uid == geteuid()) {
 				if ((mkdir(friendsfilename, 0755)) == -1) {
-					fprintf(stderr, "Couldn't create `%s' directory\n", friendsfilename);
+					gaim_debug_error("silc", "Couldn't create '%s' directory\n", friendsfilename);
 					return FALSE;
 				}
 			} else {
-				fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
+				gaim_debug_error("silc", "Couldn't create '%s' directory due to a wrong uid!\n",
 					friendsfilename);
 				return FALSE;
 			}
 		} else {
-			fprintf(stderr, "%s\n", strerror(errno));
+			gaim_debug_error("silc", "Couldn't stat '%s' directory, error: %s\n",
+							 friendsfilename, strerror(errno));
 			return FALSE;
 		}
 	}
@@ -198,16 +201,19 @@ gboolean silcgaim_check_silc_dir(GaimCon
 			silc_create_key_pair(SILCGAIM_DEF_PKCS,
 					     SILCGAIM_DEF_PKCS_LEN,
 					     file_public_key, file_private_key, NULL,
-					     "", NULL, NULL, NULL, FALSE);
+					     (gc->account->password == NULL) ? "" : gc->account->password,
+						 NULL, NULL, NULL, FALSE);
+			stat(file_public_key, &st);
 		} else {
-			fprintf(stderr, "%s\n", strerror(errno));
+			gaim_debug_error("silc", "Couldn't stat '%s' public key, error: %s\n",
+							 file_public_key, strerror(errno));
 			return FALSE;
 		}
 	}
 
 	/* Check the owner of the public key */
 	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-		fprintf(stderr, "You don't seem to own your public key!?\n");
+		gaim_debug_error("silc", "You don't seem to own your public key!?\n");
 		return FALSE;
 	}
 
@@ -218,30 +224,33 @@ gboolean silcgaim_check_silc_dir(GaimCon
 			silc_create_key_pair(SILCGAIM_DEF_PKCS,
 					     SILCGAIM_DEF_PKCS_LEN,
 					     file_public_key, file_private_key, NULL,
-					     "", NULL, NULL, NULL, FALSE);
+					     (gc->account->password == NULL) ? "" : gc->account->password,
+						 NULL, NULL, NULL, FALSE);
+			stat(file_private_key, &st);
 		} else {
-			fprintf(stderr, "%s\n", strerror(errno));
+			gaim_debug_error("silc", "Couldn't stat '%s' private key, error: %s\n",
+							 file_private_key, strerror(errno));
 			return FALSE;
 		}
 	}
 
 	/* Check the owner of the private key */
 	if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
-		fprintf(stderr, "You don't seem to own your private key!?\n");
+		gaim_debug_error("silc", "You don't seem to own your private key!?\n");
 		return FALSE;
 	}
 
 	/* Check the permissions for the private key */
 	if ((st.st_mode & 0777) != 0600) {
-		fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
+		gaim_debug_warning("silc", "Wrong permissions in your private key file `%s'!\n"
 			"Trying to change them ... ", file_private_key);
 		if ((chmod(file_private_key, 0600)) == -1) {
-			fprintf(stderr,
+			gaim_debug_error("silc",
 				"Failed to change permissions for private key file!\n"
 				"Permissions for your private key file must be 0600.\n");
 			return FALSE;
 		}
-		fprintf(stderr, "Done.\n\n");
+		gaim_debug_warning("silc", "Done.\n\n");
 	}
 
 	return TRUE;