diff libpurple/protocols/qq/qq.c @ 25141:5ace6c024230

propagate from branch 'im.pidgin.pidgin' (head 7821a3549d7d99473e999dc067afc4218addcc1e) to branch 'local.struct.hiding' (head 4235f268e41a5ad75efa1010b697599c0c0dd28a)
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Fri, 31 Oct 2008 07:59:46 +0000
parents 16734635febf 7c0a56c5fea0
children e35115192593
line wrap: on
line diff
--- a/libpurple/protocols/qq/qq.c	Sat Oct 04 21:46:10 2008 +0000
+++ b/libpurple/protocols/qq/qq.c	Fri Oct 31 07:59:46 2008 +0000
@@ -29,6 +29,7 @@
 #include "notify.h"
 #include "prefs.h"
 #include "prpl.h"
+#include "privacy.h"
 #include "request.h"
 #include "roomlist.h"
 #include "server.h"
@@ -39,12 +40,12 @@
 #include "buddy_list.h"
 #include "char_conv.h"
 #include "group.h"
-#include "group_find.h"
 #include "group_im.h"
 #include "group_info.h"
 #include "group_join.h"
 #include "group_opt.h"
-#include "header_info.h"
+#include "group_internal.h"
+#include "qq_define.h"
 #include "im.h"
 #include "qq_process.h"
 #include "qq_base.h"
@@ -56,7 +57,11 @@
 #include "version.h"
 
 #define OPENQ_AUTHOR            "Puzzlebird"
-#define OPENQ_WEBSITE            "http://openq.sourceforge.net"
+#define OPENQ_WEBSITE           "http://openq.sourceforge.net"
+
+#ifndef OPENQ_VERSION
+#define OPENQ_VERSION           DISPLAY_VERSION
+#endif
 
 static GList *server_list_build(gchar select)
 {
@@ -128,6 +133,7 @@
 	PurpleConnection *gc;
 	qq_data *qd;
 	PurplePresence *presence;
+	const gchar *version_str;
 
 	g_return_if_fail(account != NULL);
 
@@ -154,6 +160,19 @@
 	server_list_create(account);
 	purple_debug_info("QQ", "Server list has %d\n", g_list_length(qd->servers));
 
+	version_str = purple_account_get_string(account, "client_version", NULL);
+	qd->client_tag = QQ_CLIENT_0D55;	/* set default as QQ2005 */
+	qd->client_version = 2005;
+	if (version_str != NULL && strlen(version_str) != 0) {
+		if (strcmp(version_str, "qq2007") == 0) {
+			qd->client_tag = QQ_CLIENT_111D;
+			qd->client_version = 2007;
+		} else if (strcmp(version_str, "qq2008") == 0) {
+			qd->client_tag = QQ_CLIENT_115B;
+			qd->client_version = 2008;
+		}
+	}
+
 	qd->is_show_notice = purple_account_get_bool(account, "show_notice", TRUE);
 	qd->is_show_news = purple_account_get_bool(account, "show_news", TRUE);
 
@@ -203,6 +222,13 @@
 	}
 
 	qq_disconnect(gc);
+
+	if (qd->redirect) g_free(qd->redirect);
+	if (qd->ld.token) g_free(qd->ld.token);
+	if (qd->ld.token_ex) g_free(qd->ld.token_ex);
+	if (qd->captcha.token) g_free(qd->captcha.token);
+	if (qd->captcha.data) g_free(qd->captcha.data);
+
 	server_list_remove_all(qd);
 
 	g_free(qd);
@@ -210,25 +236,25 @@
 }
 
 /* returns the icon name for a buddy or protocol */
-static const gchar *_qq_list_icon(PurpleAccount *a, PurpleBuddy *b)
+static const gchar *qq_list_icon(PurpleAccount *a, PurpleBuddy *b)
 {
 	return "qq";
 }
 
 
 /* a short status text beside buddy icon*/
