changeset 25327:0331bc480515

propagate from branch 'im.pidgin.pidgin' (head 8daee71db7028dda036c11e23ca5a60fe834fa95) to branch 'im.pidgin.pidgin.next.minor' (head 8850a92295780ad9e1ccfdb3dc5a59dd078afb4d)
author Richard Laager <rlaager@wiktel.com>
date Sun, 16 Nov 2008 06:57:47 +0000
parents b5385e13e32e (current diff) 0320b4a33432 (diff)
children 5d681e194fb3
files libpurple/account.c libpurple/blist.c libpurple/protocols/gg/gg.c libpurple/protocols/jabber/roster.c libpurple/protocols/msn/msn.c libpurple/protocols/myspace/zap.c libpurple/protocols/oscar/oscar.c libpurple/protocols/qq/buddy_info.c libpurple/protocols/qq/qq.c
diffstat 22 files changed, 155 insertions(+), 216 deletions(-) [+]
line wrap: on
line diff
--- a/finch/libgnt/gntentry.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/finch/libgnt/gntentry.c	Sun Nov 16 06:57:47 2008 +0000
@@ -903,6 +903,7 @@
 				GNT_KEY_CTRL_K, NULL);
 	gnt_bindable_class_register_action(bindable, "delete-prev-word", del_prev_word,
 				GNT_KEY_CTRL_W, NULL);
+	gnt_bindable_register_binding(bindable, "delete-prev-word", "\033", s, NULL);
 	gnt_bindable_class_register_action(bindable, "cursor-prev-word", move_back_word,
 				"\033" "b", NULL);
 	gnt_bindable_class_register_action(bindable, "cursor-prev", move_back,
--- a/libpurple/blist.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/blist.c	Sun Nov 16 06:57:47 2008 +0000
@@ -2271,6 +2271,7 @@
 	struct proto_chat_entry *pce;
 	PurpleBlistNode *node, *group;
 	GList *parts;
+	char *normname;
 
 	g_return_val_if_fail(purplebuddylist != NULL, NULL);
 	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
@@ -2284,6 +2285,7 @@
 	if (prpl_info->find_blist_chat != NULL)
 		return prpl_info->find_blist_chat(account, name);
 
+	normname = g_strdup(purple_normalize(account, name));
 	for (group = purplebuddylist->root; group != NULL; group = group->next) {
 		for (node = group->child; node != NULL; node = node->next) {
 			if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
@@ -2303,14 +2305,15 @@
 				g_list_free(parts);
 
 				if (chat->account == account && chat_name != NULL &&
-					name != NULL && !strcmp(chat_name, name)) {
-
+					normname != NULL && !strcmp(purple_normalize(account, chat_name), normname)) {
+					g_free(normname);
 					return chat;
 				}
 			}
 		}
 	}
 
+	g_free(normname);
 	return NULL;
 }
 
--- a/libpurple/protocols/jabber/message.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/jabber/message.c	Sun Nov 16 06:57:47 2008 +0000
@@ -612,7 +612,7 @@
 
 						if (jid) {
 							chat = jabber_chat_find(js, jid->node, jid->domain);
-							conv = chat->conv;
+							if (chat) conv = chat->conv;
 						}
 
 						jabber_id_free(jid);
@@ -644,7 +644,7 @@
 				/* note: if there were no smileys in the incoming message, or
 				  	if receiving custom smileys is turned off, smiley_refs will
 					be NULL */
-				for (; smiley_refs ; smiley_refs = g_list_delete_link(smiley_refs, smiley_refs)) {
+				for (; conv && smiley_refs ; smiley_refs = g_list_delete_link(smiley_refs, smiley_refs)) {
 					JabberSmileyRef *ref = (JabberSmileyRef *) smiley_refs->data;
 					const gchar *cid = ref->cid;
 					const gchar *alt = ref->alt;
--- a/libpurple/protocols/msn/httpconn.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/msn/httpconn.c	Sun Nov 16 06:57:47 2008 +0000
@@ -119,7 +119,7 @@
 		/* Need to wait for the full HTTP header to arrive */
 		return FALSE;
 
-	s += 4; /* Skip \r\n */
+	s += 4; /* Skip \r\n\r\n */
 	header = g_strndup(buf, s - buf);
 	body_start = s;
 	body_len = size - (body_start - buf);
@@ -162,7 +162,7 @@
 	body[body_len] = '\0';
 
 #ifdef MSN_DEBUG_HTTP
-	purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s\r\n}\n",
+	purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s}\n",
 					header);
 #endif
 
