# HG changeset patch # User SHiNE CsyFeK # Date 1224686926 0 # Node ID a95c7e71064c68b7072fad04796e33cdf5141152 # Parent c2253c485728ed6369d921009ba2bc90c15fc5ac 2008.10.05 - ccpaging * Add my uid into buddy list * Fixed a minor bug in qq_create_buddy. Not get new buddy's info. * There are 38 fields in protocol 2008, one more than 2005/2007. * The packet of Modifing buddy info is changed. Need sample to fix it. diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/ChangeLog --- a/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:48:46 2008 +0000 @@ -1,3 +1,9 @@ +2008.10.05 - ccpaging + * Add my uid into buddy list + * Fixed a minor bug in qq_create_buddy. Not get new buddy's info. + * There are 38 fields in protocol 2008, one more than 2005/2007. + * The packet of Modifing buddy info is changed. Need sample to fix it. + 2008.10.04 - ccpaging * Update protocol for 2007 * Code cleanup diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/buddy_info.c --- a/libpurple/protocols/qq/buddy_info.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/buddy_info.c Wed Oct 22 14:48:46 2008 +0000 @@ -85,7 +85,7 @@ QQ_INFO_UNKNOW3, QQ_INFO_UNKNOW4, QQ_INFO_UNKNOW5, QQ_INFO_IS_PUB_MOBILE, QQ_INFO_IS_PUB_CONTACT, QQ_INFO_COLLEGE, QQ_INFO_HOROSCOPE, QQ_INFO_ZODIAC, QQ_INFO_BLOOD, QQ_INFO_SHOW, QQ_INFO_UNKNOW6, - QQ_INFO_LAST, + QQ_INFO_LAST_2007, QQ_INFO_LAST, }; enum { @@ -142,7 +142,8 @@ { QQ_FIELD_EXT, QQ_FIELD_CHOICE, "zodiac", N_("Zodiac"), zodiac_names, QQ_ZODIAC_SIZE }, { QQ_FIELD_EXT, QQ_FIELD_CHOICE, "blood", N_("Blood"), blood_types, QQ_BLOOD_SIZE }, { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "qq_show", "QQ Show", NULL, 0 }, - { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow6", "Unknow6", NULL, 0 } + { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "unknow6", "Unknow6", NULL, 0 }, + { QQ_FIELD_UNUSED, QQ_FIELD_STRING, "LAST_2005", "LAST_2005", NULL, 0 } }; typedef struct _modify_info_request { @@ -568,35 +569,53 @@ } /* after getting info or modify myself, refresh the buddy list accordingly */ -static void qq_refresh_buddy_and_myself(gchar **segments, PurpleConnection *gc) +static void qq_set_buddy_info(gchar **segments, PurpleConnection *gc) { - PurpleBuddy *b; + PurpleBuddy *purple_buddy; qq_data *qd; - qq_buddy *q_bud; + guint32 uid; + qq_buddy *buddy; gchar *alias_utf8; gchar *purple_name; PurpleAccount *account = purple_connection_get_account(gc); qd = (qq_data *) gc->proto_data; - purple_name = uid_to_purple_name(strtol(segments[QQ_INFO_UID], NULL, 10)); + + uid = strtol(segments[QQ_INFO_UID], NULL, 10); + purple_name = uid_to_purple_name(uid); alias_utf8 = qq_to_utf8(segments[QQ_INFO_NICK], QQ_CHARSET_DEFAULT); if (qd->uid == strtol(segments[QQ_INFO_UID], NULL, 10)) { /* it is me */ + purple_debug_info("QQ", "Got my info\n"); qd->my_icon = strtol(segments[QQ_INFO_FACE], NULL, 10); if (alias_utf8 != NULL) purple_account_set_alias(account, alias_utf8); + + /* add me to buddy list */ + purple_buddy = purple_find_buddy(gc->account, purple_name); + if ( purple_buddy == NULL) { + purple_buddy = qq_create_buddy(gc, uid, TRUE, FALSE); + } + buddy = g_new0(qq_buddy, 1); + buddy->uid = uid; + buddy->status = QQ_BUDDY_ONLINE_NORMAL; + purple_buddy->proto_data = buddy; + qd->buddies = g_list_append(qd->buddies, buddy); } + /* update buddy list (including myself, if myself is the buddy) */ - b = purple_find_buddy(gc->account, purple_name); - q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; - if (q_bud != NULL) { /* I have this buddy */ - q_bud->age = strtol(segments[QQ_INFO_AGE], NULL, 10); - q_bud->gender = strtol(segments[QQ_INFO_GENDER], NULL, 10); - q_bud->face = strtol(segments[QQ_INFO_FACE], NULL, 10); + purple_buddy = purple_find_buddy(gc->account, purple_name); + buddy = (purple_buddy == NULL) ? NULL : (qq_buddy *) purple_buddy->proto_data; + if (buddy != NULL) { /* I have this buddy */ + buddy->age = strtol(segments[QQ_INFO_AGE], NULL, 10); + buddy->gender = strtol(segments[QQ_INFO_GENDER], NULL, 10); + buddy->face = strtol(segments[QQ_INFO_FACE], NULL, 10); if (alias_utf8 != NULL) - q_bud->nickname = g_strdup(alias_utf8); - qq_update_buddy_contact(gc, q_bud); - buddy_local_icon_upate(gc->account, purple_name, q_bud->face); + buddy->nickname = g_strdup(alias_utf8); + qq_update_buddy_contact(gc, buddy); + buddy_local_icon_upate(gc->account, purple_name, buddy->face); + } else { + purple_debug_info("QQ", "Can not find buddy data of %s\n", purple_name); } g_free(purple_name); g_free(alias_utf8); @@ -607,12 +626,18 @@ { qq_data *qd; gchar **segments; + gint field_count; g_return_if_fail(data != NULL && data_len != 0); qd = (qq_data *) gc->proto_data; - if (NULL == (segments = split_data(data, data_len, "\x1e", QQ_INFO_LAST))) + if (qd->client_version >= 2008) { + field_count = QQ_INFO_LAST; + } else { + field_count = QQ_INFO_LAST_2007; + } + if (NULL == (segments = split_data(data, data_len, "\x1e", field_count))) return; #ifdef DEBUG @@ -627,13 +652,13 @@ segments[QQ_INFO_FACE] = icon; request_modify_info(gc, segments); - qq_refresh_buddy_and_myself(segments, gc); + qq_set_buddy_info(segments, gc); } g_strfreev(segments); return; } - qq_refresh_buddy_and_myself(segments, gc); + qq_set_buddy_info(segments, gc); switch (action) { case QQ_BUDDY_INFO_DISPLAY: info_display_only(gc, segments); @@ -697,7 +722,7 @@ if ( qd->buddies == NULL) { return; } - + /* server only reply levels for online buddies */ size = 4 * g_list_length(qd->buddies) + 1 + 4; buf = g_newa(guint8, size); @@ -721,7 +746,7 @@ guint32 uid, onlineTime; guint16 level, timeRemainder; qq_buddy *buddy; - + while (data_len - bytes >= 12) { bytes += qq_get32(&uid, data + bytes); bytes += qq_get32(&onlineTime, data + bytes); @@ -784,11 +809,11 @@ buddy->onlineTime = onlineTime; buddy->level = level; buddy->timeRemainder = timeRemainder; - + /* extend bytes in qq2007*/ bytes += 4; /* skip 8 bytes */ /* qq_show_packet("Buddies level", data + bytes, data_len - bytes); */ - + do { bytes += qq_get16(&str_len, data + bytes); if (str_len <= 0 || bytes + str_len > data_len) { diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/buddy_list.c --- a/libpurple/protocols/qq/buddy_list.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/buddy_list.c Wed Oct 22 14:48:46 2008 +0000 @@ -101,7 +101,7 @@ if (qd->client_version >= 2007) { bytes += qq_put16(raw_data + bytes, 0x0000); } - + qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_LIST, raw_data, bytes, update_class, 0); } @@ -251,13 +251,13 @@ guint16 qq_process_get_buddies_list_reply(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; - qq_buddy *q_bud; + qq_buddy *buddy; gint bytes_expected, count; gint bytes, buddy_bytes; + gint nickname_len; guint16 position, unknown; - guint8 pascal_len; - gchar *name; - PurpleBuddy *b; + gchar *purple_name; + PurpleBuddy *purple_buddy; g_return_val_if_fail(data != NULL && data_len != 0, -1); @@ -273,40 +273,39 @@ /* the following data is buddy list in this packet */ count = 0; while (bytes < data_len) { - q_bud = g_new0(qq_buddy, 1); + buddy = g_new0(qq_buddy, 1); /* set flag */ buddy_bytes = bytes; /* 000-003: uid */ - bytes += qq_get32(&q_bud->uid, data + bytes); + bytes += qq_get32(&buddy->uid, data + bytes); /* 004-005: icon index (1-255) */ - bytes += qq_get16(&q_bud->face, data + bytes); + bytes += qq_get16(&buddy->face, data + bytes); /* 006-006: age */ - bytes += qq_get8(&q_bud->age, data + bytes); + bytes += qq_get8(&buddy->age, data + bytes); /* 007-007: gender */ - bytes += qq_get8(&q_bud->gender, data + bytes); + bytes += qq_get8(&buddy->gender, data + bytes); - pascal_len = convert_as_pascal_string(data + bytes, &q_bud->nickname, QQ_CHARSET_DEFAULT); - bytes += pascal_len; - qq_filter_str(q_bud->nickname); + nickname_len = qq_get_vstr(&buddy->nickname, QQ_CHARSET_DEFAULT, data + bytes); + bytes += nickname_len; + qq_filter_str(buddy->nickname); /* Fixme: merge following as 32bit flag */ bytes += qq_get16(&unknown, data + bytes); - bytes += qq_get8(&q_bud->ext_flag, data + bytes); - bytes += qq_get8(&q_bud->comm_flag, data + bytes); - + bytes += qq_get8(&buddy->ext_flag, data + bytes); + bytes += qq_get8(&buddy->comm_flag, data + bytes); + if (qd->client_version >= 2007) { bytes += 4; /* skip 4 bytes */ - bytes_expected = 16 + pascal_len; + bytes_expected = 16 + nickname_len; } else { - bytes_expected = 12 + pascal_len; + bytes_expected = 12 + nickname_len; } - - if (q_bud->uid == 0 || (bytes - buddy_bytes) != bytes_expected) { + if (buddy->uid == 0 || (bytes - buddy_bytes) != bytes_expected) { purple_debug_info("QQ", "Buddy entry, expect %d bytes, read %d bytes\n", bytes_expected, bytes - buddy_bytes); - g_free(q_bud->nickname); - g_free(q_bud); + g_free(buddy->nickname); + g_free(buddy); continue; } else { count++; @@ -314,20 +313,20 @@ #if 1 purple_debug_info("QQ", "buddy [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n", - q_bud->uid, q_bud->ext_flag, q_bud->comm_flag, q_bud->nickname); + buddy->uid, buddy->ext_flag, buddy->comm_flag, buddy->nickname); #endif - name = uid_to_purple_name(q_bud->uid); - b = purple_find_buddy(gc->account, name); - g_free(name); + purple_name = uid_to_purple_name(buddy->uid); + purple_buddy = purple_find_buddy(gc->account, purple_name); + g_free(purple_name); - if (b == NULL) { - b = qq_create_buddy(gc, q_bud->uid, TRUE, FALSE); + if (purple_buddy == NULL) { + purple_buddy = qq_create_buddy(gc, buddy->uid, TRUE, FALSE); } - b->proto_data = q_bud; - qd->buddies = g_list_append(qd->buddies, q_bud); - qq_update_buddy_contact(gc, q_bud); + purple_buddy->proto_data = buddy; + qd->buddies = g_list_append(qd->buddies, buddy); + qq_update_buddy_contact(gc, buddy); } if(bytes > data_len) { @@ -361,7 +360,7 @@ bytes += qq_get8(&reply_code, data + bytes); if(0 != reply_code) { - purple_debug_warning("QQ", "qq_process_get_buddies_and_rooms, %d", reply_code); + purple_debug_warning("QQ", "qq_process_get_buddies_and_rooms, %d\n", reply_code); } bytes += qq_get32(&unknown, data + bytes); @@ -492,7 +491,7 @@ } else { away_cmd = QQ_BUDDY_ONLINE_NORMAL; } - + misc_status = 0x00000000; fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video"); if (fake_video) diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/buddy_opt.c --- a/libpurple/protocols/qq/buddy_opt.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/buddy_opt.c Wed Oct 22 14:48:46 2008 +0000 @@ -346,7 +346,7 @@ uid = purple_name_to_uid(who); g_return_if_fail(uid > 0); - + if (uid == qd->uid) { return; } @@ -501,12 +501,13 @@ /* we add new buddy, if the received packet is from someone not in my list * return the PurpleBuddy that is just created */ -PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create) +PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, + gboolean is_known, gboolean is_create_data) { - PurpleBuddy *buddy; + PurpleBuddy *purple_buddy; PurpleGroup *group; qq_data *qd; - qq_buddy *q_bud; + qq_buddy *buddy; gchar *buddy_name, *group_name; g_return_val_if_fail(gc->account != NULL && uid != 0, NULL); @@ -522,13 +523,13 @@ group = qq_create_group(group_name); buddy_name = uid_to_purple_name(uid); - buddy = purple_find_buddy(gc->account, buddy_name); + purple_buddy = purple_find_buddy(gc->account, buddy_name); /* remove old, we can not simply return here * because there might be old local copy of this buddy */ - if (buddy != NULL) - purple_blist_remove_buddy(buddy); + if (purple_buddy != NULL) + purple_blist_remove_buddy(purple_buddy); - buddy = purple_buddy_new(gc->account, buddy_name, NULL); + purple_buddy = purple_buddy_new(gc->account, buddy_name, NULL); if ( !is_known) { if (purple_privacy_check(gc->account, buddy_name)) { purple_privacy_deny(gc->account, buddy_name, TRUE, FALSE); @@ -537,29 +538,29 @@ } } - if (!create) - buddy->proto_data = NULL; + if (!is_create_data) + purple_buddy->proto_data = NULL; else { - q_bud = g_new0(qq_buddy, 1); - q_bud->uid = uid; - buddy->proto_data = q_bud; - qd->buddies = g_list_append(qd->buddies, q_bud); - qq_request_buddy_info(gc, qd->uid, 0, 0); + buddy = g_new0(qq_buddy, 1); + buddy->uid = uid; + purple_buddy->proto_data = buddy; + qd->buddies = g_list_append(qd->buddies, buddy); + qq_request_buddy_info(gc, uid, 0, 0); qq_request_get_buddies_online(gc, 0, 0); if (qd->client_version >= 2007) { - qq_request_get_level_2007(gc, q_bud->uid); + qq_request_get_level_2007(gc, uid); } else { - qq_request_get_level(gc, q_bud->uid); + qq_request_get_level(gc, uid); } } - purple_blist_add_buddy(buddy, NULL, group, NULL); + purple_blist_add_buddy(purple_buddy, NULL, group, NULL); purple_debug_warning("QQ", "Add new buddy: [%s]\n", buddy_name); g_free(buddy_name); g_free(group_name); - return buddy; + return purple_buddy; } qq_buddy *qq_get_buddy(PurpleConnection *gc, guint32 uid) @@ -574,9 +575,9 @@ purple_buddy = purple_find_buddy(purple_connection_get_account(gc), purple_name); g_free(purple_name); if (purple_buddy == NULL) return NULL; - + if (purple_buddy->proto_data == NULL) { - purple_debug_error("QQ", "Null data of buddy %d\n", uid); + purple_debug_error("QQ", "Can not find buddy data of %d\n", uid); return NULL; } return (qq_buddy *) purple_buddy->proto_data; diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/buddy_opt.h --- a/libpurple/protocols/qq/buddy_opt.h Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/buddy_opt.h Wed Oct 22 14:48:46 2008 +0000 @@ -36,7 +36,8 @@ const char *old_group, const char *new_group); void qq_remove_buddy_and_me(PurpleBlistNode * node); void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create); +PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, + gboolean is_known, gboolean is_create_data); void qq_buddies_list_free(PurpleAccount *account, qq_data *qd); void qq_process_buddy_remove(guint8 *buf, gint buf_len, PurpleConnection *gc); diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/char_conv.c --- a/libpurple/protocols/qq/char_conv.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/char_conv.c Wed Oct 22 14:48:46 2008 +0000 @@ -98,7 +98,7 @@ } /* convert a string from from_charset to to_charset, using g_convert */ -static gchar *_my_convert(const gchar *str, gssize len, const gchar *to_charset, const gchar *from_charset) +static gchar *do_convert(const gchar *str, gssize len, const gchar *to_charset, const gchar *from_charset) { GError *error = NULL; gchar *ret; @@ -128,14 +128,18 @@ * returns the number of bytes read, return -1 if fatal error * the converted UTF-8 will be saved in ret */ -gint convert_as_pascal_string(guint8 *data, gchar **ret, const gchar *from_charset) +gint qq_get_vstr(gchar **ret, const gchar *from_charset, guint8 *data) { guint8 len; g_return_val_if_fail(data != NULL && from_charset != NULL, -1); len = data[0]; - *ret = _my_convert((gchar *) (data + 1), (gssize) len, UTF8, from_charset); + if (len == 0) { + *ret = g_strdup(""); + return 1; + } + *ret = do_convert((gchar *) (data + 1), (gssize) len, UTF8, from_charset); return len + 1; } @@ -214,15 +218,15 @@ return ret; } -/* two convenience methods, using _my_convert */ +/* two convenience methods, using do_convert */ gchar *utf8_to_qq(const gchar *str, const gchar *to_charset) { - return _my_convert(str, -1, to_charset, UTF8); + return do_convert(str, -1, to_charset, UTF8); } gchar *qq_to_utf8(const gchar *str, const gchar *from_charset) { - return _my_convert(str, -1, UTF8, from_charset); + return do_convert(str, -1, UTF8, from_charset); } /* QQ uses binary code for smiley, while purple uses strings. diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/char_conv.h --- a/libpurple/protocols/qq/char_conv.h Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/char_conv.h Wed Oct 22 14:48:46 2008 +0000 @@ -29,7 +29,7 @@ #define QQ_CHARSET_DEFAULT "GB18030" -gint convert_as_pascal_string(guint8 *data, gchar **ret, const gchar *from_charset); +gint qq_get_vstr(gchar **ret, const gchar *from_charset, guint8 *data); gchar *qq_smiley_to_purple(gchar *text); gchar *purple_smiley_to_qq(gchar *text); diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/group_conv.c --- a/libpurple/protocols/qq/group_conv.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/group_conv.c Wed Oct 22 14:48:46 2008 +0000 @@ -74,55 +74,64 @@ gchar *member_name, *member_uid; PurpleConversation *conv; gint flag; + gboolean is_find; g_return_if_fail(group != NULL); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + group->title_utf8, purple_connection_get_account(gc)); + + g_return_if_fail (conv != NULL && group->members != NULL); + names = NULL; flags = NULL; - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - group->title_utf8, purple_connection_get_account(gc)); - if (conv != NULL && group->members != NULL) { - list = group->members; - while (list != NULL) { - member = (qq_buddy *) list->data; + + list = group->members; + while (list != NULL) { + member = (qq_buddy *) list->data; - /* we need unique identifiers for everyone in the chat or else we'll - * run into problems with functions like get_cb_real_name from qq.c */ - member_name = (member->nickname != NULL && *(member->nickname) != '\0') ? - g_strdup_printf("%s (%u)", member->nickname, member->uid) : - g_strdup_printf("(%u)", member->uid); - member_uid = g_strdup_printf("(%u)", member->uid); + /* we need unique identifiers for everyone in the chat or else we'll + * run into problems with functions like get_cb_real_name from qq.c */ + member_name = (member->nickname != NULL && *(member->nickname) != '\0') ? + g_strdup_printf("%s (%u)", member->nickname, member->uid) : + g_strdup_printf("(%u)", member->uid); + member_uid = g_strdup_printf("(%u)", member->uid); - flag = 0; - /* TYPING to put online above OP and FOUNDER */ - if (is_online(member->status)) - flag |= (PURPLE_CBFLAGS_TYPING | PURPLE_CBFLAGS_VOICE); - if(1 == (member->role & 1)) flag |= PURPLE_CBFLAGS_OP; - if(member->uid == group->creator_uid) flag |= PURPLE_CBFLAGS_FOUNDER; + flag = 0; + /* TYPING to put online above OP and FOUNDER */ + if (is_online(member->status)) flag |= (PURPLE_CBFLAGS_TYPING | PURPLE_CBFLAGS_VOICE); + if(1 == (member->role & 1)) flag |= PURPLE_CBFLAGS_OP; + if(member->uid == group->creator_uid) flag |= PURPLE_CBFLAGS_FOUNDER; - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_name)) - { - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), - member_name, - flag); - } else if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_uid)) - { - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), - member_uid, - flag); - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(conv), member_uid, member_name); - } else { - /* always put it even offline */ - names = g_list_append(names, member_name); - flags = g_list_append(flags, GINT_TO_POINTER(flag)); - } - g_free(member_uid); - list = list->next; + is_find = TRUE; + if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_name)) + { + purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), + member_name, + flag); + } else if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_uid)) + { + purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), + member_uid, + flag); + purple_conv_chat_rename_user(PURPLE_CONV_CHAT(conv), member_uid, member_name); + } else { + is_find = FALSE; } + if (!is_find) { + /* always put it even offline */ + names = g_list_append(names, member_name); + flags = g_list_append(flags, GINT_TO_POINTER(flag)); + } else { + g_free(member_name); + } + g_free(member_uid); + list = list->next; + } - if (names != NULL && flags != NULL) { - purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE); - } + if (names != NULL && flags != NULL) { + purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE); } + /* clean up names */ while (names != NULL) { member_name = (gchar *) names->data; diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/group_im.c --- a/libpurple/protocols/qq/group_im.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/group_im.c Wed Oct 22 14:48:46 2008 +0000 @@ -107,7 +107,7 @@ g_return_if_fail(ext_id > 0 && user_uid > 0); - bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(&reason_utf8, QQ_CHARSET_DEFAULT, data + bytes); msg = g_strdup_printf(_("%d request to join Qun %d"), user_uid, ext_id); reason = g_strdup_printf(_("Message: %s"), reason_utf8); @@ -161,7 +161,7 @@ if (uid_from != 0) { buddy = qq_group_find_member_by_uid(group, uid_from); if (buddy == NULL || buddy->nickname == NULL) - from = uid_to_purple_name(uid_from); + from = g_strdup_printf("%d", uid_from); else from = g_strdup(buddy->nickname); } else { @@ -192,7 +192,7 @@ g_return_if_fail(ext_id > 0 && admin_uid > 0); - bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(&reason_utf8, QQ_CHARSET_DEFAULT, data + bytes); msg = g_strdup_printf (_("Failed to join Qun %d, operated by admin %d"), ext_id, admin_uid); @@ -231,7 +231,7 @@ g_return_if_fail(ext_id > 0 && admin_uid > 0); /* it is also a "无" here, so do not display */ - bytes += convert_as_pascal_string(data + bytes, &reason, QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(&reason, QQ_CHARSET_DEFAULT, data + bytes); group = qq_room_search_id(gc, id); if (group != NULL) { @@ -317,7 +317,7 @@ } /* recv an IM from a group chat */ -void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type) +void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type) { gchar *msg_with_purple_smiley, *msg_utf8_encoded; qq_data *qd; @@ -353,7 +353,7 @@ bytes += qq_get32(&(packet.ext_id), data + bytes); bytes += qq_get8(&(packet.type8), data + bytes); - if(QQ_RECV_IM_TEMP_QUN_IM == im_type) { + if(QQ_MSG_TEMP_QUN_IM == msg_type) { bytes += qq_get32(&(id), data + bytes); } @@ -384,7 +384,7 @@ * buf.getInt(); */ - if(im_type != QQ_RECV_IM_UNKNOWN_QUN_IM) + if(msg_type != QQ_MSG_UNKNOWN_QUN_IM) skip_len = 10; else skip_len = 0; diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/group_im.h --- a/libpurple/protocols/qq/group_im.h Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/group_im.h Wed Oct 22 14:48:46 2008 +0000 @@ -36,7 +36,7 @@ void qq_process_group_cmd_im(guint8 *data, gint len, PurpleConnection *gc); -void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type); +void qq_process_room_msg_normal(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 msg_type); void qq_process_room_msg_apply_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc); diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/group_info.c --- a/libpurple/protocols/qq/group_info.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/group_info.c Wed Oct 22 14:48:46 2008 +0000 @@ -157,7 +157,7 @@ qd = (qq_data *) gc->proto_data; /* qq_show_packet("Room Info", data, data_len); */ - + bytes = 0; bytes += qq_get32(&id, data + bytes); g_return_if_fail(id > 0); @@ -197,10 +197,10 @@ } /* qq_show_packet("Room Info", data + bytes, data_len - bytes); */ /* strlen + */ - bytes += convert_as_pascal_string(data + bytes, &(group->title_utf8), QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(&(group->title_utf8), QQ_CHARSET_DEFAULT, data + bytes); bytes += qq_get16(&unknown, data + bytes); /* 0x0000 */ - bytes += convert_as_pascal_string(data + bytes, ¬ice, QQ_CHARSET_DEFAULT); - bytes += convert_as_pascal_string(data + bytes, &(group->desc_utf8), QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(¬ice, QQ_CHARSET_DEFAULT, data + bytes); + bytes += qq_get_vstr(&(group->desc_utf8), QQ_CHARSET_DEFAULT, data + bytes); purple_debug_info("QQ", "room [%s] notice [%s] desc [%s] unknow 0x%04X\n", group->title_utf8, notice, group->desc_utf8, unknown); @@ -336,7 +336,7 @@ bytes += qq_get16(&(member->face), data + bytes); bytes += qq_get8(&(member->age), data + bytes); bytes += qq_get8(&(member->gender), data + bytes); - bytes += convert_as_pascal_string(data + bytes, &nick, QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(&nick, QQ_CHARSET_DEFAULT, data + bytes); bytes += qq_get16(&unknown, data + bytes); bytes += qq_get8(&(member->ext_flag), data + bytes); bytes += qq_get8(&(member->comm_flag), data + bytes); diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/group_search.c --- a/libpurple/protocols/qq/group_search.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/group_search.c Wed Oct 22 14:48:46 2008 +0000 @@ -110,10 +110,10 @@ bytes += qq_get16(&(unknown), data + bytes); bytes += qq_get16(&(unknown), data + bytes); bytes += qq_get32(&(group.category), data + bytes); - bytes += convert_as_pascal_string(data + bytes, &(group.title_utf8), QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(&(group.title_utf8), QQ_CHARSET_DEFAULT, data + bytes); bytes += qq_get16(&(unknown), data + bytes); bytes += qq_get8(&(group.auth_type), data + bytes); - bytes += convert_as_pascal_string(data + bytes, &(group.desc_utf8), QQ_CHARSET_DEFAULT); + bytes += qq_get_vstr(&(group.desc_utf8), QQ_CHARSET_DEFAULT, data + bytes); /* end of one qq_group */ if(bytes != len) { purple_debug_error("QQ", diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/im.h --- a/libpurple/protocols/qq/im.h Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/im.h Wed Oct 22 14:48:46 2008 +0000 @@ -39,21 +39,22 @@ }; enum { - QQ_RECV_IM_TO_BUDDY = 0x0009, - QQ_RECV_IM_TO_UNKNOWN = 0x000a, - QQ_RECV_IM_NEWS = 0x0018, - QQ_RECV_IM_UNKNOWN_QUN_IM = 0x0020, - QQ_RECV_IM_ADD_TO_QUN = 0x0021, - QQ_RECV_IM_DEL_FROM_QUN = 0x0022, - QQ_RECV_IM_APPLY_ADD_TO_QUN = 0x0023, - QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN = 0x0024, - QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN = 0x0025, - QQ_RECV_IM_CREATE_QUN = 0x0026, - QQ_RECV_IM_TEMP_QUN_IM = 0x002A, - QQ_RECV_IM_QUN_IM = 0x002B, - QQ_RECV_IM_SYS_NOTIFICATION = 0x0030, - QQ_RECV_IM_EXTEND = 0x0084, - QQ_RECV_IM_EXTEND_85 = 0x0085, + QQ_MSG_TO_BUDDY = 0x0009, + QQ_MSG_TO_UNKNOWN = 0x000a, + QQ_MSG_NEWS = 0x0018, + QQ_MSG_UNKNOWN_QUN_IM = 0x0020, + QQ_MSG_ADD_TO_QUN = 0x0021, + QQ_MSG_DEL_FROM_QUN = 0x0022, + QQ_MSG_APPLY_ADD_TO_QUN = 0x0023, + QQ_MSG_APPROVE_APPLY_ADD_TO_QUN = 0x0024, + QQ_MSG_REJCT_APPLY_ADD_TO_QUN = 0x0025, + QQ_MSG_CREATE_QUN = 0x0026, + QQ_MSG_TEMP_QUN_IM = 0x002A, + QQ_MSG_QUN_IM = 0x002B, + QQ_MSG_SYS_30 = 0x0030, + QQ_MSG_SYS_4C = 0x004C, + QQ_MSG_EXTEND = 0x0084, + QQ_MSG_EXTEND_85 = 0x0085, }; void qq_got_attention(PurpleConnection *gc, const gchar *msg); diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/qq_process.c --- a/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:48:46 2008 +0000 @@ -95,7 +95,7 @@ purple_notify_error(gc, _("Error"), _("Failed to send IM."), NULL); return; } - + purple_debug_info("QQ", "OK sent IM\n"); } @@ -148,8 +148,7 @@ g_free(content_utf8); } -/* process im from system administrator */ -static void do_server_im(guint8 *data, gint data_len, PurpleConnection *gc) +static void do_msg_sys_30(PurpleConnection *gc, guint8 *data, gint data_len) { gint len; guint8 reply; @@ -165,46 +164,79 @@ reply = strtol(segments[0], NULL, 10); if (reply == 1) purple_debug_warning("QQ", "We are kicked out by QQ server\n"); - + msg_utf8 = qq_to_utf8(segments[1], QQ_CHARSET_DEFAULT); - purple_notify_warning(gc, NULL, _("System Message"), msg_utf8); + qq_got_attention(gc, msg_utf8); +} + +static void do_msg_sys_4c(PurpleConnection *gc, guint8 *data, gint data_len) +{ + gint bytes; + gint msg_len; + GString *content; + gchar *msg = NULL; + + g_return_if_fail(data != NULL && data_len > 0); + + bytes = 6; /* skip 0x(06 00 01 1e 01 1c)*/ + + content = g_string_new(""); + while (bytes < data_len) { + msg_len = qq_get_vstr(&msg, QQ_CHARSET_DEFAULT, data + bytes); + g_string_append(content, msg); + g_string_append(content, "\n"); + g_free(msg); + + if (msg_len <= 1) { + break; + } + bytes += msg_len; + } + if (bytes != data_len) { + purple_debug_warning("QQ", "Failed to read QQ_MSG_SYS_4C\n"); + qq_show_packet("do_msg_sys_4c", data, data_len); + } + qq_got_attention(gc, content->str); + g_string_free(content, FALSE); } static const gchar *get_im_type_desc(gint type) { switch (type) { - case QQ_RECV_IM_TO_BUDDY: - return "QQ_RECV_IM_TO_BUDDY"; - case QQ_RECV_IM_TO_UNKNOWN: - return "QQ_RECV_IM_TO_UNKNOWN"; - case QQ_RECV_IM_UNKNOWN_QUN_IM: - return "QQ_RECV_IM_UNKNOWN_QUN_IM"; - case QQ_RECV_IM_ADD_TO_QUN: - return "QQ_RECV_IM_ADD_TO_QUN"; - case QQ_RECV_IM_DEL_FROM_QUN: - return "QQ_RECV_IM_DEL_FROM_QUN"; - case QQ_RECV_IM_APPLY_ADD_TO_QUN: - return "QQ_RECV_IM_APPLY_ADD_TO_QUN"; - case QQ_RECV_IM_CREATE_QUN: - return "QQ_RECV_IM_CREATE_QUN"; - case QQ_RECV_IM_SYS_NOTIFICATION: - return "QQ_RECV_IM_SYS_NOTIFICATION"; - case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN: - return "QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN"; - case QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN: - return "QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN"; - case QQ_RECV_IM_TEMP_QUN_IM: - return "QQ_RECV_IM_TEMP_QUN_IM"; - case QQ_RECV_IM_QUN_IM: - return "QQ_RECV_IM_QUN_IM"; - case QQ_RECV_IM_NEWS: - return "QQ_RECV_IM_NEWS"; - case QQ_RECV_IM_EXTEND: - return "QQ_RECV_IM_EXTEND"; - case QQ_RECV_IM_EXTEND_85: - return "QQ_RECV_IM_EXTEND_85"; + case QQ_MSG_TO_BUDDY: + return "QQ_MSG_TO_BUDDY"; + case QQ_MSG_TO_UNKNOWN: + return "QQ_MSG_TO_UNKNOWN"; + case QQ_MSG_UNKNOWN_QUN_IM: + return "QQ_MSG_UNKNOWN_QUN_IM"; + case QQ_MSG_ADD_TO_QUN: + return "QQ_MSG_ADD_TO_QUN"; + case QQ_MSG_DEL_FROM_QUN: + return "QQ_MSG_DEL_FROM_QUN"; + case QQ_MSG_APPLY_ADD_TO_QUN: + return "QQ_MSG_APPLY_ADD_TO_QUN"; + case QQ_MSG_CREATE_QUN: + return "QQ_MSG_CREATE_QUN"; + case QQ_MSG_SYS_30: + return "QQ_MSG_SYS_30"; + case QQ_MSG_SYS_4C: + return "QQ_MSG_SYS_4C"; + case QQ_MSG_APPROVE_APPLY_ADD_TO_QUN: + return "QQ_MSG_APPROVE_APPLY_ADD_TO_QUN"; + case QQ_MSG_REJCT_APPLY_ADD_TO_QUN: + return "QQ_MSG_REJCT_APPLY_ADD_TO_QUN"; + case QQ_MSG_TEMP_QUN_IM: + return "QQ_MSG_TEMP_QUN_IM"; + case QQ_MSG_QUN_IM: + return "QQ_MSG_QUN_IM"; + case QQ_MSG_NEWS: + return "QQ_MSG_NEWS"; + case QQ_MSG_EXTEND: + return "QQ_MSG_EXTEND"; + case QQ_MSG_EXTEND_85: + return "QQ_MSG_EXTEND_85"; default: - return "QQ_RECV_IM_UNKNOWN"; + return "QQ_MSG_UNKNOWN"; } } @@ -221,7 +253,7 @@ guint32 seq; struct in_addr ip_from; guint16 port_from; - guint16 im_type; + guint16 msg_type; } header; g_return_if_fail(data != NULL && data_len != 0); @@ -250,7 +282,7 @@ /* if the message is delivered via server, it is server IP/port */ bytes += qq_getIP(&(header.ip_from), data + bytes); bytes += qq_get16(&(header.port_from), data + bytes); - bytes += qq_get16(&(header.im_type), data + bytes); + bytes += qq_get16(&(header.msg_type), data + bytes); /* im_header prepared */ if (header.uid_to != qd->uid) { /* should not happen */ @@ -264,63 +296,63 @@ return; } - switch (header.im_type) { - case QQ_RECV_IM_NEWS: + switch (header.msg_type) { + case QQ_MSG_NEWS: do_server_news(data + bytes, data_len - bytes, gc); break; - case QQ_RECV_IM_EXTEND: - case QQ_RECV_IM_EXTEND_85: + case QQ_MSG_EXTEND: + case QQ_MSG_EXTEND_85: purple_debug_info("QQ", "MSG from buddy [%d]\n", header.uid_from); qq_process_extend_im(gc, data + bytes, data_len - bytes); break; - case QQ_RECV_IM_TO_UNKNOWN: - case QQ_RECV_IM_TO_BUDDY: + case QQ_MSG_TO_UNKNOWN: + case QQ_MSG_TO_BUDDY: purple_debug_info("QQ", "MSG from buddy [%d]\n", header.uid_from); qq_process_im(gc, data + bytes, data_len - bytes); break; - case QQ_RECV_IM_UNKNOWN_QUN_IM: - case QQ_RECV_IM_TEMP_QUN_IM: - case QQ_RECV_IM_QUN_IM: + case QQ_MSG_UNKNOWN_QUN_IM: + case QQ_MSG_TEMP_QUN_IM: + case QQ_MSG_QUN_IM: purple_debug_info("QQ", "MSG from room [%d]\n", header.uid_from); - /* uid_from is in fact id */ - qq_process_room_msg_normal(data + bytes, data_len - bytes, header.uid_from, gc, header.im_type); + qq_process_room_msg_normal(data + bytes, data_len - bytes, header.uid_from, gc, header.msg_type); break; - case QQ_RECV_IM_ADD_TO_QUN: + case QQ_MSG_ADD_TO_QUN: purple_debug_info("QQ", "Notice from [%d], Added\n", header.uid_from); /* uid_from is group id * we need this to create a dummy group and add to blist */ qq_process_room_msg_been_added(data + bytes, data_len - bytes, header.uid_from, gc); break; - case QQ_RECV_IM_DEL_FROM_QUN: + case QQ_MSG_DEL_FROM_QUN: purple_debug_info("QQ", "Notice from room [%d], Removed\n", header.uid_from); /* uid_from is group id */ qq_process_room_msg_been_removed(data + bytes, data_len - bytes, header.uid_from, gc); break; - case QQ_RECV_IM_APPLY_ADD_TO_QUN: + case QQ_MSG_APPLY_ADD_TO_QUN: purple_debug_info("QQ", "Notice from room [%d], Joined\n", header.uid_from); /* uid_from is group id */ qq_process_room_msg_apply_join(data + bytes, data_len - bytes, header.uid_from, gc); break; - case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN: + case QQ_MSG_APPROVE_APPLY_ADD_TO_QUN: purple_debug_info("QQ", "Notice from room [%d], Confirm add in\n", header.uid_from); /* uid_from is group id */ qq_process_room_msg_been_approved(data + bytes, data_len - bytes, header.uid_from, gc); break; - case QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN: + case QQ_MSG_REJCT_APPLY_ADD_TO_QUN: purple_debug_info("QQ", "Notice from room [%d], Refuse add in\n", header.uid_from); /* uid_from is group id */ qq_process_room_msg_been_rejected(data + bytes, data_len - bytes, header.uid_from, gc); break; - case QQ_RECV_IM_SYS_NOTIFICATION: - purple_debug_info("QQ", "Admin notice from [%d]\n", header.uid_from); - do_server_im(data + bytes, data_len - bytes, gc); + case QQ_MSG_SYS_30: + do_msg_sys_30(gc, data + bytes, data_len - bytes); + break; + case QQ_MSG_SYS_4C: + do_msg_sys_4c(gc, data + bytes, data_len - bytes); break; default: - purple_debug_warning("QQ", "MSG from [%d], unknown type %s [0x%02x]\n", - header.uid_from, get_im_type_desc(header.im_type), - header.im_type); + purple_debug_warning("QQ", "MSG from [%d], unknown type %s [0x%04X]\n", + header.uid_from, get_im_type_desc(header.msg_type), header.msg_type); qq_show_packet("Unknown MSG type", data, data_len); break; } diff -r c2253c485728 -r a95c7e71064c libpurple/protocols/qq/utils.c --- a/libpurple/protocols/qq/utils.c Wed Oct 22 14:47:39 2008 +0000 +++ b/libpurple/protocols/qq/utils.c Wed Oct 22 14:48:46 2008 +0000 @@ -104,7 +104,7 @@ { guint8 *input; gchar **segments; - gint i, j; + gint count, j; g_return_val_if_fail(data != NULL && len != 0 && delimit != 0, NULL); @@ -118,22 +118,18 @@ if (expected_fields <= 0) return segments; - for (i = 0; segments[i] != NULL; i++) {; + for (count = 0; segments[count] != NULL; count++) {; } - if (i < expected_fields) { /* not enough fields */ - purple_debug_error("QQ", "Invalid data, expect %d fields, found only %d, discard\n", - expected_fields, i); - g_strfreev(segments); + if (count < expected_fields) { /* not enough fields */ + purple_debug_error("QQ", "Less fields %d then %d\n", count, expected_fields); return NULL; - } else if (i > expected_fields) { /* more fields, OK */ - purple_debug_warning("QQ", "Dangerous data, expect %d fields, found %d, return all\n", - expected_fields, i); + } else if (count > expected_fields) { /* more fields, OK */ + purple_debug_warning("QQ", "More fields %d than %d\n", count, expected_fields); /* free up those not used */ - for (j = expected_fields; j < i; j++) { + for (j = expected_fields; j < count; j++) { purple_debug_warning("QQ", "field[%d] is %s\n", j, segments[j]); g_free(segments[j]); } - segments[expected_fields] = NULL; } @@ -197,7 +193,7 @@ g_return_val_if_fail(start != NULL, NULL); end = strchr(start, ')'); g_return_val_if_fail(end != NULL && (end - start) > 1, NULL); - + ret = g_strndup(start + 1, end - start - 1); return ret;