-static gchar *_qq_status_text(PurpleBuddy *b)
+static gchar *qq_status_text(PurpleBuddy *b)
 {
-	qq_buddy *q_bud;
+	qq_buddy_data *bd;
 	GString *status;
 
-	q_bud = (qq_buddy *) b->proto_data;
-	if (q_bud == NULL)
+	bd = (qq_buddy_data *) b->proto_data;
+	if (bd == NULL)
 		return NULL;
 
 	status = g_string_new("");
 
-	switch(q_bud->status) {
+	switch(bd->status) {
 	case QQ_BUDDY_OFFLINE:
 		g_string_append(status, _("Offline"));
 		break;
@@ -245,8 +271,11 @@
 	case QQ_BUDDY_ONLINE_INVISIBLE:
 		g_string_append(status, _("Invisible"));
 		break;
+	case QQ_BUDDY_ONLINE_BUSY:
+		g_string_append(status, _("Busy"));
+		break;
 	default:
-		g_string_printf(status, _("Unknown-%d"), q_bud->status);
+		g_string_printf(status, _("Unknown-%d"), bd->status);
 	}
 
 	return g_string_free(status, FALSE);
@@ -254,23 +283,23 @@
 
 
 /* a floating text when mouse is on the icon, show connection status here */
-static void _qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
+static void qq_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
 {
-	qq_buddy *q_bud;
+	qq_buddy_data *bd;
 	gchar *tmp;
 	GString *str;
 
 	g_return_if_fail(b != NULL);
 
-	q_bud = (qq_buddy *) b->proto_data;
-	if (q_bud == NULL)
+	bd = (qq_buddy_data *) b->proto_data;
+	if (bd == NULL)
 		return;
 
-	/* if (PURPLE_BUDDY_IS_ONLINE(b) && q_bud != NULL) */
-	if (q_bud->ip.s_addr != 0) {
+	/* if (PURPLE_BUDDY_IS_ONLINE(b) && bd != NULL) */
+	if (bd->ip.s_addr != 0) {
 		str = g_string_new(NULL);
-		g_string_printf(str, "%s:%d", inet_ntoa(q_bud->ip), q_bud->port);
-		if (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) {
+		g_string_printf(str, "%s:%d", inet_ntoa(bd->ip), bd->port);
+		if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) {
 			g_string_append(str, " TCP");
 		} else {
 			g_string_append(str, " UDP");
@@ -278,11 +307,11 @@
 		g_string_free(str, TRUE);
 	}
 
-	tmp = g_strdup_printf("%d", q_bud->age);
+	tmp = g_strdup_printf("%d", bd->age);
 	purple_notify_user_info_add_pair(user_info, _("Age"), tmp);
 	g_free(tmp);
 
-	switch (q_bud->gender) {
+	switch (bd->gender) {
 	case QQ_BUDDY_GENDER_GG:
 		purple_notify_user_info_add_pair(user_info, _("Gender"), _("Male"));
 		break;
@@ -293,38 +322,38 @@
 		purple_notify_user_info_add_pair(user_info, _("Gender"), _("Unknown"));
 		break;
 	default:
-		tmp = g_strdup_printf("Error (%d)", q_bud->gender);
+		tmp = g_strdup_printf("Error (%d)", bd->gender);
 		purple_notify_user_info_add_pair(user_info, _("Gender"), tmp);
 		g_free(tmp);
 	}
 
-	if (q_bud->level) {
-		tmp = g_strdup_printf("%d", q_bud->level);
+	if (bd->level) {
+		tmp = g_strdup_printf("%d", bd->level);
 		purple_notify_user_info_add_pair(user_info, _("Level"), tmp);
 		g_free(tmp);
 	}
 
 	str = g_string_new(NULL);
-	if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) {
+	if (bd->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) {
 		g_string_append( str, _("Member") );
 	}
-	if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_VIP) {
+	if (bd->comm_flag & QQ_COMM_FLAG_QQ_VIP) {
 		g_string_append( str, _(" VIP") );
 	}
-	if (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) {
+	if (bd->comm_flag & QQ_COMM_FLAG_TCP_MODE) {
 		g_string_append( str, _(" TCP") );
 	}
-	if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE) {
+	if (bd->comm_flag & QQ_COMM_FLAG_MOBILE) {
 		g_string_append( str, _(" FromMobile") );
 	}
-	if (q_bud->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) {
+	if (bd->comm_flag & QQ_COMM_FLAG_BIND_MOBILE) {
 		g_string_append( str, _(" BindMobile") );
 	}
-	if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) {
+	if (bd->comm_flag & QQ_COMM_FLAG_VIDEO) {
 		g_string_append( str, _(" Video") );
 	}
 
-	if (q_bud->ext_flag & QQ_EXT_FLAG_ZONE) {
+	if (bd->ext_flag & QQ_EXT_FLAG_ZONE) {
 		g_string_append( str, _(" Zone") );
 	}
 	purple_notify_user_info_add_pair(user_info, _("Flag"), str->str);
@@ -333,40 +362,47 @@
 
 #ifdef DEBUG
 	tmp = g_strdup_printf( "%s (%04X)",
-										qq_get_ver_desc(q_bud->client_version),
-										q_bud->client_version );
+										qq_get_ver_desc(bd->client_tag),
+										bd->client_tag );
 	purple_notify_user_info_add_pair(user_info, _("Ver"), tmp);
 	g_free(tmp);
 
 	tmp = g_strdup_printf( "Ext 0x%X, Comm 0x%X",
-												q_bud->ext_flag, q_bud->comm_flag );
+												bd->ext_flag, bd->comm_flag );
 	purple_notify_user_info_add_pair(user_info, _("Flag"), tmp);
 	g_free(tmp);
 #endif
 }
 
 /* we can show tiny icons on the four corners of buddy icon, */
-static const char *_qq_list_emblem(PurpleBuddy *b)
+static const char *qq_list_emblem(PurpleBuddy *b)
 {
-	/* each char** are refering to a filename in pixmaps/purple/status/default/ */
-	qq_buddy *q_bud;
+	PurpleAccount *account;
+	PurpleConnection *gc;
+	qq_data *qd;
+	qq_buddy_data *buddy;
 
-	if (!b || !(q_bud = b->proto_data)) {
+	if (!b || !(account = b->account) ||
+		!(gc = purple_account_get_connection(account)) || !(qd = gc->proto_data))
 		return NULL;
+
+	buddy = (qq_buddy_data *)b->proto_data;
+	if (!buddy) {
+		return "not-authorized";
 	}
 
-	if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE)
+	if (buddy->comm_flag & QQ_COMM_FLAG_MOBILE)
 		return "mobile";
-	if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO)
+	if (buddy->comm_flag & QQ_COMM_FLAG_VIDEO)
 		return "video";
-	if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_MEMBER)
+	if (buddy->comm_flag & QQ_COMM_FLAG_QQ_MEMBER)
 		return "qq_member";
 
 	return NULL;
 }
 
 /* QQ away status (used to initiate QQ away packet) */
-static GList *_qq_away_states(PurpleAccount *ga)
+static GList *qq_status_types(PurpleAccount *ga)
 {
 	PurpleStatusType *status;
 	GList *types = NULL;
@@ -383,6 +419,10 @@
 			"invisible", _("Invisible"), FALSE, TRUE, FALSE);
 	types = g_list_append(types, status);
 
+	status = purple_status_type_new_full(PURPLE_STATUS_UNAVAILABLE,
+			"busy", _("Busy"), TRUE, TRUE, FALSE);
+	types = g_list_append(types, status);
+
 	status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
 			"offline", _("Offline"), FALSE, TRUE, FALSE);
 	types = g_list_append(types, status);
@@ -395,18 +435,72 @@
 }
 
 /* initiate QQ away with proper change_status packet */
-static void _qq_change_status(PurpleAccount *account, PurpleStatus *status)
+static void qq_change_status(PurpleAccount *account, PurpleStatus *status)
 {
 	PurpleConnection *gc = purple_account_get_connection(account);
 
 	qq_request_change_status(gc, 0);
 }
 
+static void qq_add_deny(PurpleConnection *gc, const char *who)
+{
+	qq_data *qd;
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+
+	qd = (qq_data *) gc->proto_data;
+	if (!qd->is_login)
+		return;
+
+	if (!who || who[0] == '\0')
+		return;
+
+	purple_debug_info("QQ", "Add deny for %s\n", who);
+}
+
+static void qq_rem_deny(PurpleConnection *gc, const char *who)
+{
+	qq_data *qd;
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+
+	qd = (qq_data *) gc->proto_data;
+	if (!qd->is_login)
+		return;
+
+	if (!who || who[0] == '\0')
+		return;
+
+	purple_debug_info("QQ", "Rem deny for %s\n", who);
+}
+
+static void qq_set_permit_deny(PurpleConnection *gc)
+{
+	PurpleAccount *account;
+	GSList *deny;
+
+	purple_debug_info("QQ", "Set permit deny\n");
+	account = purple_connection_get_account(gc);
+	switch (account->perm_deny)
+	{
+		case PURPLE_PRIVACY_ALLOW_ALL:
+			for (deny = account->deny; deny; deny = deny->next)
+				qq_rem_deny(gc, deny->data);
+			break;
+
+		case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
+		case PURPLE_PRIVACY_ALLOW_USERS:
+		case PURPLE_PRIVACY_DENY_USERS:
+		case PURPLE_PRIVACY_DENY_ALL:
+			for (deny = account->deny; deny; deny = deny->next)
+				qq_add_deny(gc, deny->data);
+			break;
+	}
+}
+
 /* IMPORTANT: PurpleConvImFlags -> PurpleMessageFlags */
 /* send an instant msg to a buddy */
-static gint _qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags)
+static gint qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *message, PurpleMessageFlags flags)
 {
-	gint type, to_uid;
+	gint type, uid_to;
 	gchar *msg, *msg_with_qq_smiley;
 	qq_data *qd;
 
@@ -417,15 +511,15 @@
 	g_return_val_if_fail(strlen(message) <= QQ_MSG_IM_MAX, -E2BIG);
 
 	type = (flags == PURPLE_MESSAGE_AUTO_RESP ? QQ_IM_AUTO_REPLY : QQ_IM_TEXT);
-	to_uid = purple_name_to_uid(who);
+	uid_to = purple_name_to_uid(who);
 
 	/* if msg is to myself, bypass the network */
-	if (to_uid == qd->uid) {
+	if (uid_to == qd->uid) {
 		serv_got_im(gc, who, message, flags, time(NULL));
 	} else {
 		msg = utf8_to_qq(message, QQ_CHARSET_DEFAULT);
 		msg_with_qq_smiley = purple_smiley_to_qq(msg);
-		qq_send_packet_im(gc, to_uid, msg_with_qq_smiley, type);
+		qq_request_send_im(gc, uid_to, msg_with_qq_smiley, type);
 		g_free(msg);
 		g_free(msg_with_qq_smiley);
 	}
@@ -434,21 +528,18 @@
 }
 
 /* send a chat msg to a QQ Qun */
-static int _qq_chat_send(PurpleConnection *gc, int channel, const char *message, PurpleMessageFlags flags)
+static int qq_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
 {
 	gchar *msg, *msg_with_qq_smiley;
-	qq_group *group;
+	guint32 room_id = id;
 
 	g_return_val_if_fail(message != NULL, -1);
 	g_return_val_if_fail(strlen(message) <= QQ_MSG_IM_MAX, -E2BIG);
 
-	group = qq_group_find_by_channel(gc, channel);
-	g_return_val_if_fail(group != NULL, -1);
-
 	purple_debug_info("QQ_MESG", "Send qun mesg in utf8: %s\n", message);
 	msg = utf8_to_qq(message, QQ_CHARSET_DEFAULT);
 	msg_with_qq_smiley = purple_smiley_to_qq(msg);
-	qq_send_packet_group_im(gc, group, msg_with_qq_smiley);
+	qq_request_room_send_im(gc, room_id, msg_with_qq_smiley);
 	g_free(msg);
 	g_free(msg_with_qq_smiley);
 
@@ -456,7 +547,7 @@
 }
 
 /* send packet to get who's detailed information */
-static void _qq_get_info(PurpleConnection *gc, const gchar *who)
+static void qq_show_buddy_info(PurpleConnection *gc, const gchar *who)
 {
 	guint32 uid;
 	qq_data *qd;
@@ -470,78 +561,135 @@
 		return;
 	}
 
-	qq_request_get_level(gc, uid);
-	qq_send_packet_get_info(gc, uid, TRUE);
+	if (qd->client_version >= 2007) {
+		qq_request_get_level_2007(gc, uid);
+	} else {
+		qq_request_get_level(gc, uid);
+	}
+	qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY);
+}
+
+static void action_update_all_rooms(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	qq_data *qd;
+
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+	qd = (qq_data *) gc->proto_data;
+
+	if ( !qd->is_login ) {
+		return;
+	}
+
+	qq_update_all_rooms(gc, 0, 0);
 }
 