@@ -184,6 +184,7 @@
 			purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n",
 							 buf);
 
+			g_free(header);
 			g_free(body);
 			return FALSE;
 		}
@@ -268,27 +269,26 @@
 {
 	MsnHttpConn *httpconn;
 	MsnServConn *servconn;
-	MsnSession *session;
 	char buf[MSN_BUF_LEN];
-	char *cur, *end, *old_rx_buf;
 	gssize len;
-	int cur_len;
 	char *result_msg = NULL;
 	size_t result_len = 0;
 	gboolean error = FALSE;
 
 	httpconn = data;
-	servconn = NULL;
-	session = httpconn->session;
+	servconn = httpconn->servconn;
+
+	if (servconn->type == MSN_SERVCONN_NS)
+		servconn->session->account->gc->last_received = time(NULL);
 
 	len = read(httpconn->fd, buf, sizeof(buf) - 1);
-
 	if (len < 0 && errno == EAGAIN)
 		return;
-	else if (len <= 0)
-	{
-		purple_debug_error("msn", "HTTP: Read error\n");
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ);
+	if (len <= 0) {
+		purple_debug_error("msn", "HTTP: servconn %03d read error, "
+			"len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
+			servconn->num, len, error, g_strerror(errno));
+		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ);
 
 		return;
 	}
@@ -304,19 +304,15 @@
 	{
 		/* Either we must wait for more input, or something went wrong */
 		if (error)
-			msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ);
+			msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ);
 
 		return;
 	}
 
-	httpconn->servconn->processing = FALSE;
-
-	servconn = httpconn->servconn;
-
 	if (error)
 	{
 		purple_debug_error("msn", "HTTP: Special error\n");
-		msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_READ);
+		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ);
 
 		return;
 	}
@@ -339,64 +335,7 @@
 	servconn->rx_buf = result_msg;
 	servconn->rx_len = result_len;
 
-	end = old_rx_buf = servconn->rx_buf;
-
-	servconn->processing = TRUE;
-
-	do
-	{
-		cur = end;
-
-		if (servconn->payload_len)
-		{
-			if (servconn->payload_len > servconn->rx_len)
-				/* The payload is still not complete. */
-				break;
-
-			cur_len = servconn->payload_len;
-			end += cur_len;
-		}
-		else
-		{
-			end = strstr(cur, "\r\n");
-
-			if (end == NULL)
-				/* The command is still not complete. */
-				break;
-
-			*end = '\0';
-			end += 2;
-			cur_len = end - cur;
-		}
-
-		servconn->rx_len -= cur_len;
-
-		if (servconn->payload_len)
-		{
-			msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len);
-			servconn->payload_len = 0;
-		}
-		else
-		{
-			msn_cmdproc_process_cmd_text(servconn->cmdproc, cur);
-			servconn->payload_len = servconn->cmdproc->last_cmd->payload_len;
-		}
-	} while (servconn->connected && servconn->rx_len > 0);
-
-	if (servconn->connected)
-	{
-		if (servconn->rx_len > 0)
-			servconn->rx_buf = g_memdup(cur, servconn->rx_len);
-		else
-			servconn->rx_buf = NULL;
-	}
-
-	servconn->processing = FALSE;
-
-	if (servconn->wasted)
-		msn_servconn_destroy(servconn);
-
-	g_free(old_rx_buf);
+	msn_servconn_process_data(servconn);
 }
 
 static void
--- a/libpurple/protocols/msn/msn.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/msn/msn.c	Sun Nov 16 06:57:47 2008 +0000
@@ -121,9 +121,6 @@
 	session = gc->proto_data;
 	swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM);
 
-	if (swboard == NULL)
-		return FALSE;
-
 	msn_switchboard_send_msg(swboard, msg, TRUE);
 	msn_message_destroy(msg);
 
@@ -556,21 +553,17 @@
 msn_new_xfer(PurpleConnection *gc, const char *who)
 {
 	MsnSession *session;
-	MsnSlpLink *slplink;
 	PurpleXfer *xfer;
 
 	session = gc->proto_data;
 
 	xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
 
-	if (xfer)
-	{
-		slplink = msn_session_get_slplink(session, who);
-
-		xfer->data = slplink;
-
-		purple_xfer_set_init_fnc(xfer, t_msn_xfer_init);
-	}
+	g_return_val_if_fail(xfer != NULL, NULL);
+
+	xfer->data = msn_session_get_slplink(session, who);
+
+	purple_xfer_set_init_fnc(xfer, t_msn_xfer_init);
 
 	return xfer;
 }
@@ -2569,22 +2562,19 @@
 	PURPLE_PLUGIN_MAGIC,
 	PURPLE_MAJOR_VERSION,
 	PURPLE_MINOR_VERSION,
-	PURPLE_PLUGIN_PROTOCOL,                             /**< type           */
+	PURPLE_PLUGIN_PROTOCOL,                           /**< type           */
 	NULL,                                             /**< ui_requirement */
 	0,                                                /**< flags          */
 	NULL,                                             /**< dependencies   */
-	PURPLE_PRIORITY_DEFAULT,                            /**< priority       */
+	PURPLE_PRIORITY_DEFAULT,                          /**< priority       */
 
 	"prpl-msn",                                       /**< id             */
 	"MSN",                                            /**< name           */
 	DISPLAY_VERSION,                                  /**< version        */
-	                                                  /**  summary        */
-	N_("Windows Live Messenger Protocol Plugin"),
-	                                                  /**  description    */
-	N_("Windows Live Messenger Protocol Plugin"),
-	"Christian Hammond <chipx86@gnupdate.org>, "
-	"MaYuan <mayuan2006@gmail.com>",				  /**< author         */
-	PURPLE_WEBSITE,                                     /**< homepage       */
+	N_("Windows Live Messenger Protocol Plugin"),     /**< summary        */
+	N_("Windows Live Messenger Protocol Plugin"),     /**< description    */
+	NULL,                                             /**< author         */
+	PURPLE_WEBSITE,                                   /**< homepage       */
 
 	msn_load,                                         /**< load           */
 	msn_unload,                                       /**< unload         */
--- a/libpurple/protocols/msn/servconn.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/msn/servconn.c	Sun Nov 16 06:57:47 2008 +0000
@@ -174,15 +174,6 @@
 
 	servconn = data;
 	servconn->connect_data = NULL;
-	servconn->processing = FALSE;
-
-	if (servconn->wasted)
-	{
-		if (source >= 0)
-			close(source);
-		msn_servconn_destroy(servconn);
-		return;
-	}
 
 	servconn->fd = source;
 