-/* get my own information */
-static void _qq_menu_modify_my_info(PurplePluginAction *action)
+static void action_change_icon(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	qq_data *qd;
+	gchar *icon_name;
+	gchar *icon_path;
+
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+	qd = (qq_data *) gc->proto_data;
+
+	if ( !qd->is_login ) {
+		return;
+	}
+
+	icon_name = qq_get_icon_name(qd->my_icon);
+	icon_path = qq_get_icon_path(icon_name);
+	g_free(icon_name);
+
+	purple_debug_info("QQ", "Change prev icon %s to ...\n", icon_path);
+	purple_request_file(action, _("Select icon..."), icon_path,
+			FALSE,
+			G_CALLBACK(qq_change_icon_cb), NULL,
+			purple_connection_get_account(gc), NULL, NULL,
+			gc);
+	g_free(icon_path);
+}
+
+static void action_modify_info_base(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	qq_data *qd;
+
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+	qd = (qq_data *) gc->proto_data;
+	qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_BASE);
+}
+
+static void action_modify_info_ext(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *) action->context;
 	qq_data *qd;
 
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
 	qd = (qq_data *) gc->proto_data;
-	qq_prepare_modify_info(gc);
+	qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_EXT);
+}
+
+static void action_modify_info_addr(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	qq_data *qd;
+
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+	qd = (qq_data *) gc->proto_data;
+	qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_ADDR);
 }
 
-static void _qq_menu_change_password(PurplePluginAction *action)
+static void action_modify_info_contact(PurplePluginAction *action)
 {
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	qq_data *qd;
+
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+	qd = (qq_data *) gc->proto_data;
+	qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_CONTACT);
+}
+
+static void action_change_password(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
 	purple_notify_uri(NULL, "https://password.qq.com");
 }
 
-/* remove a buddy from my list and remove myself from his list */
-/* TODO: re-enable this
-static void _qq_menu_block_buddy(PurpleBlistNode * node)
-{
-	guint32 uid;
-	gc_and_uid *g;
-	PurpleBuddy *buddy;
-	PurpleConnection *gc;
-	const gchar *who;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
-
-	buddy = (PurpleBuddy *) node;
-	gc = purple_account_get_connection(buddy->account);
-	who = buddy->name;
-	g_return_if_fail(who != NULL);
-
-	uid = purple_name_to_uid(who);
-	g_return_if_fail(uid > 0);
-
-	g = g_new0(gc_and_uid, 1);
-	g->gc = gc;
-	g->uid = uid;
-
-	purple_request_action(gc, _("Block Buddy"),
-			    _("Are you sure you want to block this buddy?"), NULL,
-			    1, g, 2,
-			    _("Cancel"),
-			    G_CALLBACK(qq_do_nothing_with_gc_and_uid),
-			    _("Block"), G_CALLBACK(qq_block_buddy_with_gc_and_uid));
-}
-*/
-
 /* show a brief summary of what we get from login packet */