@@ -375,24 +366,19 @@
 read_cb(gpointer data, gint source, PurpleInputCondition cond)
 {
 	MsnServConn *servconn;
-	MsnSession *session;
 	char buf[MSN_BUF_LEN];
-	char *cur, *end, *old_rx_buf;
 	gssize len;
-	int cur_len;
 
 	servconn = data;
-	session = servconn->session;
 
-	len = read(servconn->fd, buf, sizeof(buf) - 1);
 	if (servconn->type == MSN_SERVCONN_NS)
 		servconn->session->account->gc->last_received = time(NULL);
 
-	if (len < 0 && errno == EAGAIN) {
+	len = read(servconn->fd, buf, sizeof(buf) - 1);
+	if (len < 0 && errno == EAGAIN)
 		return;
-
-	} else if (len <= 0) {
-		purple_debug_error("msn", "servconn %03d read error,"
+	if (len <= 0) {
+		purple_debug_error("msn", "servconn %03d read error, "
 			"len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
 			servconn->num, len, errno, g_strerror(errno));
 		msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ);
@@ -406,6 +392,14 @@
 	memcpy(servconn->rx_buf + servconn->rx_len, buf, len + 1);
 	servconn->rx_len += len;
 
+	msn_servconn_process_data(servconn);
+}
+
+void msn_servconn_process_data(MsnServConn *servconn)
+{
+	char *cur, *end, *old_rx_buf;
+	int cur_len;
+
 	end = old_rx_buf = servconn->rx_buf;
 
 	servconn->processing = TRUE;
--- a/libpurple/protocols/msn/servconn.h	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/msn/servconn.h	Sun Nov 16 06:57:47 2008 +0000
@@ -170,4 +170,12 @@
  */
 void msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error);
 
+/**
+ * Process the data in servconn->rx_buf.  This is called after reading
+ * data from the socket.
+ *
+ * @param servconn The servconn.
+ */
+void msn_servconn_process_data(MsnServConn *servconn);
+
 #endif /* _MSN_SERVCONN_H_ */
--- a/libpurple/protocols/msn/slp.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/msn/slp.c	Sun Nov 16 06:57:47 2008 +0000
@@ -758,17 +758,17 @@
 
 	if (slplink->swboard == NULL)
 	{
+		/*
+		 * We will need swboard in order to change its flags.  If its
+		 * NULL, something has probably gone wrong earlier on.  I
+		 * didn't want to do this, but MSN 7 is somehow causing us
+		 * to crash here, I couldn't reproduce it to debug more,
+		 * and people are reporting bugs. Hopefully this doesn't
+		 * cause more crashes. Stu.
+		 */
 		if (cmdproc->data == NULL)
 			g_warning("msn_p2p_msg cmdproc->data was NULL\n");
 		else {
-			/*
-			 * We will swboard in order to change its flags.  If its
-			 * NULL, something has probably gone wrong earlier on.  I
-			 * didn't want to do this, but MSN 7 is somehow causing us
-			 * to crash here, I couldn't reproduce it to debug more,
-			 * and people are reporting bugs. Hopefully this doesn't
-			 * cause more crashes. Stu.
-			 */
 			slplink->swboard = (MsnSwitchBoard *)cmdproc->data;
 			slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
 		}
@@ -857,6 +857,7 @@
 				 */
 				slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
 			slplink->swboard = swboard;
+			slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
 		}
 
 		/* If the conversation doesn't exist then this is a custom smiley
--- a/libpurple/protocols/msn/switchboard.h	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/msn/switchboard.h	Sun Nov 16 06:57:47 2008 +0000
@@ -68,9 +68,9 @@
  */
 struct _MsnSwitchBoard
 {
-	MsnSession *session;
-	MsnServConn *servconn;
-	MsnCmdProc *cmdproc;
+	MsnSession *session;   /**< Our parent session. */
+	MsnServConn *servconn; /**< The physical connection for this switchboard. */
+	MsnCmdProc *cmdproc;   /**< Convenience variable for servconn->cmdproc. */
 	char *im_user;
 
 	MsnSBFlag flag;
--- a/libpurple/protocols/oscar/family_auth.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/oscar/family_auth.c	Sun Nov 16 06:57:47 2008 +0000
@@ -32,7 +32,7 @@
 
 #include <ctype.h>
 
-#define USE_XOR_FOR_ICQ
+/* #define USE_XOR_FOR_ICQ */
 
 #ifdef USE_XOR_FOR_ICQ
 /**
--- a/libpurple/protocols/oscar/flap_connection.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/oscar/flap_connection.c	Sun Nov 16 06:57:47 2008 +0000
@@ -228,7 +228,13 @@
 			rateclass->last.tv_usec = now.tv_usec;
 		}
 	} else {
-		purple_debug_warning("oscar", "No rate class found for family %hu subtype %hu\n", family, subtype);
+		/*
+		 * It's normal for SNACs 0x0001/0x0006 and 0x0001/0x0017 to be
+		 * sent before we receive rate info from the server, so don't
+		 * bother warning about them.
+		 */
+		if (family != 0x0001 || (subtype != 0x0006 && subtype != 0x0017))
+			purple_debug_warning("oscar", "No rate class found for family 0x%04hx subtype 0x%04hx\n", family, subtype);
 	}
 
 	if (enqueue)
--- a/libpurple/protocols/oscar/oscar.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Sun Nov 16 06:57:47 2008 +0000
@@ -1147,15 +1147,7 @@
 	conn->watcher_incoming = purple_input_add(conn->fd,
 			PURPLE_INPUT_READ, flap_connection_recv_cb, conn);
 	if (conn->cookie == NULL)
-	{
-		if (!aim_snvalid_icq(purple_account_get_username(account)))
-			/*
-			 * We don't send this when authenticating an ICQ account
-			 * because for some reason ICQ is still using the
-			 * assy/insecure authentication procedure.
-			 */
-			flap_connection_send_version(od, conn);
-	}
+		flap_connection_send_version(od, conn);
 	else
 	{
 		flap_connection_send_version_with_cookie(od, conn,
@@ -4818,7 +4810,7 @@
 		gchar *buf;
 		buf = g_strdup_printf(_("Could not add the buddy %s because the username is invalid.  Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), bname);
 		if (!purple_conv_present_error(bname, account, buf))
-			purple_notify_error(gc, NULL, _("Unable To Add"), buf);
+			purple_notify_error(gc, NULL, _("Unable to Add"), buf);
 		g_free(buf);
 
 		/* Remove from local list */
@@ -4938,7 +4930,7 @@
 	purple_debug_error("oscar", "ssi: SNAC error %hu\n", reason);
 
 	if (reason == 0x0005) {
-		purple_notify_error(gc, NULL, _("Unable To Retrieve Buddy List"),
+		purple_notify_error(gc, NULL, _("Unable to Retrieve Buddy List"),
 						  _("The AIM servers were temporarily unable to send your buddy list.  Your buddy list is not lost, and will probably become available in a few minutes."));
 		if (od->getblisttimer > 0)
 			purple_timeout_remove(od->getblisttimer);
@@ -5300,7 +5292,7 @@
 				gchar *buf;
 				buf = g_strdup_printf(_("Could not add the buddy %s because you have too many buddies in your buddy list.  Please remove one and try again."), (retval->name ? retval->name : _("(no name)")));
 				if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf))
-					purple_notify_error(gc, NULL, _("Unable To Add"), buf);
+					purple_notify_error(gc, NULL, _("Unable to Add"), buf);
 				g_free(buf);
 			}
 
@@ -5315,7 +5307,7 @@
 				buf = g_strdup_printf(_("Could not add the buddy %s for an unknown reason."),
 						(retval->name ? retval->name : _("(no name)")));
 				if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf))
-					purple_notify_error(gc, NULL, _("Unable To Add"), buf);
+					purple_notify_error(gc, NULL, _("Unable to Add"), buf);
 				g_free(buf);
 			} break;
 		}
--- a/libpurple/protocols/qq/buddy_info.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/qq/buddy_info.c	Sun Nov 16 06:57:47 2008 +0000
@@ -418,8 +418,8 @@
 			utf8_title = g_strdup(_("Modify Address"));
 			utf8_prim = g_strdup_printf("%s for %s", _("Modify Address"), segments[0]);
 		case QQ_FIELD_EXT:
-			utf8_title = g_strdup(_("Modify Extend Information"));
-			utf8_prim = g_strdup_printf("%s for %s", _("Modify Extend Information"), segments[0]);
+			utf8_title = g_strdup(_("Modify Extended Information"));
+			utf8_prim = g_strdup_printf("%s for %s", _("Modify Extended Information"), segments[0]);
 			break;
 		case QQ_FIELD_BASE:
 		default:
@@ -457,7 +457,7 @@
 	data[data_len] = '\0';
 	if (qd->uid != atoi((gchar *) data)) {	/* return should be my uid */
 		purple_debug_info("QQ", "Failed Updating info\n");
-		qq_got_attention(gc, _("Failed changing buddy information."));
+		qq_got_attention(gc, _("Could not change buddy information."));
 	}
 }
 
@@ -483,51 +483,27 @@
 
 void qq_change_icon_cb(PurpleConnection *gc, const char *filepath)
 {
-	gchar **segments;
-	const gchar *filename;
-	gint index;
+	gchar *basename;
+	size_t index;
 	gint face;
-	gchar *error;
 
 	g_return_if_fail(filepath != NULL);
 
 	purple_debug_info("QQ", "Change my icon to %s\n", filepath);
-	segments = g_strsplit_set(filepath, G_DIR_SEPARATOR_S, 0);
 
-#if 0
-	for (index = 0; segments[index] != NULL; index++) {
-		purple_debug_info("QQ", "Split to %s\n", segments[index]);
-	}
-#endif
-
-	index = g_strv_length(segments) - 1;
-	if (index < 0) {
-		g_strfreev(segments);
-		return;
-	}
-
-	filename = segments[index];
-	index = strcspn (filename, "0123456789");
-	if (index < 0 || index >= strlen(filename)) {
-		error = g_strdup_printf(_("Can not get face number in file name (%s)"), filename);
-		purple_notify_error(gc, _("QQ Buddy"), _("Failed change icon"), error);
-		g_free(error);
-		return;
-	}
-	face = strtol(filename+index, NULL, 10);
+	basename = g_path_get_basename(filepath);
+	index = strcspn(basename, "0123456789");
+	face = strtol(basename + index, NULL, 10);
+	g_free(basename);
 	purple_debug_info("QQ", "Set face to %d\n", face);
 
 	request_set_buddy_icon(gc, face);
-
-	g_strfreev(segments);
 }
 
 void qq_set_custom_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
 	const gchar *icon_path = purple_account_get_buddy_icon_path(account);
-	gchar **segments;
-	gint index;
 
 	g_return_if_fail(icon_path != NULL);
 
@@ -536,12 +512,6 @@
 	 *  purple_imgstore_get_filename is always new file
 	 *  QQ buddy may set custom icon if level is over 16 */
 	purple_debug_info("QQ", "Change my icon to %s\n", icon_path);