-static void _qq_menu_account_info(PurplePluginAction *action)
+static void action_show_account_info(PurplePluginAction *action)
 {
 	PurpleConnection *gc = (PurpleConnection *) action->context;
 	qq_data *qd;
 	GString *info;
+	struct tm *tm_local;
+	int index;
 
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
 	qd = (qq_data *) gc->proto_data;
-	info = g_string_new("<html><body>\n");
+	info = g_string_new("<html><body>");
 
-	g_string_append_printf(info, _("<b>Current Online</b>: %d<br>\n"), qd->total_online);
-	g_string_append_printf(info, _("<b>Last Refresh</b>: %s<br>\n"), ctime(&qd->last_get_online));
+	tm_local = localtime(&qd->login_time);
+	g_string_append_printf(info, _("<b>Login time</b>: %d-%d-%d, %d:%d:%d<br>\n"),
+			(1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday,
+			tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec);
+	g_string_append_printf(info, _("<b>Total Online Buddies</b>: %d<br>\n"), qd->online_total);
+	tm_local = localtime(&qd->online_last_update);
+	g_string_append_printf(info, _("<b>Last Refresh</b>: %d-%d-%d, %d:%d:%d<br>\n"),
+			(1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday,
+			tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec);
 
-	g_string_append(info, "<hr>\n");
+	g_string_append(info, "<hr>");
 
 	g_string_append_printf(info, _("<b>Server</b>: %s<br>\n"), qd->curr_server);
+	g_string_append_printf(info, _("<b>Client Tag</b>: %s<br>\n"), qq_get_ver_desc(qd->client_tag));
 	g_string_append_printf(info, _("<b>Connection Mode</b>: %s<br>\n"), qd->use_tcp ? "TCP" : "UDP");
-	g_string_append_printf(info, _("<b>My Internet Address</b>: %s<br>\n"), inet_ntoa(qd->my_ip));
+	g_string_append_printf(info, _("<b>My Internet IP</b>: %s:%d<br>\n"), inet_ntoa(qd->my_ip), qd->my_port);
 
-	g_string_append(info, "<hr>\n");
+	g_string_append(info, "<hr>");
 	g_string_append(info, "<i>Network Status</i><br>\n");
 	g_string_append_printf(info, _("<b>Sent</b>: %lu<br>\n"), qd->net_stat.sent);
 	g_string_append_printf(info, _("<b>Resend</b>: %lu<br>\n"), qd->net_stat.resend);
@@ -549,12 +697,18 @@
 	g_string_append_printf(info, _("<b>Received</b>: %lu<br>\n"), qd->net_stat.rcved);
 	g_string_append_printf(info, _("<b>Received Duplicate</b>: %lu<br>\n"), qd->net_stat.rcved_dup);
 
-	g_string_append(info, "<hr>\n");
-	g_string_append(info, "<i>Information below may not be accurate</i><br>\n");
+	g_string_append(info, "<hr>");
+	g_string_append(info, "<i>Last Login Information</i><br>\n");
 
-	g_string_append_printf(info, _("<b>Login Time</b>: %s<br>\n"), ctime(&qd->login_time));
-	g_string_append_printf(info, _("<b>Last Login IP</b>: %s<br>\n"), qd->last_login_ip);
-	g_string_append_printf(info, _("<b>Last Login Time</b>: %s\n"), ctime(&qd->last_login_time));
+	for (index = 0; index < sizeof(qd->last_login_time) / sizeof(time_t); index++) {
+		tm_local = localtime(&qd->last_login_time[index]);
+		g_string_append_printf(info, _("<b>Time</b>: %d-%d-%d, %d:%d:%d<br>\n"),
+				(1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday,
+				tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec);
+	}
+	if (qd->last_login_ip.s_addr != 0) {
+		g_string_append_printf(info, _("<b>IP</b>: %s<br>\n"), inet_ntoa(qd->last_login_ip));
+	}
 
 	g_string_append(info, "</body></html>");
 
@@ -563,6 +717,65 @@
 	g_string_free(info, TRUE);
 }
 
+static void action_about_openq(PurplePluginAction *action)
+{
+	PurpleConnection *gc = (PurpleConnection *) action->context;
+	qq_data *qd;
+	GString *info;
+	gchar *title;
+
+	g_return_if_fail(NULL != gc && NULL != gc->proto_data);
+	qd = (qq_data *) gc->proto_data;
+
+	info = g_string_new("<html><body>");
+	g_string_append(info, _("<p><b>Original Author</b>:<br>\n"));
+	g_string_append(info, "puzzlebird<br>\n");
+	g_string_append(info, "<br>\n");
+	g_string_append(info, _("<p><b>Code Contributors</b>:<br>\n"));
+	g_string_append(info, "gfhuang : patches for libpurple 2.0.0beta2, maintainer<br>\n");
+	g_string_append(info, "Yuan Qingyun : patches for libpurple 1.5.0, maintainer<br>\n");
+	g_string_append(info, "henryouly : file transfer, udp sock5 proxy and qq_show, maintainer<br>\n");
+	g_string_append(info, "hzhr : maintainer<br>\n");
+	g_string_append(info, "joymarquis : maintainer<br>\n");
+	g_string_append(info, "arfankai : fixed bugs in char_conv.c<br>\n");
+	g_string_append(info, "rakescar : provided filter for HTML tag<br>\n");
+	g_string_append(info, "yyw : improved performance on PPC linux<br>\n");
+	g_string_append(info, "lvxiang : provided ip to location original code<br>\n");
+	g_string_append(info, "markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007<br>\n");
+	g_string_append(info, "ccpaging : maintainer since 2007<br>\n");
+	g_string_append(info, "icesky : maintainer since 2007<br>\n");
+	g_string_append(info, "csyfek : faces, maintainer since 2007<br>\n");
+	g_string_append(info, "<br>\n");
+	g_string_append(info, _("<p><b>Lovely Patch Writers</b>:<br>\n"));
+	g_string_append(info, "gnap : message displaying, documentation<br>\n");
+	g_string_append(info, "manphiz : qun processing<br>\n");
+	g_string_append(info, "moo : qun processing<br>\n");
+	g_string_append(info, "Coly Li : qun processing<br>\n");
+	g_string_append(info, "Emil Alexiev : captcha verification on login based on LumaQQ for MAC (2007), login, add buddy, remove buddy, message exchange and logout<br>\n");
+	g_string_append(info, "<br>\n");
+	g_string_append(info, _("<p><b>Acknowledgement</b>:<br>\n"));
+	g_string_append(info, "Shufeng Tan : http://sf.net/projects/perl-oicq<br>\n");
+	g_string_append(info, "Jeff Ye : http://www.sinomac.com<br>\n");
+	g_string_append(info, "Hu Zheng : http://forlinux.yeah.net<br>\n");
+	g_string_append(info, "yunfan : http://www.myswear.net<br>\n");
+	g_string_append(info, "OpenQ Team : http://openq.linuxsir.org<br>\n");
+	g_string_append(info, "LumaQQ Team : http://lumaqq.linuxsir.org<br>\n");
+	g_string_append(info, "khc(at)pidgin.im<br>\n");
+	g_string_append(info, "qulogic(at)pidgin.im<br>\n");
+	g_string_append(info, "rlaager(at)pidgin.im<br>\n");
+	g_string_append(info, "OpenQ Google Group : http://groups.google.com/group/openq<br>\n");
+	g_string_append(info, "<br>\n");
+	g_string_append(info, _("<p><i>And, all the boys in the backroom...</i><br>\n"));
+	g_string_append(info, _("<i>Feel free to join us!</i> :)"));
+	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);
+
+	g_free(title);
+	g_string_free(info, TRUE);
+}
+
 /*
 static void _qq_menu_search_or_add_permanent_group(PurplePluginAction *action)
 {
@@ -578,38 +791,48 @@
 			   _("Input Qun name here"),
 			   _("Only QQ members can create permanent Qun"),
 			   "OpenQ", FALSE, FALSE, NULL,
-			   _("Create"), G_CALLBACK(qq_room_create_new), _("Cancel"), NULL, gc);
+			   _("Create"), G_CALLBACK(qq_create_room), _("Cancel"), NULL, gc);
 }
 */
 
-static void _qq_menu_unsubscribe_group(PurpleBlistNode * node)
-{
-	PurpleChat *chat = (PurpleChat *)node;
-	PurpleConnection *gc;
-	GHashTable *components;
-
-	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
-
-	gc = purple_account_get_connection(purple_chat_get_account(chat));
-	components = purple_chat_get_components(chat);
-
-	g_return_if_fail(components != NULL);
-	qq_group_exit(gc, components);
-}
-
-/*
-static void _qq_menu_manage_group(PurpleBlistNode * node)
+static void action_chat_quit(PurpleBlistNode * node)
 {
 	PurpleChat *chat = (PurpleChat *)node;
 	PurpleConnection *gc = purple_account_get_connection(chat->account);
 	GHashTable *components = chat -> components;
+	gchar *num_str;
+	guint32 room_id;
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
 
 	g_return_if_fail(components != NULL);
-	qq_group_manage_group(gc, components);
+
+	num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID);
+	room_id = strtol(num_str, NULL, 10);
+	g_return_if_fail(room_id != 0);
+
+	qq_room_quit(gc, room_id);
 }
-*/
+
+static void action_chat_get_info(PurpleBlistNode * node)
+{
+	PurpleChat *chat = (PurpleChat *)node;
+	PurpleConnection *gc = purple_account_get_connection(chat->account);
+	GHashTable *components = chat -> components;
+	gchar *num_str;
+	guint32 room_id;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
+	g_return_if_fail(components != NULL);
+
+	num_str = g_hash_table_lookup(components, QQ_ROOM_KEY_INTERNAL_ID);
+	room_id = strtol(num_str, NULL, 10);
+	g_return_if_fail(room_id != 0);
+
+	qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, room_id, NULL, 0,
+			0, QQ_ROOM_INFO_DISPLAY);
+}
 
 #if 0
 /* TODO: re-enable this */
@@ -617,12 +840,12 @@
 {
 	PurpleBuddy *buddy;
 	PurpleConnection *gc;
-	qq_buddy *q_bud;
+	qq_buddy_data *bd;
 
 	g_return_if_fail (PURPLE_BLIST_NODE_IS_BUDDY (node));
 	buddy = (PurpleBuddy *) node;
-	q_bud = (qq_buddy *) buddy->proto_data;
-/*	if (is_online (q_bud->status)) { */
+	bd = (qq_buddy_data *) buddy->proto_data;
+/*	if (is_online (bd->status)) { */
 	gc = purple_account_get_connection (buddy->account);
 	g_return_if_fail (gc != NULL && gc->proto_data != NULL);
 	qq_send_file(gc, buddy->name, NULL);
@@ -631,21 +854,38 @@
 #endif
 
 /* protocol related menus */
-static GList *_qq_actions(PurplePlugin *plugin, gpointer context)
+static GList *qq_actions(PurplePlugin *plugin, gpointer context)
 {
 	GList *m;
 	PurplePluginAction *act;
 
 	m = NULL;
-	act = purple_plugin_action_new(_("Set My Information"), _qq_menu_modify_my_info);
+	act = purple_plugin_action_new(_("Change Icon"), action_change_icon);
+	m = g_list_append(m, act);
+
+	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);
+	m = g_list_append(m, act);
+
+	act = purple_plugin_action_new(_("Modify Address"), action_modify_info_addr);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Change Password"), _qq_menu_change_password);
+	act = purple_plugin_action_new(_("Modify Contact"), action_modify_info_contact);
+	m = g_list_append(m, act);
+
+	act = purple_plugin_action_new(_("Change Password"), action_change_password);
 	m = g_list_append(m, act);
 
-	act = purple_plugin_action_new(_("Account Information"), _qq_menu_account_info);
+	act = purple_plugin_action_new(_("Account Information"), action_show_account_info);
 	m = g_list_append(m, act);
 
+	act = purple_plugin_action_new(_("Update all QQ Quns"), action_update_all_rooms);
+	m = g_list_append(m, act);
+
+	act = purple_plugin_action_new(_("About OpenQ"), action_about_openq);
+	m = g_list_append(m, act);
 	/*
 	act = purple_plugin_action_new(_("Qun: Search a permanent Qun"), _qq_menu_search_or_add_permanent_group);
 	m = g_list_append(m, act);
@@ -657,63 +897,131 @@
 	return m;
 }
 
+static void qq_add_buddy_from_menu_cb(PurpleBlistNode *node, gpointer data)
+{
+	PurpleBuddy *buddy;
+	PurpleConnection *gc;
+
+	g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+
+	buddy = (PurpleBuddy *) node;
+	gc = purple_account_get_connection(buddy->account);
+
+	qq_add_buddy(gc, buddy, NULL);
+}
+
+static GList *qq_buddy_menu(PurpleBuddy *buddy)
+{
+	GList *m = NULL;
+	PurpleMenuAction *act;
+	/*
+	PurpleConnection *gc = purple_account_get_connection(buddy->account);
+	qq_data *qd = gc->proto_data;
+	*/
+	qq_buddy_data *bd = (qq_buddy_data *)buddy->proto_data;
+
+	if (bd == NULL) {
+		act = purple_menu_action_new(_("Add Buddy"),
+		                           PURPLE_CALLBACK(qq_add_buddy_from_menu_cb),
+		                           NULL, NULL);
+		m = g_list_append(m, act);
+
+		return m;
+
+	}
+
+/* TODO : not working, temp commented out by gfhuang */
+#if 0
+	if (bd && is_online(bd->status)) {
+		act = purple_menu_action_new(_("Send File"), PURPLE_CALLBACK(_qq_menu_send_file), NULL, NULL); /* add NULL by gfhuang */
+		m = g_list_append(m, act);
+	}
+#endif
+	return m;
+}
+
 /* chat-related (QQ Qun) menu shown up with right-click */
-static GList *_qq_chat_menu(PurpleBlistNode *node)
+static GList *qq_chat_menu(PurpleBlistNode *node)
 {
 	GList *m;
 	PurpleMenuAction *act;
 
 	m = NULL;
-	act = purple_menu_action_new(_("Leave the QQ Qun"), PURPLE_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL);
+	act = purple_menu_action_new(_("Get Info"), PURPLE_CALLBACK(action_chat_get_info), NULL, NULL);
 	m = g_list_append(m, act);
 
-	/* TODO: enable this
-	act = purple_menu_action_new(_("Show Details"), PURPLE_CALLBACK(_qq_menu_manage_group), NULL, NULL);
+	act = purple_menu_action_new(_("Quit Qun"), PURPLE_CALLBACK(action_chat_quit), NULL, NULL);
 	m = g_list_append(m, act);
-	*/
-
 	return m;
 }
 
 /* buddy-related menu shown up with right-click */
-static GList *_qq_buddy_menu(PurpleBlistNode * node)
+static GList *qq_blist_node_menu(PurpleBlistNode * node)
 {
-	GList *m;
+	if(PURPLE_BLIST_NODE_IS_CHAT(node))
+		return qq_chat_menu(node);
 
-	if(PURPLE_BLIST_NODE_IS_CHAT(node))
-		return _qq_chat_menu(node);
+	if(PURPLE_BLIST_NODE_IS_BUDDY(node))
+		return qq_buddy_menu((PurpleBuddy *) node);
 
-	m = NULL;
+	return NULL;
+}
 
-/* TODO : not working, temp commented out by gfhuang */
-#if 0
+/* convert name displayed in a chat channel to original QQ UID */
+static gchar *chat_name_to_purple_name(const gchar *const name)
+{
+	const char *start;
+	const char *end;
+	gchar *ret;
+
+	g_return_val_if_fail(name != NULL, NULL);
 
-	act = purple_menu_action_new(_("Block this buddy"), PURPLE_CALLBACK(_qq_menu_block_buddy), NULL, NULL); /* add NULL by gfhuang */
-	m = g_list_append(m, act);
-/*	if (q_bud && is_online(q_bud->status)) { */
-		act = purple_menu_action_new(_("Send File"), PURPLE_CALLBACK(_qq_menu_send_file), NULL, NULL); /* add NULL by gfhuang */
-		m = g_list_append(m, act);
-/*	} */
-#endif
+	/* Sample: (1234567)*/
+	start = strchr(name, '(');
+	g_return_val_if_fail(start != NULL, NULL);
+	end = strchr(start, ')');
+	g_return_val_if_fail(end != NULL && (end - start) > 1, NULL);
 
-	return m;
+	ret = g_strndup(start + 1, end - start - 1);
+
+	return ret;
 }
 
-/* convert chat nickname to qq-uid to get this buddy info */
+/* convert chat nickname to uid to get this buddy info */
 /* who is the nickname of buddy in QQ chat-room (Qun) */
-static void _qq_get_chat_buddy_info(PurpleConnection *gc, gint channel, const gchar *who)
+static void qq_get_chat_buddy_info(PurpleConnection *gc, gint channel, const gchar *who)
 {
-	gchar *purple_name;
+	qq_data *qd;
+	gchar *uid_str;
+	guint32 uid;
+
+	purple_debug_info("QQ", "Get chat buddy info of %s\n", who);
 	g_return_if_fail(who != NULL);
 
-	purple_name = chat_name_to_purple_name(who);
-	if (purple_name != NULL)
-		_qq_get_info(gc, purple_name);
+	uid_str = chat_name_to_purple_name(who);
+	if (uid_str == NULL) {
+		return;
+	}
+
+	qd = gc->proto_data;
+	uid = purple_name_to_uid(uid_str);
+	g_free(uid_str);
+
+	if (uid <= 0) {
+		purple_debug_error("QQ", "Not valid chat name: %s\n", who);
+		purple_notify_error(gc, NULL, _("Invalid name"), NULL);
+		return;
+	}
+
+	if (qd->client_version < 2007) {
+		qq_request_get_level(gc, uid);
+	}
+	qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY);
 }
 