-	segments = g_strsplit_set(icon_path, G_DIR_SEPARATOR_S, 0);
-	for (index = 0; segments[index] != NULL; index++) {
-		purple_debug_info("QQ", "Split to %s\n", segments[index]);
-	}
-
-	g_strfreev(segments);
 }
 
 gchar *qq_get_icon_name(gint face)
--- a/libpurple/protocols/qq/group_join.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/qq/group_join.c	Sun Nov 16 06:57:47 2008 +0000
@@ -219,11 +219,11 @@
 
 	rmd = qq_room_data_find(gc, id);
 	if (rmd != NULL) {
-		msg = g_strdup_printf(_("Successed join to Qun %s (%d)"), rmd->title_utf8, rmd->ext_id);
+		msg = g_strdup_printf(_("Successfully joined Qun %s (%d)"), rmd->title_utf8, rmd->ext_id);
 		qq_got_attention(gc, msg);
 		g_free(msg);
 	} else {
-		qq_got_attention(gc, _("Successed join to Qun"));
+		qq_got_attention(gc, _("Successfully joined Qun"));
 	}
 }
 
--- a/libpurple/protocols/qq/group_opt.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/qq/group_opt.c	Sun Nov 16 06:57:47 2008 +0000
@@ -204,7 +204,7 @@
 
 	purple_debug_info("QQ", "Succeed in modify members for room %d\n", rmd->ext_id);
 
-	qq_room_got_chat_in(gc, id, 0, _("Successed changing Qun member"), now);
+	qq_room_got_chat_in(gc, id, 0, _("Successfully changed Qun member"), now);
 }
 
 void qq_room_change_info(PurpleConnection *gc, qq_room_data *rmd)
@@ -248,7 +248,7 @@
 
 	purple_debug_info("QQ", "Succeed modify room info of %d\n", id);
 
-	qq_room_got_chat_in(gc, id, 0, _("Successed changing Qun information"), now);
+	qq_room_got_chat_in(gc, id, 0, _("Successfully changed Qun information"), now);
 }
 
 /* we create a very simple room first, and then let the user to modify */
@@ -347,7 +347,7 @@
 
 	purple_request_action(gc, _("QQ Qun Operation"),
 			    _("You have successfully created a Qun"),
-			    _("Would you like to set up the detail information now?"),
+			    _("Would you like to set detailed information now?"),
 			    1,
 				purple_connection_get_account(gc), NULL, NULL,
 				add_req, 2,
@@ -520,7 +520,7 @@
 		rmd->my_role = QQ_ROOM_ROLE_YES;
 	}
 
-	msg = g_strdup_printf(_("<b>Joinning Qun %d is approved by Admin %d for %s</b>"),
+	msg = g_strdup_printf(_("<b>Joining Qun %d is approved by admin %d for %s</b>"),
 			ext_id, admin_uid, reason);
 	now = time(NULL);
 	qq_room_got_chat_in(gc, id, 0, msg, now);
--- a/libpurple/protocols/qq/qq.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/qq/qq.c	Sun Nov 16 06:57:47 2008 +0000
@@ -56,9 +56,6 @@
 #include "utils.h"
 #include "version.h"
 
-#define OPENQ_AUTHOR            "Puzzlebird"
-#define OPENQ_WEBSITE           "http://openq.sourceforge.net"
-
 #ifndef OPENQ_VERSION
 #define OPENQ_VERSION           DISPLAY_VERSION
 #endif
@@ -771,7 +768,7 @@
 	g_string_append(info, "</body></html>");
 
 	title = g_strdup_printf(_("About OpenQ r%s"), OPENQ_VERSION);
-	purple_notify_formatted(gc, NULL, title, NULL, info->str, NULL, NULL);
+	purple_notify_formatted(gc, title, title, NULL, info->str, NULL, NULL);
 
 	g_free(title);
 	g_string_free(info, TRUE);
@@ -869,7 +866,7 @@
 	act = purple_plugin_action_new(_("Modify Information"), action_modify_info_base);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Modify Extend Information"), action_modify_info_ext);
+	act = purple_plugin_action_new(_("Modify Extended Information"), action_modify_info_ext);
 	m = g_list_append(m, act);
 
 	act = purple_plugin_action_new(_("Modify Address"), action_modify_info_addr);
@@ -1116,11 +1113,11 @@
 	"QQ",				/**< name		*/
 	DISPLAY_VERSION,		/**< version		*/
 					/**  summary		*/
-	N_("QQ Protocol	Plugin"),
+	N_("QQ Protocol Plugin"),
 					/**  description	*/
-	N_("QQ Protocol	Plugin"),
-	OPENQ_AUTHOR,			/**< author		*/
-	OPENQ_WEBSITE,			/**< homepage		*/
+	N_("QQ Protocol Plugin"),
+	NULL,				/**< author		*/
+	PURPLE_WEBSITE,		/**< homepage	*/
 
 	NULL,				/**< load		*/
 	NULL,				/**< unload		*/
@@ -1152,8 +1149,7 @@
 
 	server_list = server_list_build('A');
 
-	purple_prefs_add_string_list("/plugins/prpl/qq/serverlist", server_list);
-	server_list = purple_prefs_get_string_list("/plugins/prpl/qq/serverlist");
+	purple_prefs_remove("/plugins/prpl/qq/serverlist");
 
 	server_kv_list = NULL;
 	kvp = g_new0(PurpleKeyValuePair, 1);
@@ -1206,10 +1202,10 @@
 	option = purple_account_option_bool_new(_("Show server news"), "show_news", TRUE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
-	option = purple_account_option_int_new(_("Keep alive interval(s)"), "keep_alive_interval", 60);
+	option = purple_account_option_int_new(_("Keep alive interval (seconds)"), "keep_alive_interval", 60);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
-	option = purple_account_option_int_new(_("Update interval(s)"), "update_interval", 300);
+	option = purple_account_option_int_new(_("Update interval (seconds)"), "update_interval", 300);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
 	purple_prefs_add_none("/plugins/prpl/qq");
--- a/libpurple/protocols/qq/qq_base.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/qq/qq_base.c	Sun Nov 16 06:57:47 2008 +0000
@@ -71,7 +71,7 @@
 	if (len < 139) {
 		purple_connection_error_reason(gc,
 				PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
-				_("Can not decrypt get server reply"));
+				_("Can not decrypt server reply"));
 		return QQ_LOGIN_REPLY_ERR;
 	}
 
@@ -404,18 +404,18 @@
 			return process_login_redirect(gc, data, data_len);
 
 		case 0x0A:		/* extend redirect used in QQ2006 */
-			error = g_strdup( _("Not support Redirect_EX now") );
+			error = g_strdup( _("Redirect_EX is not currently supported") );
 			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 			break;
 		case 0x05:		/* invalid password */
 			if (!purple_account_get_remember_password(gc->account)) {
 				purple_account_set_password(gc->account, NULL);
 			}
-			error = g_strdup( _("Error password"));
+			error = g_strdup( _("Incorrect password."));
 			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 			break;
 		case 0x06:		/* need activation */
-			error = g_strdup( _("Need active"));
+			error = g_strdup( _("Activation required"));
 			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 			break;
 
@@ -789,7 +789,7 @@
 	qd->send_seq++;
 	qq_send_cmd_encrypted(gc, QQ_CMD_TOKEN_EX, qd->send_seq, buf, bytes, TRUE);
 
-	purple_connection_update_progress(gc, _("Checking code of  captcha ..."), 3, QQ_CONNECT_STEPS);
+	purple_connection_update_progress(gc, _("Checking code of captcha ..."), 3, QQ_CONNECT_STEPS);
 }
 
 typedef struct {
@@ -873,7 +873,7 @@
 	purple_request_fields(account,
 		_("QQ Captcha Verifing"),
 		_("QQ Captcha Verifing"),
-		_("Please fill code according to image"),
+		_("Enter the text from the image"),
 		fields,
 		_("OK"), G_CALLBACK(captcha_input_ok_cb),
 		_("Cancel"), G_CALLBACK(captcha_input_cancel_cb),
@@ -1094,16 +1094,16 @@
 			if (!purple_account_get_remember_password(gc->account)) {
 				purple_account_set_password(gc->account, NULL);
 			}
-			error = g_strdup(_("Error password"));
+			error = g_strdup(_("Incorrect password."));
 			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 			break;
 		case 0x33:		/* need activation */
 		case 0x51:		/* need activation */
-			error = g_strdup(_("Need active"));
+			error = g_strdup(_("Activation required"));
 			reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
 			break;
 		case 0xBF:		/* uid is not exist */
-			error = g_strdup(_("invalid user name"));
+			error = g_strdup(_("Invalid username."));
 			reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
 			break;
 		default:
--- a/libpurple/protocols/qq/qq_network.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/qq/qq_network.c	Sun Nov 16 06:57:47 2008 +0000
@@ -204,7 +204,7 @@
 		if ( set_new_server(qd) != TRUE) {
 			purple_connection_error_reason(gc,
 					PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
-					_("Failed to connect all servers"));
+					_("Unable to connect."));
 			return FALSE;
 		}
 		qd->connect_retry = QQ_CONNECT_MAX;
--- a/libpurple/protocols/qq/qq_process.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/libpurple/protocols/qq/qq_process.c	Sun Nov 16 06:57:47 2008 +0000
@@ -960,7 +960,7 @@
 				return ret_8;
 			}
 