-/* convert chat nickname to qq-uid to invite individual IM to buddy */
+/* convert chat nickname to uid to invite individual IM to buddy */
 /* who is the nickname of buddy in QQ chat-room (Qun) */
-static gchar *_qq_get_chat_buddy_real_name(PurpleConnection *gc, gint channel, const gchar *who)
+static gchar *qq_get_chat_buddy_real_name(PurpleConnection *gc, gint channel, const gchar *who)
 {
 	g_return_val_if_fail(who != NULL, NULL);
 	return chat_name_to_purple_name(who);
@@ -725,21 +1033,21 @@
 	NULL,							/* user_splits	*/
 	NULL,							/* protocol_options */
 	{"png", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */
-	_qq_list_icon,						/* list_icon */
-	_qq_list_emblem,					/* list_emblems */
-	_qq_status_text,					/* status_text	*/
-	_qq_tooltip_text,					/* tooltip_text */
-	_qq_away_states,					/* away_states	*/
-	_qq_buddy_menu,						/* blist_node_menu */
+	qq_list_icon,						/* list_icon */
+	qq_list_emblem,					/* list_emblems */
+	qq_status_text,					/* status_text	*/
+	qq_tooltip_text,					/* tooltip_text */
+	qq_status_types,					/* away_states	*/
+	qq_blist_node_menu,			/* blist_node_menu */
 	qq_chat_info,						/* chat_info */
 	qq_chat_info_defaults,					/* chat_info_defaults */
 	qq_login,							/* open */
 	qq_close,						/* close */
-	_qq_send_im,						/* send_im */
+	qq_send_im,						/* send_im */
 	NULL,							/* set_info */
 	NULL,							/* send_typing	*/
-	_qq_get_info,						/* get_info */
-	_qq_change_status,						/* change status */
+	qq_show_buddy_info,						/* get_info */
+	qq_change_status,						/* change status */
 	NULL,							/* set_idle */
 	NULL,							/* change_passwd */
 	qq_add_buddy,						/* add_buddy */
@@ -747,30 +1055,30 @@
 	qq_remove_buddy,					/* remove_buddy */
 	NULL,							/* remove_buddies */
 	NULL,							/* add_permit */
-	NULL,							/* add_deny */
+	qq_add_deny,							/* add_deny */
 	NULL,							/* rem_permit */
 	NULL,							/* rem_deny */
-	NULL,							/* set_permit_deny */
+	qq_set_permit_deny,			/* set_permit_deny */
 	qq_group_join,						/* join_chat */
 	NULL,							/* reject chat	invite */
 	NULL,							/* get_chat_name */
 	NULL,							/* chat_invite	*/
 	NULL,							/* chat_leave */
 	NULL,							/* chat_whisper */
-	_qq_chat_send,			/* chat_send */
+	qq_chat_send,			/* chat_send */
 	NULL,							/* keepalive */
 	NULL,							/* register_user */
-	_qq_get_chat_buddy_info,				/* get_cb_info	*/
+	qq_get_chat_buddy_info,				/* get_cb_info	*/
 	NULL,							/* get_cb_away	*/
 	NULL,							/* alias_buddy	*/
-	NULL,							/* group_buddy	*/
+	NULL,							/* change buddy's group	*/
 	NULL,							/* rename_group */
 	NULL,							/* buddy_free */
 	NULL,							/* convo_closed */
 	NULL,							/* normalize */
-	qq_set_my_buddy_icon,					/* set_buddy_icon */
+	qq_set_custom_icon,
 	NULL,							/* remove_group */
-	_qq_get_chat_buddy_real_name,				/* get_cb_real_name */
+	qq_get_chat_buddy_real_name,				/* get_cb_real_name */
 	NULL,							/* set_chat_topic */
 	NULL,							/* find_blist_chat */
 	qq_roomlist_get_list,					/* roomlist_get_list */
@@ -818,7 +1126,7 @@
 	NULL,				/**< ui_info		*/
 	&prpl_info,			/**< extra_info		*/
 	NULL,				/**< prefs_info		*/
-	_qq_actions,
+	qq_actions,
 
 	/* padding */
 	NULL,
@@ -832,35 +1140,60 @@
 {
 	PurpleAccountOption *option;
 	PurpleKeyValuePair *kvp;
-	GList *list = NULL;
-	GList *kvlist = NULL;
-	GList *entry;
+	GList *server_list = NULL;
+	GList *server_kv_list = NULL;
+	GList *it;
+//#ifdef DEBUG
+	GList *version_kv_list = NULL;
+//#endif
 
-	list = server_list_build('A');
+	server_list = server_list_build('A');
 
-	purple_prefs_add_string_list("/plugins/prpl/qq/serverlist", list);
-	list = purple_prefs_get_string_list("/plugins/prpl/qq/serverlist");
+	purple_prefs_add_string_list("/plugins/prpl/qq/serverlist", server_list);
+	server_list = purple_prefs_get_string_list("/plugins/prpl/qq/serverlist");
 
-	kvlist = NULL;
+	server_kv_list = NULL;
 	kvp = g_new0(PurpleKeyValuePair, 1);
 	kvp->key = g_strdup(_("Auto"));
 	kvp->value = g_strdup("auto");
-	kvlist = g_list_append(kvlist, kvp);
+	server_kv_list = g_list_append(server_kv_list, kvp);
 
-	entry = list;
-	while(entry) {
-		if (entry->data != NULL && strlen(entry->data) > 0) {
+	it = server_list;
+	while(it) {
+		if (it->data != NULL && strlen(it->data) > 0) {
 			kvp = g_new0(PurpleKeyValuePair, 1);
-			kvp->key = g_strdup(entry->data);
-			kvp->value = g_strdup(entry->data);
-			kvlist = g_list_append(kvlist, kvp);
+			kvp->key = g_strdup(it->data);
+			kvp->value = g_strdup(it->data);
+			server_kv_list = g_list_append(server_kv_list, kvp);
 		}
-		entry = entry->next;
+		it = it->next;
 	}
 
-	option = purple_account_option_list_new(_("Server"), "server", kvlist);
+	g_list_free(server_list);
+
+	option = purple_account_option_list_new(_("Select Server"), "server", server_kv_list);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
+//#ifdef DEBUG
+	kvp = g_new0(PurpleKeyValuePair, 1);
+	kvp->key = g_strdup(_("QQ2005"));
+	kvp->value = g_strdup("qq2005");
+	version_kv_list = g_list_append(version_kv_list, kvp);
+
+	kvp = g_new0(PurpleKeyValuePair, 1);
+	kvp->key = g_strdup(_("QQ2007"));
+	kvp->value = g_strdup("qq2007");
+	version_kv_list = g_list_append(version_kv_list, kvp);
+
+	kvp = g_new0(PurpleKeyValuePair, 1);
+	kvp->key = g_strdup(_("QQ2008"));
+	kvp->value = g_strdup("qq2008");
+	version_kv_list = g_list_append(version_kv_list, kvp);
+
+	option = purple_account_option_list_new(_("Client Version"), "client_version", version_kv_list);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+//#endif
+
 	option = purple_account_option_bool_new(_("Connect by TCP"), "use_tcp", TRUE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
@@ -879,9 +1212,10 @@
 	purple_prefs_add_none("/plugins/prpl/qq");
 	purple_prefs_add_bool("/plugins/prpl/qq/show_status_by_icon", TRUE);
 	purple_prefs_add_bool("/plugins/prpl/qq/show_fake_video", FALSE);
-	purple_prefs_add_bool("/plugins/prpl/qq/show_room_when_newin", TRUE);
+	purple_prefs_add_bool("/plugins/prpl/qq/auto_popup_conversation", FALSE);
+	purple_prefs_add_bool("/plugins/prpl/qq/auto_get_authorize_info", TRUE);
 	purple_prefs_add_int("/plugins/prpl/qq/resend_interval", 3);
-	purple_prefs_add_int("/plugins/prpl/qq/resend_times", 4);
+	purple_prefs_add_int("/plugins/prpl/qq/resend_times", 10);
 }
 
 PURPLE_INIT_PLUGIN(qq, init_plugin, info);