-			purple_connection_update_progress(gc, _("Logined"), QQ_CONNECT_STEPS - 1, QQ_CONNECT_STEPS);
+			purple_connection_update_progress(gc, _("Logging in"), QQ_CONNECT_STEPS - 1, QQ_CONNECT_STEPS);
 			purple_debug_info("QQ", "Login repliess OK; everything is fine\n");
 			purple_connection_set_state(gc, PURPLE_CONNECTED);
 			qd->is_login = TRUE;	/* must be defined after sev_finish_login */
--- a/pidgin/gtknotify.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/pidgin/gtknotify.c	Sun Nov 16 06:57:47 2008 +0000
@@ -703,7 +703,7 @@
 	gtk_widget_grab_focus(button);
 
 	g_signal_connect_swapped(G_OBJECT(button), "clicked",
-							 G_CALLBACK(gtk_widget_destroy), window);
+							 G_CALLBACK(formatted_close_cb), window);
 	g_signal_connect(G_OBJECT(window), "key_press_event",
 					 G_CALLBACK(formatted_input_cb), NULL);
 
--- a/pidgin/gtksavedstatuses.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/pidgin/gtksavedstatuses.c	Sun Nov 16 06:57:47 2008 +0000
@@ -475,7 +475,8 @@
 static void
 savedstatus_activated_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, StatusWindow *dialog)
 {
-	status_window_modify_cb(NULL, dialog);
+	status_window_use_cb(NULL, dialog);
+	status_window_close_cb(NULL, dialog);
 }
 
 static void
--- a/pidgin/plugins/sendbutton.c	Fri Nov 14 06:52:15 2008 +0000
+++ b/pidgin/plugins/sendbutton.c	Sun Nov 16 06:57:47 2008 +0000
@@ -37,9 +37,26 @@
 }
 
 static void
+input_buffer_changed(GtkTextBuffer *text_buffer, GtkWidget *send_button)
+{
+	if (gtk_text_buffer_get_char_count(text_buffer) != 0)
+		gtk_widget_set_sensitive(send_button, TRUE);
+	else
+		gtk_widget_set_sensitive(send_button, FALSE);
+}
+
+static void
 create_send_button_pidgin(PidginConversation *gtkconv)
 {
 	GtkWidget *send_button;
+	GtkTextBuffer *buf;
+	guint signal_id;
+
+	send_button = g_object_get_data(G_OBJECT(gtkconv->lower_hbox),
+	                                "send_button");
+
+	if (send_button != NULL)
+		return;
 
 	send_button = gtk_button_new_with_mnemonic(_("_Send"));
 	g_signal_connect(G_OBJECT(send_button), "clicked",
@@ -48,6 +65,16 @@
 	                 FALSE, 0);
 	gtk_widget_show(send_button);
 
+	buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
+	if (buf) {
+		signal_id = g_signal_connect(G_OBJECT(buf), "changed",
+		                             G_CALLBACK(input_buffer_changed),
+		                             send_button);
+		g_object_set_data(G_OBJECT(send_button), "buffer-signal",
+		                  GINT_TO_POINTER(signal_id));
+		input_buffer_changed(buf, send_button);
+	}
+ 
 	g_object_set_data(G_OBJECT(gtkconv->lower_hbox), "send_button",
 	                  send_button);
 }
@@ -60,7 +87,18 @@
 	send_button = g_object_get_data(G_OBJECT(gtkconv->lower_hbox),
 	                                "send_button");
 	if (send_button != NULL) {
+		GtkTextBuffer *buf;
+		guint signal_id;
+
+		buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));
+		signal_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(send_button),
+		                                              "buffer-signal"));
+		if (buf && signal_id)
+			g_signal_handler_disconnect(G_OBJECT(buf), signal_id);
+
 		gtk_widget_destroy(send_button);
+		g_object_set_data(G_OBJECT(gtkconv->lower_hbox),
+		                  "send_button", NULL);
 	}
 }