Mercurial > pidgin.yaz
changeset 24026:25f62d21b3f8
disapproval of revision '8cebefbc6cd5d84acb69c74e69e8821f11dd225d'
line wrap: on
line diff
--- a/libpurple/protocols/qq/AUTHORS Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/AUTHORS Mon Sep 15 03:04:07 2008 +0000 @@ -1,38 +1,35 @@ Code Contributors -========= -puzzlebird : original author -gfhuang : patches for libpurple 2.0.0beta2, maintainer -Yuan Qingyun : patches for libpurple 1.5.0, maintainer -henryouly : file transfer, udp sock5 proxy and qq_show, maintainer -hzhr : maintainer -joymarquis : maintainer -arfankai : fixed bugs in char_conv.c -rakescar : provided filter for HTML tag -yyw : improved performance on PPC linux -lvxiang : provided ip to location original code -markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007 -ccpaging : maintainer since 2007 -icesky : maintainer since 2007 -csyfek : faces, maintainer since 2007 +===== +puzzlebird : original author +gfhuang : patches for libpurple 2.0.0beta2, maintainer +henryouly : file transfer, udp sock5 proxy and qq_show, maintainer +hzhr : maintainer +joymarquis : maintainer +arfankai : fixed bugs in char_conv.c +rakescar : provided filter for HTML tag +yyw : improved performance on PPC linux +lvxiang : provided ip to location original code +markhuetsch : OpenQ merge into libpurple, maintainer 2006-2007 +ccpaging : maintainer since 2007 +icesky : maintainer since 2007 +csyfek : faces, maintainer since 2007 Lovely Patch Writers -========= -gnap : message displaying, documentation -manphiz : qun processing -moo : qun processing -Coly Li : qun processing -Emil Alexiev : captcha verification on login based on LumaQQ for MAC (2007), - login, add buddy, remove buddy, message exchange and logout +===== +gnap : message displaying, documentation +manphiz : qun processing +moo : qun processing +Coly Li : qun processing Acknowledgement -========= -Shufeng Tan : http://sf.net/projects/perl-oicq -Jeff Ye : http://www.sinomac.com -Hu Zheng : http://forlinux.yeah.net -yunfan : http://www.myswear.net -OpenQ Team : http://openq.linuxsir.org -LumaQQ Team : http://lumaqq.linuxsir.org +===== +Shufeng Tan : http://sf.net/projects/perl-oicq +Jeff Ye : http://www.sinomac.com +Hu Zheng : http://forlinux.yeah.net +yunfan : http://www.myswear.net khc@pidgin.im qulogic@pidgin.im rlaager@pidgin.im -OpenQ Google Group : http://groups.google.com/group/openq +OpenQ Team +LumaQQ Team +OpenQ Google Group
--- a/libpurple/protocols/qq/ChangeLog Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/ChangeLog Mon Sep 15 03:04:07 2008 +0000 @@ -1,17 +1,6 @@ -2008.08.16 - ccpaging <ecc_hy(at)hotmail.com> - * Rename group to room. If you used pidginqq before, this may create a new room with same title, you may delete old one - * Replace purple_debug with purple_debug_info, purple_debug_warning, purple_debug_error - * Add server notice and server new, and two options to turn on/off - * Minor modify for reducing transaction's debug infor - * Minor modifies for system notice and QQ news. - * Add 4 new strings need translate compare with p10. - 2008.08.10 - csyfek <csyfek(at)gmail.com> * Commit to Pidgin -2008.08.07 - ccpaging <ecc_hy(at)hotmail.com> - * Support managing multi-connections according to simple.c - 2008.08.06 - ccpaging <ecc_hy(at)hotmail.com> * Rename names of variables, Group, to Room * Functions of group_network merged into qq_network and qq_process
--- a/libpurple/protocols/qq/buddy_info.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/buddy_info.c Mon Sep 15 03:04:07 2008 +0000 @@ -284,7 +284,7 @@ qd = (qq_data *) gc->proto_data; g_snprintf(uid_str, sizeof(uid_str), "%d", uid); - qq_send_cmd(gc, QQ_CMD_GET_USER_INFO, (guint8 *) uid_str, strlen(uid_str)); + qq_send_cmd(qd, QQ_CMD_GET_USER_INFO, (guint8 *) uid_str, strlen(uid_str)); query = g_new0(qq_info_query, 1); query->uid = uid; @@ -293,20 +293,6 @@ qd->info_query = g_list_append(qd->info_query, query); } -void qq_request_buddy_info(PurpleConnection *gc, guint32 uid, - gint update_class, guint32 ship32) -{ - qq_data *qd; - gchar raw_data[16] = {0}; - - g_return_if_fail(uid != 0); - - qd = (qq_data *) gc->proto_data; - g_snprintf(raw_data, sizeof(raw_data), "%d", uid); - qq_send_cmd_mess(gc, QQ_CMD_GET_USER_INFO, (guint8 *) raw_data, strlen(raw_data), - update_class, ship32); -} - /* set up the fields requesting personal information and send a get_info packet * for myself */ void qq_prepare_modify_info(PurpleConnection *gc) @@ -328,6 +314,7 @@ /* send packet to modify personal information */ static void qq_send_packet_modify_info(PurpleConnection *gc, contact_info *info) { + qq_data *qd = (qq_data *) gc->proto_data; gint bytes = 0; guint8 raw_data[MAX_PACKET_SIZE - 128] = {0}; guint8 bar; @@ -459,7 +446,7 @@ bytes += qq_put8(raw_data + bytes, bar); - qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, raw_data, bytes); + qq_send_cmd(qd, QQ_CMD_UPDATE_INFO, raw_data, bytes); } @@ -710,8 +697,8 @@ data[data_len] = '\0'; if (qd->uid == atoi((gchar *) data)) { /* return should be my uid */ - purple_debug_info("QQ", "Update info ACK OK\n"); - purple_notify_info(gc, NULL, _("My information has been updated"), NULL); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Update info ACK OK\n"); + purple_notify_info(gc, NULL, _("Your information has been updated"), NULL); } } @@ -759,8 +746,8 @@ const gchar *buddy_icon_dir = qq_buddy_icon_dir(); gint prefix_len = strlen(QQ_ICON_PREFIX); gint suffix_len = strlen(QQ_ICON_SUFFIX); - gint dir_len = strlen(buddy_icon_dir); - gchar *errmsg = g_strdup_printf(_("Setting custom faces is not currently supported. Please choose an image from %s."), buddy_icon_dir); + gint dir_len = buddy_icon_dir ? strlen(buddy_icon_dir) : 0; + gchar *errmsg = g_strdup_printf(_("Setting custom faces is not currently supported. Please choose an image from %s."), buddy_icon_dir ? buddy_icon_dir : "(null)"); gboolean icon_global = purple_account_get_bool(gc->account, "use-global-buddyicon", TRUE); if (!icon_path) @@ -769,13 +756,13 @@ icon_len = strlen(icon_path) - dir_len - 1 - prefix_len - suffix_len; /* make sure we're using an appropriate icon */ - if (!(g_ascii_strncasecmp(icon_path, buddy_icon_dir, dir_len) == 0 + if (buddy_icon_dir && !(g_ascii_strncasecmp(icon_path, buddy_icon_dir, dir_len) == 0 && icon_path[dir_len] == G_DIR_SEPARATOR && g_ascii_strncasecmp(icon_path + dir_len + 1, QQ_ICON_PREFIX, prefix_len) == 0 && g_ascii_strncasecmp(icon_path + dir_len + 1 + prefix_len + icon_len, QQ_ICON_SUFFIX, suffix_len) == 0 && icon_len <= 3)) { if (icon_global) - purple_debug_error("QQ", "%s\n", errmsg); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "%s\n", errmsg); else purple_notify_error(gc, _("Invalid QQ Face"), errmsg, NULL); g_free(errmsg); @@ -788,7 +775,7 @@ /* ensure face number in proper range */ if (icon_num > QQ_FACES) { if (icon_global) - purple_debug_error("QQ", "%s\n", errmsg); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "%s\n", errmsg); else purple_notify_error(gc, _("Invalid QQ Face"), errmsg, NULL); g_free(errmsg); @@ -811,8 +798,8 @@ if ((buddy = purple_find_buddy(account, name))) old_icon_num = purple_buddy_icons_get_checksum_for_user(buddy); - if (old_icon_num == NULL || - strcmp(icon_num_str, old_icon_num)) + if ((old_icon_num == NULL || + strcmp(icon_num_str, old_icon_num)) && (qq_buddy_icon_dir() != NULL)) { gchar *icon_path; @@ -915,21 +902,19 @@ void qq_info_query_free(qq_data *qd) { - gint count; + gint i; qq_info_query *p; g_return_if_fail(qd != NULL); - count = 0; + i = 0; while (qd->info_query != NULL) { p = (qq_info_query *) (qd->info_query->data); qd->info_query = g_list_remove(qd->info_query, p); g_free(p); - count++; + i++; } - if (count > 0) { - purple_debug_info("QQ", "%d info queries are freed!\n", count); - } + purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d info queries are freed!\n", i); } void qq_send_packet_get_level(PurpleConnection *gc, guint32 uid) @@ -942,10 +927,10 @@ bytes += qq_put32(buf + bytes, uid); qd = (qq_data *) gc->proto_data; - qq_send_cmd(gc, QQ_CMD_GET_LEVEL, buf, bytes); + qq_send_cmd(qd, QQ_CMD_GET_LEVEL, buf, bytes); } -void qq_request_get_buddies_levels(PurpleConnection *gc, gint update_class) +void qq_send_packet_get_buddies_levels(PurpleConnection *gc) { guint8 *buf; guint16 size; @@ -957,11 +942,12 @@ if ( qd->buddies == NULL) { return; } - /* server only reply levels for online buddies */ - size = 4 * g_list_length(qd->buddies) + 1 + 4; + /* server only sends back levels for online buddies, no point + * in asking for anyone else */ + size = 4 * g_list_length(qd->buddies) + 1; buf = g_newa(guint8, size); bytes += qq_put8(buf + bytes, 0x00); - + while (NULL != node) { q_bud = (qq_buddy *) node->data; if (NULL != q_bud) { @@ -969,10 +955,7 @@ } node = node->next; } - - /* my id should be the end if included */ - bytes += qq_put32(buf + bytes, qd->uid); - qq_send_cmd_mess(gc, QQ_CMD_GET_LEVEL, buf, size, update_class, 0); + qq_send_cmd(qd, QQ_CMD_GET_LEVEL, buf, size); } void qq_process_get_level_reply(guint8 *decr_buf, gint decr_len, PurpleConnection *gc) @@ -987,9 +970,9 @@ qq_data *qd = (qq_data *) gc->proto_data; gint bytes = 0; - decr_len--; + decr_len--; if (decr_len % 12 != 0) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Get levels list of abnormal length. Truncating last %d bytes.\n", decr_len % 12); decr_len -= (decr_len % 12); } @@ -997,18 +980,19 @@ bytes += 1; /* this byte seems random */ /* - purple_debug_info("QQ", "Byte one of get_level packet: %d\n", buf[0]); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Byte one of get_level packet: %d\n", buf[0]); */ for (i = 0; i < decr_len; i += 12) { bytes += qq_get32(&uid, decr_buf + bytes); bytes += qq_get32(&onlineTime, decr_buf + bytes); bytes += qq_get16(&level, decr_buf + bytes); bytes += qq_get16(&timeRemainder, decr_buf + bytes); - purple_debug_info("QQ_LEVEL", "%d, tmOnline: %d, level: %d, tmRemainder: %d\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ_LEVEL", + "%d, tmOnline: %d, level: %d, tmRemainder: %d\n", uid, onlineTime, level, timeRemainder); if (uid == qd->uid) { qd->my_level = level; - purple_debug_warning("QQ", "Got my levels as %d\n", qd->my_level); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Got my levels as %d\n", qd->my_level); continue; } @@ -1016,7 +1000,7 @@ if (purple_name == NULL) { continue; } - + b = purple_find_buddy(account, purple_name); g_free(purple_name); @@ -1024,9 +1008,10 @@ if (b != NULL) { q_bud = (qq_buddy *) b->proto_data; } - + if (q_bud == NULL) { - purple_debug_error("QQ", "Got levels of %d not in my buddy list\n", uid); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "Got levels of %d not in my buddy list\n", uid); continue; }
--- a/libpurple/protocols/qq/buddy_info.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/buddy_info.h Mon Sep 15 03:04:07 2008 +0000 @@ -51,14 +51,14 @@ #define QQ_FRIEND_FLAG_MOBILE 0x10 #define QQ_FRIEND_FLAG_BIND_MOBILE 0x20 */ -#define QQ_COMM_FLAG_QQ_VIP 0x02 -#define QQ_COMM_FLAG_QQ_MEMBER 0x04 +#define QQ_COMM_FLAG_QQ_MEMBER 0x02 +#define QQ_COMM_FLAG_QQ_VIP 0x04 #define QQ_COMM_FLAG_TCP_MODE 0x10 #define QQ_COMM_FLAG_MOBILE 0x20 #define QQ_COMM_FLAG_BIND_MOBILE 0x40 #define QQ_COMM_FLAG_VIDEO 0x80 -#define QQ_EXT_FLAG_ZONE 0x02 +#define QQ_EXT_FLAG_SPACE 0x02 #define QQ_BUDDY_GENDER_GG 0x00 #define QQ_BUDDY_GENDER_MM 0x01 @@ -67,15 +67,7 @@ #define QQ_ICON_PREFIX "qq_" #define QQ_ICON_SUFFIX ".png" -enum { - QQ_BUDDY_INFO_UPDATE_ONLY = 0, - QQ_BUDDY_INFO_DISPLAY, - QQ_BUDDY_INFO_MODIFY, -}; - void qq_send_packet_get_info(PurpleConnection *gc, guint32 uid, gboolean show_window); -void qq_request_buddy_info(PurpleConnection *gc, guint32 uid, - gint update_class, guint32 ship32); void qq_set_my_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img); void qq_set_buddy_icon_for_user(PurpleAccount *account, const gchar *who, const gchar *icon_num, const gchar *iconfile); void qq_prepare_modify_info(PurpleConnection *gc); @@ -83,6 +75,6 @@ void qq_process_get_info_reply(guint8 *data, gint data_len, PurpleConnection *gc); void qq_info_query_free(qq_data *qd); void qq_send_packet_get_level(PurpleConnection *gc, guint32 uid); -void qq_request_get_buddies_levels(PurpleConnection *gc, gint update_class); +void qq_send_packet_get_buddies_levels(PurpleConnection *gc); void qq_process_get_level_reply(guint8 *buf, gint buf_len, PurpleConnection *gc); #endif
--- a/libpurple/protocols/qq/buddy_list.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/buddy_list.c Mon Sep 15 03:04:07 2008 +0000 @@ -56,7 +56,7 @@ } qq_buddy_online; /* get a list of online_buddies */ -void qq_request_get_buddies_online(PurpleConnection *gc, guint8 position, gint update_class) +void qq_send_packet_get_buddies_online(PurpleConnection *gc, guint8 position) { qq_data *qd; guint8 *raw_data; @@ -77,14 +77,15 @@ /* 003-004 */ bytes += qq_put16(raw_data + bytes, 0x0000); - qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_ONLINE, raw_data, 5, update_class, 0); + qq_send_cmd(qd, QQ_CMD_GET_BUDDIES_ONLINE, raw_data, 5); qd->last_get_online = time(NULL); } -/* position starts with 0x0000, +/* position starts with 0x0000, * server may return a position tag if list is too long for one packet */ -void qq_request_get_buddies_list(PurpleConnection *gc, guint16 position, gint update_class) +void qq_send_packet_get_buddies_list(PurpleConnection *gc, guint16 position) { + qq_data *qd = (qq_data *) gc->proto_data; guint8 raw_data[16] = {0}; gint bytes = 0; @@ -97,12 +98,13 @@ * March 22, found the 00,00,00 starts to work as well */ bytes += qq_put8(raw_data + bytes, 0x00); - qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_LIST, raw_data, bytes, update_class, 0); + qq_send_cmd(qd, QQ_CMD_GET_BUDDIES_LIST, raw_data, bytes); } /* get all list, buddies & Quns with groupsid support */ -void qq_request_get_buddies_and_rooms(PurpleConnection *gc, guint32 position, gint update_class) +void qq_send_packet_get_buddies_and_rooms(PurpleConnection *gc, guint32 position) { + qq_data *qd = (qq_data *) gc->proto_data; guint8 raw_data[16] = {0}; gint bytes = 0; @@ -114,7 +116,7 @@ bytes += qq_put32(raw_data + bytes, 0x00000000); bytes += qq_put32(raw_data + bytes, position); - qq_send_cmd_mess(gc, QQ_CMD_GET_BUDDIES_AND_ROOMS, raw_data, bytes, update_class, 0); + qq_send_cmd(qd, QQ_CMD_GET_BUDDIES_AND_ROOMS, raw_data, bytes); } /* parse the data into qq_buddy_status */ @@ -144,8 +146,8 @@ /* 015-030: unknown key */ bytes += qq_getdata(&(bs->unknown_key[0]), QQ_KEY_LENGTH, data + bytes); - purple_debug_info("QQ_STATUS", - "uid: %d, U1: %d, ip: %s:%d, U2:%d, status:%d, U3:%04X\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ_STATUS", + "uid: %d, U1: %d, ip: %s:%d, U2:%d, status:%d, U3:%04X\n", bs->uid, bs->unknown1, inet_ntoa(bs->ip), bs->port, bs->unknown2, bs->status, bs->unknown3); @@ -178,12 +180,13 @@ count = 0; while (bytes < data_len) { if (data_len - bytes < QQ_ONLINE_BUDDY_ENTRY_LEN) { - purple_debug_error("QQ", "[buddies online] only %d, need %d", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "[buddies online] only %d, need %d", (data_len - bytes), QQ_ONLINE_BUDDY_ENTRY_LEN); break; } memset(&bo, 0 ,sizeof(bo)); - + /* set flag */ bytes_buddy = bytes; /* based on one online buddy entry */ @@ -201,29 +204,31 @@ bytes += qq_get8(&bo.ending, data + bytes); /* 0x00 */ if (bo.bs.uid == 0 || (bytes - bytes_buddy) != QQ_ONLINE_BUDDY_ENTRY_LEN) { - purple_debug_error("QQ", "uid=0 or entry complete len(%d) != %d", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "uid=0 or entry complete len(%d) != %d", (bytes - bytes_buddy), QQ_ONLINE_BUDDY_ENTRY_LEN); continue; } /* check if it is a valid entry */ if (bo.bs.uid == qd->uid) { - purple_debug_warning("QQ", "I am in online list %d\n", bo.bs.uid); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "I am in online list %d\n", bo.bs.uid); continue; } /* update buddy information */ purple_name = uid_to_purple_name(bo.bs.uid); if (purple_name == NULL) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Got an online buddy %d, but not find purple name\n", bo.bs.uid); continue; } b = purple_find_buddy(purple_connection_get_account(gc), purple_name); g_free(purple_name); - + q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; if (q_bud == NULL) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Got an online buddy %d, but not in my buddy list\n", bo.bs.uid); continue; } @@ -242,11 +247,11 @@ } if(bytes > data_len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n"); } - purple_debug_info("QQ", "Received %d online buddies, nextposition=%u\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d online buddies, nextposition=%u\n", count, (guint) position); return position; } @@ -269,7 +274,7 @@ qd = (qq_data *) gc->proto_data; if (data_len <= 2) { - purple_debug_error("QQ", "empty buddies list"); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "empty buddies list"); return -1; } /* qq_show_packet("QQ get buddies list", data, data_len); */ @@ -300,7 +305,7 @@ bytes_expected = 12 + pascal_len; if (q_bud->uid == 0 || (bytes - buddy_bytes) != bytes_expected) { - purple_debug_info("QQ", + purple_debug(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); @@ -310,7 +315,7 @@ } #if 1 - purple_debug_info("QQ", + purple_debug(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); #endif @@ -329,11 +334,11 @@ } if(bytes > data_len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "qq_process_get_buddies_list_reply: Dangerous error! maybe protocol changed, notify developers!"); } - purple_debug_info("QQ", "Received %d buddies, nextposition=%u\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies, nextposition=%u\n", count, (guint) position); return position; } @@ -359,7 +364,8 @@ 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(PURPLE_DEBUG_WARNING, "QQ", + "qq_process_get_buddies_and_rooms, %d", reply_code); } bytes += qq_get32(&unknown, data + bytes); @@ -375,45 +381,48 @@ /* 05: groupid*4 */ /* seems to always be 0 */ bytes += qq_get8(&groupid, data + bytes); /* - purple_debug_info("QQ", "groupid: %i\n", groupid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "groupid: %i\n", groupid); groupid >>= 2; */ if (uid == 0 || (type != 0x1 && type != 0x4)) { - purple_debug_info("QQ", "Buddy entry, uid=%d, type=%d", uid, type); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "Buddy entry, uid=%d, type=%d", uid, type); continue; - } + } if(0x1 == type) { /* a buddy */ - /* don't do anything but count - buddies are handled by - * qq_request_get_buddies_list */ + /* don't do anything but count - buddies are handled by + * qq_send_packet_get_buddies_list */ ++i; } else { /* a group */ group = qq_room_search_id(gc, uid); if(group == NULL) { - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Not find room id %d in qq_process_get_buddies_and_rooms\n", uid); qq_set_pending_id(&qd->adding_groups_from_server, uid, TRUE); + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, uid); } else { - group->my_role = QQ_ROOM_ROLE_YES; + group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER; qq_group_refresh(gc, group); + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id); } ++j; } } if(bytes > data_len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "qq_process_get_buddies_and_rooms: Dangerous error! maybe protocol changed, notify developers!"); } - purple_debug_info("QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Received %d buddies and %d groups, nextposition=%u\n", i, j, (guint) position); return position; } #define QQ_MISC_STATUS_HAVING_VIIDEO 0x00000001 #define QQ_CHANGE_ONLINE_STATUS_REPLY_OK 0x30 /* ASCII value of "0" */ -/* TODO: figure out what's going on with the IP region. Sometimes I get valid IP addresses, - * but the port number's weird, other times I get 0s. I get these simultaneously on the same buddy, +/* TODO: figure out what's going on with the IP region. Sometimes I get valid IP addresses, + * but the port number's weird, other times I get 0s. I get these simultaneously on the same buddy, * using different accounts to get info. */ /* check if status means online or offline */ @@ -432,9 +441,9 @@ /* Help calculate the correct icon index to tell the server. */ gint get_icon_offset(PurpleConnection *gc) -{ +{ PurpleAccount *account; - PurplePresence *presence; + PurplePresence *presence; account = purple_connection_get_account(gc); presence = purple_account_get_presence(account); @@ -451,7 +460,7 @@ } /* send a packet to change my online status */ -void qq_request_change_status(PurpleConnection *gc, gint update_class) +void qq_send_packet_change_status(PurpleConnection *gc) { qq_data *qd; guint8 raw_data[16] = {0}; @@ -460,13 +469,13 @@ guint32 misc_status; gboolean fake_video; PurpleAccount *account; - PurplePresence *presence; + PurplePresence *presence; account = purple_connection_get_account(gc); presence = purple_account_get_presence(account); qd = (qq_data *) gc->proto_data; - if (!qd->is_login) + if (!qd->logged_in) return; if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { @@ -488,7 +497,7 @@ bytes += qq_put8(raw_data + bytes, away_cmd); bytes += qq_put32(raw_data + bytes, misc_status); - qq_send_cmd_mess(gc, QQ_CMD_CHANGE_STATUS, raw_data, bytes, update_class, 0); + qq_send_cmd(qd, QQ_CMD_CHANGE_ONLINE_STATUS, raw_data, bytes); } /* parse the reply packet for change_status */ @@ -504,15 +513,15 @@ g_return_if_fail(data != NULL && data_len != 0); qd = (qq_data *) gc->proto_data; - + bytes = 0; bytes = qq_get8(&reply, data + bytes); if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) { - purple_debug_warning("QQ", "Change status fail 0x%02X\n", reply); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Change status fail 0x%02X\n", reply); return; } - /* purple_debug_info("QQ", "Change status OK\n"); */ + /* purple_debug(PURPLE_DEBUG_INFO, "QQ", "Change status OK\n"); */ name = uid_to_purple_name(qd->uid); b = purple_find_buddy(gc->account, name); g_free(name); @@ -523,7 +532,7 @@ } /* it is a server message indicating that one of my buddies has changed its status */ -void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc) +void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; gint bytes; @@ -538,16 +547,16 @@ qd = (qq_data *) gc->proto_data; if (data_len < 35) { - purple_debug_error("QQ", "[buddy status change] only %d, need 35 bytes\n", data_len); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "[buddy status change] only %d, need 35 bytes\n", data_len); return; } - + memset(&bs, 0, sizeof(bs)); bytes = 0; /* 000-030: qq_buddy_status */ bytes += get_buddy_status(&bs, data + bytes); - /* 031-034: Unknow, maybe my uid */ - /* This has a value of 0 when we've changed our status to + /* 031-034: Unknow, maybe my uid */ + /* This has a value of 0 when we've changed our status to * QQ_BUDDY_ONLINE_INVISIBLE */ bytes += qq_get32(&my_uid, data + bytes); @@ -556,13 +565,13 @@ g_free(name); q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; if (q_bud == NULL) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "got information of unknown buddy %d\n", bs.uid); return; } - purple_debug_info("QQ", "status:.uid = %d, q_bud->uid = %d\n", bs.uid , q_bud->uid); - if(bs.ip.s_addr != 0) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "status:.uid = %d, q_bud->uid = %d\n", bs.uid , q_bud->uid); + if(bs.ip.s_addr != 0) { q_bud->ip.s_addr = bs.ip.s_addr; q_bud->port = bs.port; } @@ -580,24 +589,24 @@ gchar *purple_name; PurpleBuddy *bud; gchar *status_id; - + g_return_if_fail(q_bud != NULL); purple_name = uid_to_purple_name(q_bud->uid); if (purple_name == NULL) { - purple_debug_error("QQ", "Not find purple name: %d\n", q_bud->uid); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Not find purple name: %d\n", q_bud->uid); return; } bud = purple_find_buddy(gc->account, purple_name); if (bud == NULL) { - purple_debug_error("QQ", "Not find buddy: %d\n", q_bud->uid); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Not find buddy: %d\n", q_bud->uid); g_free(purple_name); return; } - + purple_blist_server_alias_buddy(bud, q_bud->nickname); /* server */ - q_bud->last_update = time(NULL); + q_bud->last_refresh = time(NULL); /* purple supports signon and idle time * but it is not much use for QQ, I do not use them */ @@ -621,10 +630,10 @@ break; default: status_id = "invisible"; - purple_debug_error("QQ", "unknown status: %x\n", q_bud->status); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "unknown status: %x\n", q_bud->status); break; } - purple_debug_info("QQ", "buddy %d %s\n", q_bud->uid, status_id); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "buddy %d %s\n", q_bud->uid, status_id); purple_prpl_got_user_status(gc->account, purple_name, status_id, NULL); if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE && q_bud->status != QQ_BUDDY_OFFLINE) @@ -655,7 +664,7 @@ while (list != NULL) { q_bud = (qq_buddy *) list->data; - if (q_bud != NULL && now > q_bud->last_update + QQ_UPDATE_ONLINE_INTERVAL + if (q_bud != NULL && now > q_bud->last_refresh + QQ_UPDATE_ONLINE_INTERVAL && q_bud->status != QQ_BUDDY_ONLINE_INVISIBLE) { q_bud->status = QQ_BUDDY_ONLINE_OFFLINE; qq_update_buddy_contact(gc, q_bud);
--- a/libpurple/protocols/qq/buddy_list.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/buddy_list.h Mon Sep 15 03:04:07 2008 +0000 @@ -42,19 +42,19 @@ enum { QQ_BUDDY_OFFLINE = 0x00, - QQ_BUDDY_ONLINE_NORMAL = 10, - QQ_BUDDY_ONLINE_OFFLINE = 20, - QQ_BUDDY_ONLINE_AWAY = 30, - QQ_BUDDY_ONLINE_INVISIBLE = 40 + QQ_BUDDY_ONLINE_NORMAL = 0x0a, + QQ_BUDDY_ONLINE_OFFLINE = 0x14, + QQ_BUDDY_ONLINE_AWAY = 0x1e, + QQ_BUDDY_ONLINE_INVISIBLE = 0x28 }; -void qq_request_get_buddies_online(PurpleConnection *gc, guint8 position, gint update_class); +void qq_send_packet_get_buddies_online(PurpleConnection *gc, guint8 position); guint8 qq_process_get_buddies_online_reply(guint8 *data, gint data_len, PurpleConnection *gc); -void qq_request_get_buddies_list(PurpleConnection *gc, guint16 position, gint update_class); +void qq_send_packet_get_buddies_list(PurpleConnection *gc, guint16 position); guint16 qq_process_get_buddies_list_reply(guint8 *data, gint data_len, PurpleConnection *gc); -void qq_request_get_buddies_and_rooms(PurpleConnection *gc, guint32 position, gint update_class); +void qq_send_packet_get_buddies_and_rooms(PurpleConnection *gc, guint32 position); guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConnection *gc); void qq_refresh_all_buddy_status(PurpleConnection *gc); @@ -63,7 +63,7 @@ gint get_icon_offset(PurpleConnection *gc); -void qq_request_change_status(PurpleConnection *gc, gint update_class); +void qq_send_packet_change_status(PurpleConnection *gc); void qq_process_change_status_reply(guint8 *data, gint data_len, PurpleConnection *gc); void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc);
--- a/libpurple/protocols/qq/buddy_opt.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/buddy_opt.c Mon Sep 15 03:04:07 2008 +0000 @@ -60,17 +60,19 @@ /* send packet to remove a buddy from my buddy list */ static void _qq_send_packet_remove_buddy(PurpleConnection *gc, guint32 uid) { + qq_data *qd = (qq_data *) gc->proto_data; gchar uid_str[11]; g_return_if_fail(uid > 0); g_snprintf(uid_str, sizeof(uid_str), "%d", uid); - qq_send_cmd(gc, QQ_CMD_DEL_BUDDY, (guint8 *) uid_str, strlen(uid_str)); + qq_send_cmd(qd, QQ_CMD_DEL_BUDDY, (guint8 *) uid_str, strlen(uid_str)); } /* try to remove myself from someone's buddy list */ static void _qq_send_packet_remove_self_from(PurpleConnection *gc, guint32 uid) { + qq_data *qd = (qq_data *) gc->proto_data; guint8 raw_data[16] = {0}; gint bytes = 0; @@ -78,7 +80,7 @@ bytes += qq_put32(raw_data + bytes, uid); - qq_send_cmd(gc, QQ_CMD_REMOVE_SELF, raw_data, bytes); + qq_send_cmd(qd, QQ_CMD_REMOVE_SELF, raw_data, bytes); } /* try to add a buddy without authentication */ @@ -92,7 +94,7 @@ /* we need to send the ascii code of this uid to qq server */ g_snprintf(uid_str, sizeof(uid_str), "%d", uid); - qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_WO_AUTH, (guint8 *) uid_str, strlen(uid_str)); + qq_send_cmd(qd, QQ_CMD_ADD_BUDDY_WO_AUTH, (guint8 *) uid_str, strlen(uid_str)); /* must be set after sending packet to get the correct send_seq */ req = g_new0(qq_add_buddy_request, 1); @@ -104,6 +106,7 @@ /* this buddy needs authentication, text conversion is done at lowest level */ static void _qq_send_packet_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text) { + qq_data *qd = (qq_data *) gc->proto_data; gchar *text_qq, uid_str[11]; guint8 bar, *raw_data; gint bytes = 0; @@ -125,7 +128,7 @@ g_free(text_qq); } - qq_send_cmd(gc, QQ_CMD_BUDDY_AUTH, raw_data, bytes); + qq_send_cmd(qd, QQ_CMD_BUDDY_AUTH, raw_data, bytes); } static void _qq_send_packet_add_buddy_auth_with_gc_and_uid(gc_and_uid *g, const gchar *text) @@ -201,11 +204,11 @@ g2->uid = uid; msg1 = g_strdup_printf(_("You rejected %d's request"), uid); - msg2 = g_strdup(_("Message:")); + msg2 = g_strdup(_("Input your reason:")); nombre = uid_to_purple_name(uid); purple_request_input(gc, _("Reject request"), msg1, msg2, - _("Sorry, you are not my style..."), TRUE, FALSE, + _("Sorry, you are not my type..."), TRUE, FALSE, NULL, _("Reject"), G_CALLBACK(_qq_reject_add_request_real), _("Cancel"), NULL, purple_connection_get_account(gc), nombre, NULL, g2); @@ -258,7 +261,7 @@ qd = (qq_data *) gc->proto_data; if (data[0] != QQ_ADD_BUDDY_AUTH_REPLY_OK) { - purple_debug_warning("QQ", "Add buddy with auth request failed\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy with auth request failed\n"); if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) { return; } @@ -266,7 +269,7 @@ purple_notify_error(gc, NULL, _("Add buddy with auth request failed"), msg_utf8); g_free(msg_utf8); } else { - purple_debug_info("QQ", "Add buddy with auth request OK\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Add buddy with auth request OK\n"); } } @@ -281,16 +284,16 @@ if (data[0] != QQ_REMOVE_BUDDY_REPLY_OK) { /* there is no reason return from server */ - purple_debug_warning("QQ", "Remove buddy fails\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove buddy fails\n"); } else { /* if reply */ - purple_debug_info("QQ", "Remove buddy OK\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove buddy OK\n"); /* TODO: We don't really need to notify the user about this, do we? */ purple_notify_info(gc, NULL, _("You have successfully removed a buddy"), NULL); } } /* process the server reply for my request to remove myself from a buddy */ -void qq_process_remove_self_reply(guint8 *data, gint data_len, PurpleConnection *gc) +void qq_process_remove_self_reply(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; @@ -300,12 +303,11 @@ if (data[0] != QQ_REMOVE_SELF_REPLY_OK) { /* there is no reason return from server */ - purple_debug_warning("QQ", "Remove self fails\n"); - purple_notify_info(gc, NULL, _("Failed removing from friend's buddy list"), NULL); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Remove self fails\n"); } else { /* if reply */ - purple_debug_info("QQ", "Remove from a buddy OK\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Remove self from a buddy OK\n"); /* TODO: Does the user really need to be notified about this? */ - purple_notify_info(gc, NULL, _("Successed removing from friend's buddy list"), NULL); + purple_notify_info(gc, NULL, _("You have successfully removed yourself from your friend's buddy list"), NULL); } } @@ -338,25 +340,25 @@ } if (for_uid == 0) { /* we have no record for this */ - purple_debug_error("QQ", "We have no record for add buddy reply [%d], discard\n", seq); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "We have no record for add buddy reply [%d], discard\n", seq); return; } else { - purple_debug_info("QQ", "Add buddy reply [%d] is for id [%d]\n", seq, for_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Add buddy reply [%d] is for id [%d]\n", seq, for_uid); } if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) return; - + uid = segments[0]; reply = segments[1]; if (strtol(uid, NULL, 10) != qd->uid) { /* should not happen */ - purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", uid); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Add buddy reply is to [%s], not me!", uid); g_strfreev(segments); return; } if (strtol(reply, NULL, 10) > 0) { /* need auth */ - purple_debug_warning("QQ", "Add buddy attempt fails, need authentication\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add buddy attempt fails, need authentication\n"); nombre = uid_to_purple_name(for_uid); b = purple_find_buddy(gc->account, nombre); if (b != NULL) @@ -364,7 +366,7 @@ g = g_new0(gc_and_uid, 1); g->gc = gc; g->uid = for_uid; - msg = g_strdup_printf(_("%d needs authentication"), for_uid); + msg = g_strdup_printf(_("User %d needs authentication"), for_uid); purple_request_input(gc, NULL, msg, _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */ _("Would you be my friend?"), @@ -395,7 +397,7 @@ if (g == NULL) { g = purple_group_new(group_name); purple_blist_add_group(g, NULL); - purple_debug_warning("QQ", "Add new group: %s\n", group_name); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add new group: %s\n", group_name); } return g; @@ -438,11 +440,11 @@ b->proto_data = q_bud; qd->buddies = g_list_append(qd->buddies, q_bud); qq_send_packet_get_info(gc, q_bud->uid, FALSE); - qq_request_get_buddies_online(gc, 0, 0); + qq_send_packet_get_buddies_online(gc, 0); } purple_blist_add_buddy(b, NULL, g, NULL); - purple_debug_warning("QQ", "Add new buddy: [%s]\n", name); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Add new buddy: [%s]\n", name); g_free(name); g_free(group_name); @@ -452,8 +454,8 @@ /* add a buddy and send packet to QQ server * note that when purple load local cached buddy list into its blist - * it also calls this funtion, so we have to - * define qd->is_login=TRUE AFTER serv_finish_login(gc) */ + * it also calls this funtion, so we have to + * define qd->logged_in=TRUE AFTER serv_finish_login(gc) */ void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { qq_data *qd; @@ -461,7 +463,7 @@ PurpleBuddy *b; qd = (qq_data *) gc->proto_data; - if (!qd->is_login) + if (!qd->logged_in) return; /* IMPORTANT ! */ uid = purple_name_to_uid(buddy->name); @@ -472,8 +474,8 @@ if (b != NULL) purple_blist_remove_buddy(b); purple_notify_error(gc, NULL, - _("QQ Number Error"), - _("Invalid QQ Number")); + _("QQid Error"), + _("Invalid QQid")); } } @@ -488,7 +490,7 @@ qd = (qq_data *) gc->proto_data; uid = purple_name_to_uid(buddy->name); - if (!qd->is_login) + if (!qd->logged_in) return; if (uid > 0) @@ -500,7 +502,7 @@ if (q_bud != NULL) qd->buddies = g_list_remove(qd->buddies, q_bud); else - purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "We have no qq_buddy record for %s\n", buddy->name); /* remove buddy on blist, this does not trigger qq_remove_buddy again * do this only if the request comes from block request, * otherwise purple segmentation fault */ @@ -512,45 +514,41 @@ /* free add buddy request queue */ void qq_add_buddy_request_free(qq_data *qd) { - gint count; + gint i; qq_add_buddy_request *p; - count = 0; - while (qd->add_buddy_request != NULL) { + i = 0; + while (qd->add_buddy_request) { p = (qq_add_buddy_request *) (qd->add_buddy_request->data); qd->add_buddy_request = g_list_remove(qd->add_buddy_request, p); g_free(p); - count++; + i++; } - if (count > 0) { - purple_debug_info("QQ", "%d add buddy requests are freed!\n", count); - } + purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d add buddy requests are freed!\n", i); } /* free up all qq_buddy */ void qq_buddies_list_free(PurpleAccount *account, qq_data *qd) { - gint count; + gint i; qq_buddy *p; gchar *name; PurpleBuddy *b; - count = 0; + i = 0; while (qd->buddies) { p = (qq_buddy *) (qd->buddies->data); qd->buddies = g_list_remove(qd->buddies, p); name = uid_to_purple_name(p->uid); - b = purple_find_buddy(account, name); - if(b != NULL) + b = purple_find_buddy(account, name); + if(b != NULL) b->proto_data = NULL; else - purple_debug_info("QQ", "qq_buddy %s not found in purple proto_data\n", name); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "qq_buddy %s not found in purple proto_data\n", name); g_free(name); g_free(p); - count++; + i++; } - if (count > 0) { - purple_debug_info("QQ", "%d qq_buddy structures are freed!\n", count); - } + purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d qq_buddy structures are freed!\n", i); }
--- a/libpurple/protocols/qq/char_conv.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/char_conv.c Mon Sep 15 03:04:07 2008 +0000 @@ -113,7 +113,7 @@ } /* conversion error */ - purple_debug_error("QQ_CONVERT", "%s\n", error->message); + purple_debug(PURPLE_DEBUG_ERROR, "QQ_CONVERT", "%s\n", error->message); qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ_CONVERT", (guint8 *) str, (len == -1) ? strlen(str) : len, @@ -182,7 +182,7 @@ g_string_append_printf(encoded, "<font color=\"%s\"><font face=\"%s\"><font size=\"%d\">", color_code, font_name, font_size / 3); - purple_debug_info("QQ_MESG", + purple_debug(PURPLE_DEBUG_INFO, "QQ_MESG", "recv <font color=\"%s\"><font face=\"%s\"><font size=\"%d\">\n", color_code, font_name, font_size / 3); g_string_append(encoded, msg_utf8);
--- a/libpurple/protocols/qq/file_trans.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/file_trans.c Mon Sep 15 03:04:07 2008 +0000 @@ -22,6 +22,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#ifdef _WIN32 +#define random rand +#endif + #include "internal.h" #include "debug.h" @@ -58,7 +62,7 @@ { guint8 seed; - seed = rand() & 0xFF; + seed = random(); return _get_file_key(seed); } @@ -257,7 +261,7 @@ if (bytes == len + 12) { _qq_xfer_write(raw_data, bytes, qd->xfer); } else - purple_debug_info("QQ", "send_file: want %d but got %d\n", len + 12, bytes); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "send_file: want %d but got %d\n", len + 12, bytes); return bytes; } @@ -319,13 +323,13 @@ bytes_expected = 61; break; default: - purple_debug_info("QQ", "qq_send_file_ctl_packet: Unknown packet type[%d]\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "qq_send_file_ctl_packet: Unknown packet type[%d]\n", packet_type); bytes_expected = 0; } if (bytes != bytes_expected) { - purple_debug_error("QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d", bytes_expected, bytes); return; } @@ -342,24 +346,24 @@ guint8 *buf; int buflen; hex_dump = hex_dump_to_str(encrypted_data, encrypted_len); - purple_debug_info("QQ", "encrypted packet: \n%s", hex_dump); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "encrypted packet: \n%s", hex_dump); g_free(hex_dump); buf = g_newa(guint8, MAX_PACKET_SIZE); buflen = encrypted_len; if (qq_crypt(DECRYPT, encrypted_data, encrypted_len, info->file_session_key, buf, &buflen)) { - purple_debug_info("QQ", "decrypt success\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypt success\n"); if (buflen == bytes && memcmp(raw_data, buf, buflen) == 0) - purple_debug_info("QQ", "checksum ok\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "checksum ok\n"); hex_dump = hex_dump_to_str(buf, buflen); - purple_debug_info("QQ", "decrypted packet: \n%s", hex_dump); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypted packet: \n%s", hex_dump); g_free(hex_dump); } else { - purple_debug_info("QQ", "decrypt fail\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "decrypt fail\n"); } #endif - purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type)); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type)); _qq_send_file(gc, encrypted_data, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid); } @@ -406,7 +410,7 @@ info->fragment_num = (filesize - 1) / QQ_FILE_FRAGMENT_MAXLEN + 1; info->fragment_len = QQ_FILE_FRAGMENT_MAXLEN; - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "start transfering data, %d fragments with %d length each\n", info->fragment_num, info->fragment_len); /* Unknown */ @@ -431,7 +435,7 @@ filename_len); break; case QQ_FILE_DATA_INFO: - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "sending %dth fragment with length %d, offset %d\n", fragment_index, len, (fragment_index-1)*fragment_size); /* bytes += qq_put16(raw_data + bytes, ++(qd->send_seq)); */ @@ -444,7 +448,7 @@ bytes += qq_putdata(raw_data + bytes, data, len); break; case QQ_FILE_EOF: - purple_debug_info("QQ", "end of sending data\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "end of sending data\n"); /* bytes += qq_put16(raw_data + bytes, info->fragment_num + 1); */ bytes += qq_put16(raw_data + bytes, info->fragment_num); bytes += qq_put8(raw_data + bytes, sub_type); @@ -470,7 +474,7 @@ break; } } - purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type)); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type)); _qq_send_file(gc, raw_data, bytes, QQ_FILE_DATA_PACKET_TAG, info->to_uid); } @@ -512,7 +516,7 @@ decrypted_data = g_newa(guint8, data_len); decrypted_len = qq_decrypt(decrypted_data, data, data_len, qd->session_md5); if ( decrypted_len <= 0 ) { - purple_debug_error("QQ", "Error decrypt rcv file ctrl packet\n"); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Error decrypt rcv file ctrl packet\n"); return; } @@ -522,7 +526,7 @@ decryped_bytes += qq_get16(&seq, decrypted_data + decryped_bytes); decryped_bytes += 4+1+1+19+1; /* skip something */ - purple_debug_info("QQ", "==> [%d] receive %s packet\n", seq, qq_get_file_cmd_desc(packet_type)); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "==> [%d] receive %s packet\n", seq, qq_get_file_cmd_desc(packet_type)); qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", decrypted_data, decrypted_len, "decrypted control packet received:"); @@ -562,7 +566,7 @@ qq_send_file_ctl_packet(gc, QQ_FILE_CMD_SENDER_SAY_HELLO, fh.sender_uid, 0); break; default: - purple_debug_info("QQ", "unprocess file command %d\n", packet_type); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "unprocess file command %d\n", packet_type); } } @@ -573,7 +577,7 @@ ft_info *info = (ft_info *) xfer->data; guint32 mask; - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "receiving %dth fragment with length %d, slide window status %o, max_fragment_index %d\n", index, len, info->window, info->max_fragment_index); if (info->window == 0 && info->max_fragment_index == 0) { @@ -581,11 +585,11 @@ purple_xfer_cancel_local(xfer); return; } - purple_debug_info("QQ", "object file opened for writing\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "object file opened for writing\n"); } mask = 0x1 << (index % sizeof(info->window)); if (index < info->max_fragment_index || (info->window & mask)) { - purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", index+1); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "duplicate %dth fragment, drop it!\n", index+1); return; } @@ -605,7 +609,7 @@ if (mask & 0x8000) mask = 0x0001; else mask = mask << 1; } - purple_debug_info("QQ", "procceed %dth fragment, slide window status %o, max_fragment_index %d\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "procceed %dth fragment, slide window status %o, max_fragment_index %d\n", index, info->window, info->max_fragment_index); } @@ -650,12 +654,12 @@ PurpleXfer *xfer = qd->xfer; ft_info *info = (ft_info *) xfer->data; - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "receiving %dth fragment ack, slide window status %o, max_fragment_index %d\n", fragment_index, info->window, info->max_fragment_index); if (fragment_index < info->max_fragment_index || fragment_index >= info->max_fragment_index + sizeof(info->window)) { - purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1); return; } mask = 0x1 << (fragment_index % sizeof(info->window)); @@ -692,7 +696,7 @@ else mask = mask << 1; } } - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "procceed %dth fragment ack, slide window status %o, max_fragment_index %d\n", fragment_index, info->window, info->max_fragment_index); } @@ -733,7 +737,7 @@ info->max_fragment_index = 0; info->window = 0; - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "start receiving data, %d fragments with %d length each\n", info->fragment_num, info->fragment_len); _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, @@ -743,7 +747,7 @@ bytes += qq_get32(&fragment_index, data + bytes); bytes += qq_get32(&fragment_offset, data + bytes); bytes += qq_get16(&fragment_len, data + bytes); - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "received %dth fragment with length %d, offset %d\n", fragment_index, fragment_len, fragment_offset); @@ -752,7 +756,7 @@ _qq_recv_file_progess(gc, data + bytes, fragment_len, fragment_index, fragment_offset); break; case QQ_FILE_EOF: - purple_debug_info("QQ", "end of receiving\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "end of receiving\n"); _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, 0, 0, NULL, 0); break; @@ -791,11 +795,11 @@ purple_xfer_end(qd->xfer); break; case QQ_FILE_BASIC_INFO: - purple_debug_info("QQ", "here\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "here\n"); _qq_send_file_data_packet(gc, QQ_FILE_DATA_INFO, 0, 0, 0, NULL, 0); break; default: - purple_debug_info("QQ", "_qq_process_recv_file_data: unknown packet type [%d]\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "_qq_process_recv_file_data: unknown packet type [%d]\n", packet_type); break; } @@ -820,6 +824,6 @@ _qq_process_recv_file_data(gc, data + bytes, len - bytes); break; default: - purple_debug_info("QQ", "unknown packet tag"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "unknown packet tag"); } }
--- a/libpurple/protocols/qq/group.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group.c Mon Sep 15 03:04:07 2008 +0000 @@ -64,7 +64,7 @@ pce = g_new0(struct proto_chat_entry, 1); pce->label = _("ID: "); - pce->identifier = QQ_ROOM_KEY_EXTERNAL_ID; + pce->identifier = QQ_GROUP_KEY_EXTERNAL_ID; m = g_list_append(m, pce); return m; @@ -77,7 +77,7 @@ defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); if (chat_name != NULL) - g_hash_table_insert(defaults, QQ_ROOM_KEY_EXTERNAL_ID, g_strdup(chat_name)); + g_hash_table_insert(defaults, QQ_GROUP_KEY_EXTERNAL_ID, g_strdup(chat_name)); return defaults; } @@ -96,30 +96,30 @@ rl = purple_roomlist_new(purple_connection_get_account(gc)); qd->roomlist = rl; - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Group ID"), QQ_ROOM_KEY_EXTERNAL_ID, FALSE); + f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Group ID"), QQ_GROUP_KEY_EXTERNAL_ID, FALSE); fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Creator"), QQ_ROOM_KEY_CREATOR_UID, FALSE); + f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Creator"), QQ_GROUP_KEY_CREATOR_UID, FALSE); fields = g_list_append(fields, f); f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, - _("Group Description"), QQ_ROOM_KEY_DESC_UTF8, FALSE); + _("Group Description"), QQ_GROUP_KEY_GROUP_DESC_UTF8, FALSE); fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_ROOM_KEY_INTERNAL_ID, TRUE); + f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_GROUP_KEY_INTERNAL_ID, TRUE); fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_ROOM_KEY_TYPE, TRUE); + f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_GROUP_KEY_TYPE, TRUE); fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Auth"), QQ_ROOM_KEY_AUTH_TYPE, TRUE); + f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, _("Auth"), QQ_GROUP_KEY_AUTH_TYPE, TRUE); fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_ROOM_KEY_CATEGORY, TRUE); + f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_GROUP_KEY_GROUP_CATEGORY, TRUE); fields = g_list_append(fields, f); - f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_ROOM_KEY_TITLE_UTF8, TRUE); + f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", QQ_GROUP_KEY_GROUP_NAME_UTF8, TRUE); fields = g_list_append(fields, f); purple_roomlist_set_fields(rl, fields); purple_roomlist_set_in_progress(qd->roomlist, TRUE); purple_request_input(gc, _("QQ Qun"), - _("Please enter Qun number"), - _("You can only search for permanent Qun\n"), + _("Please enter external group ID"), + _("You can only search for permanent QQ groups\n"), NULL, FALSE, FALSE, NULL, _("Search"), G_CALLBACK(_qq_group_search_callback), _("Cancel"), G_CALLBACK(_qq_group_search_cancel_callback), @@ -157,7 +157,7 @@ purple_group = purple_find_group(PURPLE_GROUP_QQ_QUN); if (purple_group == NULL) { - purple_debug_info("QQ", "We have no QQ Qun\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "We have no QQ Qun\n"); return; } @@ -178,7 +178,8 @@ continue; count++; + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id); } - purple_debug_info("QQ", "Load %d QQ Qun configurations\n", count); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Load %d QQ Qun configurations\n", count); }
--- a/libpurple/protocols/qq/group.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group.h Mon Sep 15 03:04:07 2008 +0000 @@ -34,27 +34,27 @@ #define PURPLE_GROUP_QQ_QUN "QQ 群" typedef enum { - QQ_ROOM_ROLE_NO = 0x00, /* default 0x00 means not member */ - QQ_ROOM_ROLE_YES, - QQ_ROOM_ROLE_REQUESTING, - QQ_ROOM_ROLE_ADMIN, -} qq_room_role; + QQ_GROUP_MEMBER_STATUS_NOT_MEMBER = 0x00, /* default 0x00 means not member */ + QQ_GROUP_MEMBER_STATUS_IS_MEMBER, + QQ_GROUP_MEMBER_STATUS_APPLYING, + QQ_GROUP_MEMBER_STATUS_IS_ADMIN, +} qq_group_member_status; typedef struct _qq_group { /* all these will be saved when we exit Purple */ - qq_room_role my_role; /* my role for this room */ - gchar *my_role_desc; /* my role description */ + qq_group_member_status my_status; /* my status for this group */ + gchar *my_status_desc; /* my status description */ guint32 id; guint32 ext_id; guint8 type8; /* permanent or temporory */ guint32 creator_uid; - guint32 category; + guint32 group_category; guint8 auth_type; - gchar *title_utf8; - gchar *desc_utf8; + gchar *group_name_utf8; + gchar *group_desc_utf8; /* all these will be loaded from the network */ gchar *notice_utf8; /* group notice by admin */ - GList *members; + GList *members; } qq_group; GList *qq_chat_info(PurpleConnection *gc);
--- a/libpurple/protocols/qq/group_conv.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_conv.c Mon Sep 15 03:04:07 2008 +0000 @@ -41,9 +41,9 @@ qd = (qq_data *) gc->proto_data; conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - group->title_utf8, purple_connection_get_account(gc)); + group->group_name_utf8, purple_connection_get_account(gc)); if (conv == NULL) /* show only one window per group */ - serv_got_joined_chat(gc, qd->channel++, group->title_utf8); + serv_got_joined_chat(gc, qd->channel++, group->group_name_utf8); } /* refresh online member in group conversation window */ @@ -59,7 +59,7 @@ names = NULL; flags = NULL; conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - group->title_utf8, purple_connection_get_account(gc)); + group->group_name_utf8, purple_connection_get_account(gc)); if (conv != NULL && group->members != NULL) { list = group->members; while (list != NULL) {
--- a/libpurple/protocols/qq/group_find.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_find.c Mon Sep 15 03:04:07 2008 +0000 @@ -110,10 +110,10 @@ group = NULL; while (list != NULL) { group = (qq_group *) list->data; - if (group->title_utf8 == NULL) { + if (group->group_name_utf8 == NULL) { continue; } - if (!g_ascii_strcasecmp(purple_conversation_get_name(conv), group->title_utf8)) + if (!g_ascii_strcasecmp(purple_conversation_get_name(conv), group->group_name_utf8)) break; list = list->next; } @@ -167,83 +167,3 @@ return NULL; } - -qq_group *qq_room_get_next(PurpleConnection *gc, guint32 room_id) -{ - GList *list; - qq_group *group; - qq_data *qd; - gboolean is_find = FALSE; - - qd = (qq_data *) gc->proto_data; - - if (qd->groups == NULL) { - return NULL; - } - - if (room_id <= 0) { - return (qq_group *) qd->groups->data; - } - - list = qd->groups; - while (list != NULL) { - group = (qq_group *) list->data; - list = list->next; - if (group->id == room_id) { - is_find = TRUE; - break; - } - } - - if ( !is_find || list == NULL) { - return NULL; - } - - return (qq_group *)list->data; -} - -qq_group *qq_room_get_next_conv(PurpleConnection *gc, guint32 room_id) -{ - GList *list; - qq_group *group; - qq_data *qd; - gboolean is_find; - - qd = (qq_data *) gc->proto_data; - - list = qd->groups; - if (room_id > 0) { - /* search next room */ - is_find = FALSE; - while (list != NULL) { - group = (qq_group *) list->data; - list = list->next; - if (group->id == room_id) { - is_find = TRUE; - break; - } - } - if ( !is_find || list == NULL) { - return NULL; - } - } - - is_find = FALSE; - while (list != NULL) { - group = (qq_group *) list->data; - if (group->my_role == QQ_ROOM_ROLE_YES || group->my_role == QQ_ROOM_ROLE_ADMIN) { - if (NULL != purple_find_conversation_with_account( - PURPLE_CONV_TYPE_CHAT,group->title_utf8, purple_connection_get_account(gc))) { - /* In convseration*/ - is_find = TRUE; - break; - } - } - list = list->next; - } - - if ( !is_find) { - return NULL; - } - return group; -}
--- a/libpurple/protocols/qq/group_find.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_find.h Mon Sep 15 03:04:07 2008 +0000 @@ -32,12 +32,10 @@ qq_buddy *qq_group_find_member_by_uid(qq_group *group, guint32 uid); void qq_group_remove_member_by_uid(qq_group *group, guint32 uid); qq_buddy *qq_group_find_or_add_member(PurpleConnection *gc, qq_group *group, guint32 member_uid); +gboolean qq_group_find_id_by_seq(PurpleConnection *gc, guint16 seq, guint32 *id); qq_group *qq_group_find_by_channel(PurpleConnection *gc, gint channel); qq_group *qq_room_search_ext_id(PurpleConnection *gc, guint32 ext_id); qq_group *qq_room_search_id(PurpleConnection *gc, guint32 room_id); -qq_group *qq_room_get_next(PurpleConnection *gc, guint32 room_id); -qq_group *qq_room_get_next_conv(PurpleConnection *gc, guint32 room_id); - #endif
--- a/libpurple/protocols/qq/group_free.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_free.c Mon Sep 15 03:04:07 2008 +0000 @@ -54,9 +54,9 @@ { g_return_if_fail(group != NULL); qq_group_free_member(group); - g_free(group->my_role_desc); - g_free(group->title_utf8); - g_free(group->desc_utf8); + g_free(group->my_status_desc); + g_free(group->group_name_utf8); + g_free(group->group_desc_utf8); g_free(group->notice_utf8); g_free(group); } @@ -64,18 +64,16 @@ void qq_group_free_all(qq_data *qd) { qq_group *group; - gint count; - + gint i; g_return_if_fail(qd != NULL); - count = 0; + + i = 0; while (qd->groups != NULL) { + i++; group = (qq_group *) qd->groups->data; qd->groups = g_list_remove(qd->groups, group); qq_group_free(group); - count++; } - if (count > 0) { - purple_debug_info("QQ", "%d rooms are freed\n", count); - } + purple_debug(PURPLE_DEBUG_INFO, "QQ", "%d groups are freed\n", i); }
--- a/libpurple/protocols/qq/group_im.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_im.c Mon Sep 15 03:04:07 2008 +0000 @@ -41,7 +41,6 @@ #include "header_info.h" #include "packet_parse.h" #include "qq_network.h" -#include "qq_process.h" #include "utils.h" typedef struct _qq_recv_group_im { @@ -86,12 +85,12 @@ if (bytes == data_len) /* create OK */ qq_send_room_cmd(gc, QQ_ROOM_CMD_SEND_MSG, group->id, raw_data, data_len); else - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail creating group_im packet, expect %d bytes, build %d bytes\n", data_len, bytes); } /* this is the ACK */ -void qq_process_group_cmd_im(guint8 *data, gint len, PurpleConnection *gc) +void qq_process_group_cmd_im(guint8 *data, gint len, PurpleConnection *gc) { /* return should be the internal group id * but we have nothing to do with it */ @@ -99,7 +98,7 @@ } /* receive an application to join the group */ -void qq_process_room_msg_apply_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc) +void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc) { guint32 ext_id, user_uid; guint8 type8; @@ -120,8 +119,8 @@ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT); - msg = g_strdup_printf(_("%d requested to join Qun %d"), user_uid, ext_id); - reason = g_strdup_printf(_("Message: %s"), reason_utf8); + msg = g_strdup_printf(_("User %d requested to join group %d"), user_uid, ext_id); + reason = g_strdup_printf(_("Reason: %s"), reason_utf8); g = g_new0(group_member_opt, 1); g->gc = gc; @@ -150,7 +149,7 @@ } /* the request to join a group is rejected */ -void qq_process_room_msg_been_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc) +void qq_process_recv_group_im_been_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc) { guint32 ext_id, admin_uid; guint8 type8; @@ -171,14 +170,14 @@ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT); msg = g_strdup_printf - (_("Your request to join Qun %d has been rejected by admin %d"), ext_id, admin_uid); - reason = g_strdup_printf(_("Message: %s"), reason_utf8); + (_("Your request to join group %d has been rejected by admin %d"), ext_id, admin_uid); + reason = g_strdup_printf(_("Reason: %s"), reason_utf8); purple_notify_warning(gc, _("QQ Qun Operation"), msg, reason); group = qq_room_search_id(gc, id); if (group != NULL) { - group->my_role = QQ_ROOM_ROLE_NO; + group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER; qq_group_refresh(gc, group); } @@ -188,7 +187,7 @@ } /* the request to join a group is approved */ -void qq_process_room_msg_been_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc) +void qq_process_recv_group_im_been_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc) { guint32 ext_id, admin_uid; guint8 type8; @@ -209,13 +208,13 @@ bytes += convert_as_pascal_string(data + bytes, &reason_utf8, QQ_CHARSET_DEFAULT); msg = g_strdup_printf - (_("Your request to join Qun %d has been approved by admin %d"), ext_id, admin_uid); + (_("Your request to join group %d has been approved by admin %d"), ext_id, admin_uid); purple_notify_warning(gc, _("QQ Qun Operation"), msg, NULL); group = qq_room_search_id(gc, id); if (group != NULL) { - group->my_role = QQ_ROOM_ROLE_YES; + group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER; qq_group_refresh(gc, group); } @@ -224,7 +223,7 @@ } /* process the packet when removed from a group */ -void qq_process_room_msg_been_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc) +void qq_process_recv_group_im_been_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc) { guint32 ext_id, uid; guint8 type8; @@ -242,12 +241,12 @@ g_return_if_fail(ext_id > 0 && uid > 0); - msg = g_strdup_printf(_("[%d] removed from Qun \"%d\""), uid, ext_id); + msg = g_strdup_printf(_("You [%d] have left group \"%d\""), uid, ext_id); purple_notify_info(gc, _("QQ Qun Operation"), msg, NULL); group = qq_room_search_id(gc, id); if (group != NULL) { - group->my_role = QQ_ROOM_ROLE_NO; + group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER; qq_group_refresh(gc, group); } @@ -255,7 +254,7 @@ } /* process the packet when added to a group */ -void qq_process_room_msg_been_added(guint8 *data, gint len, guint32 id, PurpleConnection *gc) +void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 id, PurpleConnection *gc) { guint32 ext_id, uid; guint8 type8; @@ -273,18 +272,18 @@ g_return_if_fail(ext_id > 0 && uid > 0); - msg = g_strdup_printf(_("[%d] added to Qun \"%d\""), uid, ext_id); - purple_notify_info(gc, _("QQ Qun Operation"), msg, _("Qun is in buddy list")); + msg = g_strdup_printf(_("You [%d] have been added to group \"%d\""), uid, ext_id); + purple_notify_info(gc, _("QQ Qun Operation"), msg, _("This group has been added to your buddy list")); group = qq_room_search_id(gc, id); if (group != NULL) { - group->my_role = QQ_ROOM_ROLE_YES; + group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER; qq_group_refresh(gc, group); } else { /* no such group, try to create a dummy first, and then update */ group = qq_group_create_internal_record(gc, id, ext_id, NULL); - group->my_role = QQ_ROOM_ROLE_YES; + group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER; qq_group_refresh(gc, group); - qq_room_update(gc, 0, group->id); + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id); /* the return of this cmd will automatically update the group in blist */ } @@ -292,7 +291,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_recv_group_im(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type) { gchar *msg_with_purple_smiley, *msg_utf8_encoded, *im_src_name; guint16 unknown; @@ -311,9 +310,7 @@ qd = (qq_data *) gc->proto_data; -#if 0 - qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", data, data_len, "group im hex dump"); -#endif + /* qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", data, data_len, "group im hex dump"); */ im_group = g_newa(qq_recv_group_im, 1); @@ -377,13 +374,13 @@ group = qq_room_search_id(gc, id); g_return_if_fail(group != NULL); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->title_utf8, purple_connection_get_account(gc)); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->group_name_utf8, purple_connection_get_account(gc)); if (conv == NULL && purple_prefs_get_bool("/plugins/prpl/qq/prompt_group_msg_on_recv")) { /* New conv should open, get group info*/ - qq_room_update(gc, 0, group->id); - - serv_got_joined_chat(gc, qd->channel++, group->title_utf8); - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->title_utf8, purple_connection_get_account(gc)); + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id); + + serv_got_joined_chat(gc, qd->channel++, group->group_name_utf8); + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->group_name_utf8, purple_connection_get_account(gc)); } if (conv != NULL) {
--- a/libpurple/protocols/qq/group_im.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_im.h Mon Sep 15 03:04:07 2008 +0000 @@ -31,17 +31,30 @@ void qq_send_packet_group_im(PurpleConnection *gc, qq_group *group, const gchar *msg); +/* void qq_process_group_cmd_im(guint8 *data, guint8 **cursor, gint len, PurpleConnection *gc); */ 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_recv_group_im(guint8 *data, guint8 **cursor, + * gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type); */ +void qq_process_recv_group_im(guint8 *data, gint data_len, guint32 id, PurpleConnection *gc, guint16 im_type); -void qq_process_room_msg_apply_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc); +/* void qq_process_recv_group_im_apply_join(guint8 *data, guint8 **cursor, gint len, + * guint32 id, PurpleConnection *gc); */ +void qq_process_recv_group_im_apply_join(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_msg_been_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc); +/* void qq_process_recv_group_im_been_rejected(guint8 *data, guint8 **cursor, gint len, + * guint32 id, PurpleConnection *gc); */ +void qq_process_recv_group_im_been_rejected(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_msg_been_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc); +/* void qq_process_recv_group_im_been_approved(guint8 *data, guint8 **cursor, gint len, + * guint32 id, PurpleConnection *gc); */ +void qq_process_recv_group_im_been_approved(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_msg_been_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc); +/* void qq_process_recv_group_im_been_removed(guint8 *data, guint8 **cursor, gint len, + * guint32 id, PurpleConnection *gc); */ +void qq_process_recv_group_im_been_removed(guint8 *data, gint len, guint32 id, PurpleConnection *gc); -void qq_process_room_msg_been_added(guint8 *data, gint len, guint32 id, PurpleConnection *gc); +/* void qq_process_recv_group_im_been_added(guint8 *data, guint8 **cursor, gint len, + * guint32 id, PurpleConnection *gc); */ +void qq_process_recv_group_im_been_added(guint8 *data, gint len, guint32 id, PurpleConnection *gc); #endif
--- a/libpurple/protocols/qq/group_info.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_info.c Mon Sep 15 03:04:07 2008 +0000 @@ -41,16 +41,16 @@ * this interval determines if their member info is outdated */ #define QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL 180 -static gboolean check_update_interval(qq_buddy *member) +static gboolean _is_group_member_need_update_info(qq_buddy *member) { g_return_val_if_fail(member != NULL, FALSE); return (member->nickname == NULL) || - (time(NULL) - member->last_update) > QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL; + (time(NULL) - member->last_refresh) > QQ_GROUP_CHAT_REFRESH_NICKNAME_INTERNAL; } /* this is done when we receive the reply to get_online_members sub_cmd * all member are set offline, and then only those in reply packets are online */ -static void set_all_offline(qq_group *group) +static void _qq_group_set_members_all_offline(qq_group *group) { GList *list; qq_buddy *member; @@ -64,24 +64,60 @@ } } +/* send packet to get online group member, called by keep_alive */ +void qq_send_cmd_group_all_get_online_members(PurpleConnection *gc) +{ + qq_data *qd; + qq_group *group; + GList *list; + + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + qd = (qq_data *) gc->proto_data; + + list = qd->groups; + while (list != NULL) { + group = (qq_group *) list->data; + if (group->my_status == QQ_GROUP_MEMBER_STATUS_IS_MEMBER || + group->my_status == QQ_GROUP_MEMBER_STATUS_IS_ADMIN) + /* no need to get info time and time again, online members enough */ + qq_send_cmd_group_get_online_members(gc, group); + + list = list->next; + } +} + +void qq_send_cmd_group_get_online_members(PurpleConnection *gc, qq_group *group) +{ + g_return_if_fail(group != NULL); + + /* only get online members when conversation window is on */ + if (NULL == purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,group->group_name_utf8, purple_connection_get_account(gc))) { + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Conversation \"%s\" is not open, ignore to get online members\n", group->group_name_utf8); + return; + } + + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, group->id); +} + /* send packet to get info for each group member */ -gint qq_request_room_get_buddies(PurpleConnection *gc, qq_group *group, gint update_class) +void qq_send_cmd_group_get_members_info(PurpleConnection *gc, qq_group *group) { guint8 *raw_data; gint bytes, num; GList *list; qq_buddy *member; - g_return_val_if_fail(group != NULL, 0); + g_return_if_fail(group != NULL); for (num = 0, list = group->members; list != NULL; list = list->next) { member = (qq_buddy *) list->data; - if (check_update_interval(member)) + if (_is_group_member_need_update_info(member)) num++; } if (num <= 0) { - purple_debug_info("QQ", "No group member info needs to be updated now.\n"); - return 0; + purple_debug(PURPLE_DEBUG_INFO, "QQ", "No group member info needs to be updated now.\n"); + return; } raw_data = g_newa(guint8, 4 * num); @@ -91,14 +127,12 @@ list = group->members; while (list != NULL) { member = (qq_buddy *) list->data; - if (check_update_interval(member)) + if (_is_group_member_need_update_info(member)) bytes += qq_put32(raw_data + bytes, member->uid); list = list->next; } - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_BUDDIES, group->id, raw_data, bytes, - update_class, 0); - return num; + qq_send_room_cmd(gc, QQ_ROOM_CMD_GET_MEMBER_INFO, group->id, raw_data, bytes); } void qq_process_room_cmd_get_info(guint8 *data, gint data_len, PurpleConnection *gc) @@ -140,8 +174,8 @@ bytes += qq_get32(&(group->creator_uid), data + bytes); bytes += qq_get8(&(group->auth_type), data + bytes); bytes += qq_get32(&unknown4, data + bytes); /* oldCategory */ - bytes += qq_get16(&unknown, data + bytes); - bytes += qq_get32(&(group->category), data + bytes); + bytes += qq_get16(&unknown, data + bytes); + bytes += qq_get32(&(group->group_category), data + bytes); bytes += qq_get16(&max_members, data + bytes); bytes += qq_get8(&unknown1, data + bytes); /* the following, while Eva: @@ -149,17 +183,17 @@ * 2(qunNoticeLen), qunNoticeLen(qunNoticeContent, 1(qunDescLen), * qunDestLen(qunDestcontent)) */ bytes += qq_get8(&unknown1, data + bytes); - purple_debug_info("QQ", "type=%u creatorid=%u category=%u maxmembers=%u\n", - group->type8, group->creator_uid, group->category, max_members); - + purple_debug(PURPLE_DEBUG_INFO, "QQ", "type=%u creatorid=%u category=%u maxmembers=%u\n", + group->type8, group->creator_uid, group->group_category, max_members); + /* strlen + <str content> */ - bytes += convert_as_pascal_string(data + bytes, &(group->title_utf8), QQ_CHARSET_DEFAULT); - purple_debug_info("QQ", "group \"%s\"\n", group->title_utf8); + bytes += convert_as_pascal_string(data + bytes, &(group->group_name_utf8), QQ_CHARSET_DEFAULT); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "group \"%s\"\n", group->group_name_utf8); bytes += qq_get16(&unknown, data + bytes); /* 0x0000 */ bytes += convert_as_pascal_string(data + bytes, ¬ice, QQ_CHARSET_DEFAULT); - purple_debug_info("QQ", "notice \"%s\"\n", notice); - bytes += convert_as_pascal_string(data + bytes, &(group->desc_utf8), QQ_CHARSET_DEFAULT); - purple_debug_info("QQ", "group_desc \"%s\"\n", group->desc_utf8); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "notice \"%s\"\n", notice); + bytes += convert_as_pascal_string(data + bytes, &(group->group_desc_utf8), QQ_CHARSET_DEFAULT); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "group_desc \"%s\"\n", group->group_desc_utf8); num = 0; /* now comes the member list separated by 0x00 */ @@ -171,7 +205,7 @@ #if 0 if(organization != 0 || role != 0) { - purple_debug_info("QQ_GRP", "%d, organization=%d, role=%d\n", member_uid, organization, role); + purple_debug(PURPLE_DEBUG_INFO, "QQ_GRP", "%d, organization=%d, role=%d\n", member_uid, organization, role); } #endif @@ -180,22 +214,22 @@ member->role = role; } if(bytes > data_len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "group_cmd_get_group_info: Dangerous error! maybe protocol changed, notify me!"); } - purple_debug_info("QQ", "group \"%s\" has %d members\n", group->title_utf8, num); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "group \"%s\" has %d members\n", group->group_name_utf8, num); if (group->creator_uid == qd->uid) - group->my_role = QQ_ROOM_ROLE_ADMIN; + group->my_status = QQ_GROUP_MEMBER_STATUS_IS_ADMIN; qq_group_refresh(gc, group); - purple_conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - group->title_utf8, purple_connection_get_account(gc)); + purple_conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + group->group_name_utf8, purple_connection_get_account(gc)); if(NULL == purple_conv) { - purple_debug_warning("QQ", - "Conversation \"%s\" is not open, do not set topic\n", group->title_utf8); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Conversation \"%s\" is not open, do not set topic\n", group->group_name_utf8); return; } @@ -203,7 +237,7 @@ qq_filter_str(notice); group->notice_utf8 = strdup(notice); g_free(notice); - + purple_conv_chat_set_topic(PURPLE_CONV_CHAT(purple_conv), NULL, group->notice_utf8); } @@ -218,7 +252,7 @@ g_return_if_fail(data != NULL && len > 0); if (len <= 3) { - purple_debug_error("QQ", "Invalid group online member reply, discard it!\n"); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Invalid group online member reply, discard it!\n"); return; } @@ -229,12 +263,13 @@ group = qq_room_search_id(gc, id); if (group == NULL) { - purple_debug_error("QQ", "We have no group info for internal id [%d]\n", id); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "We have no group info for internal id [%d]\n", id); return; } /* set all offline first, then update those online */ - set_all_offline(group); + _qq_group_set_members_all_offline(group); num = 0; while (bytes < len) { bytes += qq_get32(&member_uid, data + bytes); @@ -244,15 +279,15 @@ member->status = QQ_BUDDY_ONLINE_NORMAL; } if(bytes > len) { - purple_debug_error("QQ", - "group_cmd_get_online_members: Dangerous error! maybe protocol changed, notify developers!"); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "group_cmd_get_online_members: Dangerous error! maybe protocol changed, notify developers!"); } - purple_debug_info("QQ", "Group \"%s\" has %d online members\n", group->title_utf8, num); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Group \"%s\" has %d online members\n", group->group_name_utf8, num); } /* process the reply to get_members_info packet */ -void qq_process_room_cmd_get_buddies(guint8 *data, gint len, PurpleConnection *gc) +void qq_process_room_cmd_get_members(guint8 *data, gint len, PurpleConnection *gc) { gint bytes; gint num; @@ -265,7 +300,7 @@ g_return_if_fail(data != NULL && len > 0); #if 0 - qq_show_packet("qq_process_room_cmd_get_buddies", data, len); + qq_show_packet("qq_process_room_cmd_get_members", data, len); #endif bytes = 0; @@ -296,19 +331,19 @@ qq_filter_str(nick); member->nickname = g_strdup(nick); g_free(nick); - + #if 0 - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "member [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n", member_uid, member->ext_flag, member->comm_flag, member->nickname); #endif - member->last_update = time(NULL); + member->last_refresh = time(NULL); } if (bytes > len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "group_cmd_get_members_info: Dangerous error! maybe protocol changed, notify developers!"); } - purple_debug_info("QQ", "Group \"%s\" obtained %d member info\n", group->title_utf8, num); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Group \"%s\" obtained %d member info\n", group->group_name_utf8, num); }
--- a/libpurple/protocols/qq/group_info.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_info.h Mon Sep 15 03:04:07 2008 +0000 @@ -29,9 +29,12 @@ #include "connection.h" #include "group.h" -gint qq_request_room_get_buddies(PurpleConnection *gc, qq_group *group, gint update_class); +void qq_send_cmd_group_get_online_members(PurpleConnection *gc, qq_group *group); +void qq_send_cmd_group_all_get_online_members(PurpleConnection *gc); + +void qq_send_cmd_group_get_members_info(PurpleConnection *gc, qq_group *group); void qq_process_room_cmd_get_info(guint8 *data, gint len, PurpleConnection *gc); void qq_process_room_cmd_get_onlines(guint8 *data, gint len, PurpleConnection *gc); -void qq_process_room_cmd_get_buddies(guint8 *data, gint len, PurpleConnection *gc); +void qq_process_room_cmd_get_members(guint8 *data, gint len, PurpleConnection *gc); #endif
--- a/libpurple/protocols/qq/group_internal.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_internal.c Mon Sep 15 03:04:07 2008 +0000 @@ -31,49 +31,49 @@ #include "group_internal.h" #include "utils.h" -static gchar *get_role_desc(qq_group *group) +static gchar *_qq_group_set_my_status_desc(qq_group *group) { - const char *role_desc; + const char *status_desc; g_return_val_if_fail(group != NULL, g_strdup("")); - switch (group->my_role) { - case QQ_ROOM_ROLE_NO: - role_desc = _("I am not a member"); + switch (group->my_status) { + case QQ_GROUP_MEMBER_STATUS_NOT_MEMBER: + status_desc = _("I am not a member"); break; - case QQ_ROOM_ROLE_YES: - role_desc = _("I am a member"); + case QQ_GROUP_MEMBER_STATUS_IS_MEMBER: + status_desc = _("I am a member"); break; - case QQ_ROOM_ROLE_REQUESTING: - role_desc = _("I am requesting"); + case QQ_GROUP_MEMBER_STATUS_APPLYING: + status_desc = _("I am applying to join"); break; - case QQ_ROOM_ROLE_ADMIN: - role_desc = _("I am the admin"); + case QQ_GROUP_MEMBER_STATUS_IS_ADMIN: + status_desc = _("I am the admin"); break; default: - role_desc = _("Unknown status"); + status_desc = _("Unknown status"); } - return g_strdup(role_desc); + return g_strdup(status_desc); } -static void add_room_to_blist(PurpleConnection *gc, qq_group *group) +static void _qq_group_add_to_blist(PurpleConnection *gc, qq_group *group) { GHashTable *components; PurpleGroup *g; PurpleChat *chat; components = qq_group_to_hashtable(group); - chat = purple_chat_new(purple_connection_get_account(gc), group->title_utf8, components); + chat = purple_chat_new(purple_connection_get_account(gc), group->group_name_utf8, components); g = qq_get_purple_group(PURPLE_GROUP_QQ_QUN); purple_blist_add_chat(chat, g, NULL); - purple_debug_info("QQ", "You have added group \"%s\" to blist locally\n", group->title_utf8); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "You have added group \"%s\" to blist locally\n", group->group_name_utf8); } /* Create a dummy qq_group, which includes only internal_id, ext_id, - * and potentially title_utf8, in case we need to call group_conv_show_window + * and potentially group_name_utf8, in case we need to call group_conv_show_window * right after creation. All other attributes are set to empty. * We need to send a get_group_info to the QQ server to update it right away */ qq_group *qq_group_create_internal_record(PurpleConnection *gc, - guint32 internal_id, guint32 ext_id, gchar *title_utf8) + guint32 internal_id, guint32 ext_id, gchar *group_name_utf8) { qq_group *group; qq_data *qd; @@ -82,21 +82,21 @@ qd = (qq_data *) gc->proto_data; group = g_new0(qq_group, 1); - group->my_role = QQ_ROOM_ROLE_NO; - group->my_role_desc = get_role_desc(group); + group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER; + group->my_status_desc = _qq_group_set_my_status_desc(group); group->id = internal_id; group->ext_id = ext_id; group->type8 = 0x01; /* assume permanent Qun */ group->creator_uid = 10000; /* assume by QQ admin */ - group->category = 0x01; + group->group_category = 0x01; group->auth_type = 0x02; /* assume need auth */ - group->title_utf8 = g_strdup(title_utf8 == NULL ? "" : title_utf8); - group->desc_utf8 = g_strdup(""); + group->group_name_utf8 = g_strdup(group_name_utf8 == NULL ? "" : group_name_utf8); + group->group_desc_utf8 = g_strdup(""); group->notice_utf8 = g_strdup(""); group->members = NULL; qd->groups = g_list_append(qd->groups, group); - add_room_to_blist(gc, group); + _qq_group_add_to_blist(gc, group); return group; } @@ -124,21 +124,21 @@ { GHashTable *components; components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_ROLE), g_strdup_printf("%d", group->my_role)); - group->my_role_desc = get_role_desc(group); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_MEMBER_STATUS), g_strdup_printf("%d", group->my_status)); + group->my_status_desc = _qq_group_set_my_status_desc(group); g_hash_table_insert(components, - g_strdup(QQ_ROOM_KEY_INTERNAL_ID), g_strdup_printf("%d", group->id)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_EXTERNAL_ID), + g_strdup(QQ_GROUP_KEY_INTERNAL_ID), g_strdup_printf("%d", group->id)); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_EXTERNAL_ID), g_strdup_printf("%d", group->ext_id)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_TYPE), g_strdup_printf("%d", group->type8)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid)); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_TYPE), g_strdup_printf("%d", group->type8)); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid)); g_hash_table_insert(components, - g_strdup(QQ_ROOM_KEY_CATEGORY), g_strdup_printf("%d", group->category)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_ROLE_DESC), g_strdup(group->my_role_desc)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(group->title_utf8)); - g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_DESC_UTF8), g_strdup(group->desc_utf8)); + g_strdup(QQ_GROUP_KEY_GROUP_CATEGORY), g_strdup_printf("%d", group->group_category)); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type)); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_MEMBER_STATUS_DESC), g_strdup(group->my_status_desc)); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_GROUP_NAME_UTF8), g_strdup(group->group_name_utf8)); + g_hash_table_insert(components, g_strdup(QQ_GROUP_KEY_GROUP_DESC_UTF8), g_strdup(group->group_desc_utf8)); return components; } @@ -152,22 +152,22 @@ qd = (qq_data *) gc->proto_data; group = g_new0(qq_group, 1); - group->my_role = + group->my_status = qq_string_to_dec_value (NULL == g_hash_table_lookup(data, - QQ_ROOM_KEY_ROLE) ? - g_strdup_printf("%d", QQ_ROOM_ROLE_NO) : - g_hash_table_lookup(data, QQ_ROOM_KEY_ROLE)); - group->id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID)); - group->ext_id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_EXTERNAL_ID)); - group->type8 = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_TYPE)); - group->creator_uid = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_CREATOR_UID)); - group->category = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_CATEGORY)); - group->auth_type = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_AUTH_TYPE)); - group->title_utf8 = g_strdup(g_hash_table_lookup(data, QQ_ROOM_KEY_TITLE_UTF8)); - group->desc_utf8 = g_strdup(g_hash_table_lookup(data, QQ_ROOM_KEY_DESC_UTF8)); - group->my_role_desc = get_role_desc(group); + QQ_GROUP_KEY_MEMBER_STATUS) ? + g_strdup_printf("%d", QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) : + g_hash_table_lookup(data, QQ_GROUP_KEY_MEMBER_STATUS)); + group->id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID)); + group->ext_id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID)); + group->type8 = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_TYPE)); + group->creator_uid = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_CREATOR_UID)); + group->group_category = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_CATEGORY)); + group->auth_type = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_GROUP_KEY_AUTH_TYPE)); + group->group_name_utf8 = g_strdup(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_NAME_UTF8)); + group->group_desc_utf8 = g_strdup(g_hash_table_lookup(data, QQ_GROUP_KEY_GROUP_DESC_UTF8)); + group->my_status_desc = _qq_group_set_my_status_desc(group); qd->groups = g_list_append(qd->groups, group); @@ -184,54 +184,48 @@ ext_id = g_strdup_printf("%d", group->ext_id); chat = purple_blist_find_chat(purple_connection_get_account(gc), ext_id); g_free(ext_id); - if (chat == NULL && group->my_role != QQ_ROOM_ROLE_NO) { - add_room_to_blist(gc, group); - return; - } - - if (chat == NULL) { - return; + if (chat == NULL && group->my_status != QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) { + _qq_group_add_to_blist(gc, group); + } else if (chat != NULL) { /* we have a local record, update its info */ + /* if there is group_name_utf8, we update the group name */ + if (group->group_name_utf8 != NULL && strlen(group->group_name_utf8) > 0) + purple_blist_alias_chat(chat, group->group_name_utf8); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_MEMBER_STATUS), g_strdup_printf("%d", group->my_status)); + group->my_status_desc = _qq_group_set_my_status_desc(group); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_MEMBER_STATUS_DESC), g_strdup(group->my_status_desc)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_INTERNAL_ID), + g_strdup_printf("%d", group->id)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_EXTERNAL_ID), + g_strdup_printf("%d", group->ext_id)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_TYPE), g_strdup_printf("%d", group->type8)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_GROUP_CATEGORY), + g_strdup_printf("%d", group->group_category)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_GROUP_NAME_UTF8), g_strdup(group->group_name_utf8)); + g_hash_table_replace(chat->components, + g_strdup(QQ_GROUP_KEY_GROUP_DESC_UTF8), g_strdup(group->group_desc_utf8)); } - - /* we have a local record, update its info */ - /* if there is title_utf8, we update the group name */ - if (group->title_utf8 != NULL && strlen(group->title_utf8) > 0) - purple_blist_alias_chat(chat, group->title_utf8); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_ROLE), g_strdup_printf("%d", group->my_role)); - group->my_role_desc = get_role_desc(group); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_ROLE_DESC), g_strdup(group->my_role_desc)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_INTERNAL_ID), - g_strdup_printf("%d", group->id)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_EXTERNAL_ID), - g_strdup_printf("%d", group->ext_id)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_TYPE), g_strdup_printf("%d", group->type8)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_CATEGORY), - g_strdup_printf("%d", group->category)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(group->title_utf8)); - g_hash_table_replace(chat->components, - g_strdup(QQ_ROOM_KEY_DESC_UTF8), g_strdup(group->desc_utf8)); } -/* NOTE: If we knew how to convert between an external and internal group id, as the official +/* NOTE: If we knew how to convert between an external and internal group id, as the official * client seems to, the following would be unnecessary. That would be ideal. */ /* Use list to specify if id's alternate id is pending discovery. */ void qq_set_pending_id(GSList **list, guint32 id, gboolean pending) { - if (pending) + if (pending) *list = g_slist_prepend(*list, GINT_TO_POINTER(id)); - else + else *list = g_slist_remove(*list, GINT_TO_POINTER(id)); }
--- a/libpurple/protocols/qq/group_internal.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_internal.h Mon Sep 15 03:04:07 2008 +0000 @@ -28,18 +28,18 @@ #include <glib.h> #include "group.h" -#define QQ_ROOM_KEY_ROLE "my_role" -#define QQ_ROOM_KEY_ROLE_DESC "my_role_desc" -#define QQ_ROOM_KEY_INTERNAL_ID "id" -#define QQ_ROOM_KEY_EXTERNAL_ID "ext_id" -#define QQ_ROOM_KEY_TYPE "type" -#define QQ_ROOM_KEY_CREATOR_UID "creator_uid" -#define QQ_ROOM_KEY_CATEGORY "category" -#define QQ_ROOM_KEY_AUTH_TYPE "auth_type" -#define QQ_ROOM_KEY_TITLE_UTF8 "title_utf8" -#define QQ_ROOM_KEY_DESC_UTF8 "desc_utf8" +#define QQ_GROUP_KEY_MEMBER_STATUS "my_status_code" +#define QQ_GROUP_KEY_MEMBER_STATUS_DESC "my_status_desc" +#define QQ_GROUP_KEY_INTERNAL_ID "id" +#define QQ_GROUP_KEY_EXTERNAL_ID "ext_id" +#define QQ_GROUP_KEY_TYPE "type" +#define QQ_GROUP_KEY_CREATOR_UID "creator_uid" +#define QQ_GROUP_KEY_GROUP_CATEGORY "category" +#define QQ_GROUP_KEY_AUTH_TYPE "auth_type" +#define QQ_GROUP_KEY_GROUP_NAME_UTF8 "name_utf8" +#define QQ_GROUP_KEY_GROUP_DESC_UTF8 "desc_utf8" -qq_group *qq_group_create_internal_record(PurpleConnection *gc, +qq_group *qq_group_create_internal_record(PurpleConnection *gc, guint32 internal_id, guint32 ext_id, gchar *group_name_utf8); void qq_group_delete_internal_record(qq_data *qd, guint32 id);
--- a/libpurple/protocols/qq/group_join.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_join.c Mon Sep 15 03:04:07 2008 +0000 @@ -42,11 +42,10 @@ #include "header_info.h" #include "packet_parse.h" #include "qq_network.h" -#include "qq_process.h" enum { - QQ_ROOM_JOIN_OK = 0x01, - QQ_ROOM_JOIN_NEED_AUTH = 0x02, + QQ_GROUP_JOIN_OK = 0x01, + QQ_GROUP_JOIN_NEED_AUTH = 0x02, }; static void _qq_group_exit_with_gc_and_id(gc_and_uid *g) @@ -69,20 +68,20 @@ { g_return_if_fail(group != NULL); - if (group->my_role == QQ_ROOM_ROLE_NO) { - group->my_role = QQ_ROOM_ROLE_REQUESTING; + if (group->my_status == QQ_GROUP_MEMBER_STATUS_NOT_MEMBER) { + group->my_status = QQ_GROUP_MEMBER_STATUS_APPLYING; qq_group_refresh(gc, group); } switch (group->auth_type) { - case QQ_ROOM_AUTH_TYPE_NO_AUTH: - case QQ_ROOM_AUTH_TYPE_NEED_AUTH: + case QQ_GROUP_AUTH_TYPE_NO_AUTH: + case QQ_GROUP_AUTH_TYPE_NEED_AUTH: break; - case QQ_ROOM_AUTH_TYPE_NO_ADD: - purple_notify_warning(gc, NULL, _("The Qun does not allow others to join"), NULL); + case QQ_GROUP_AUTH_TYPE_NO_ADD: + purple_notify_warning(gc, NULL, _("This group does not allow others to join"), NULL); return; default: - purple_debug_error("QQ", "Unknown room auth type: %d\n", group->auth_type); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown group auth type: %d\n", group->auth_type); break; } @@ -100,10 +99,10 @@ group = qq_room_search_id(gc, id); if (group == NULL) { - purple_debug_error("QQ", "Can not find qq_group by internal_id: %d\n", id); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Can not find qq_group by internal_id: %d\n", id); return; } else { /* everything is OK */ - qq_send_cmd_group_auth(gc, group, QQ_ROOM_AUTH_REQUEST_APPLY, 0, reason_utf8); + qq_send_cmd_group_auth(gc, group, QQ_GROUP_AUTH_REQUEST_APPLY, 0, reason_utf8); } } @@ -113,9 +112,10 @@ gc_and_uid *g; g_return_if_fail(group != NULL); - purple_debug_info("QQ", "Group (internal id: %d) needs authentication\n", group->id); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "Group (internal id: %d) needs authentication\n", group->id); - msg = g_strdup_printf("Group \"%s\" needs authentication\n", group->title_utf8); + msg = g_strdup_printf("Group \"%s\" needs authentication\n", group->group_name_utf8); g = g_new0(gc_and_uid, 1); g->gc = gc; g->uid = group->id; @@ -125,7 +125,7 @@ _("Send"), G_CALLBACK(_qq_group_join_auth_with_gc_and_id), _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid), - purple_connection_get_account(gc), group->title_utf8, NULL, + purple_connection_get_account(gc), group->group_name_utf8, NULL, g); g_free(msg); } @@ -143,8 +143,8 @@ else reason_qq = utf8_to_qq(reason_utf8, QQ_CHARSET_DEFAULT); - if (opt == QQ_ROOM_AUTH_REQUEST_APPLY) { - group->my_role = QQ_ROOM_ROLE_REQUESTING; + if (opt == QQ_GROUP_AUTH_REQUEST_APPLY) { + group->my_status = QQ_GROUP_MEMBER_STATUS_APPLYING; qq_group_refresh(gc, group); uid = 0; } @@ -173,7 +173,8 @@ qd = (qq_data *) gc->proto_data; if (len < 4) { - purple_debug_error("QQ", "Invalid exit group reply, expect %d bytes, read %d bytes\n", 4, len); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "Invalid exit group reply, expect %d bytes, read %d bytes\n", 4, len); return; } @@ -188,7 +189,7 @@ purple_blist_remove_chat(chat); qq_group_delete_internal_record(qd, id); } - purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully left the Qun"), NULL); + purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully left the group"), NULL); } /* Process the reply to group_auth subcmd */ @@ -202,15 +203,15 @@ qd = (qq_data *) gc->proto_data; if (len < 4) { - purple_debug_error("QQ", - "Invalid join room reply, expect %d bytes, read %d bytes\n", 4, len); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "Invalid join group reply, expect %d bytes, read %d bytes\n", 4, len); return; } bytes = 0; bytes += qq_get32(&id, data + bytes); g_return_if_fail(id > 0); - purple_notify_info(gc, _("QQ Qun Auth"), + purple_notify_info(gc, _("QQ Group Auth"), _("Your authorization request has been accepted by the QQ server"), NULL); } @@ -225,11 +226,11 @@ g_return_if_fail(data != NULL && len > 0); if (len < 5) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Invalid join group reply, expect %d bytes, read %d bytes\n", 5, len); return; } - + bytes = 0; bytes += qq_get32(&id, data + bytes); bytes += qq_get8(&reply, data + bytes); @@ -239,26 +240,26 @@ /* need to check if group is NULL or not. */ g_return_if_fail(group != NULL); switch (reply) { - case QQ_ROOM_JOIN_OK: - purple_debug_info("QQ", "Succeed joining group \"%s\"\n", group->title_utf8); - group->my_role = QQ_ROOM_ROLE_YES; + case QQ_GROUP_JOIN_OK: + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed joining group \"%s\"\n", group->group_name_utf8); + group->my_status = QQ_GROUP_MEMBER_STATUS_IS_MEMBER; qq_group_refresh(gc, group); /* this must be shown before getting online members */ qq_group_conv_show_window(gc, group); - qq_room_update(gc, 0, group->id); + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, group->id); break; - case QQ_ROOM_JOIN_NEED_AUTH: - purple_debug_info("QQ", + case QQ_GROUP_JOIN_NEED_AUTH: + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Fail joining group [%d] %s, needs authentication\n", - group->ext_id, group->title_utf8); - group->my_role = QQ_ROOM_ROLE_NO; + group->ext_id, group->group_name_utf8); + group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER; qq_group_refresh(gc, group); _qq_group_join_auth(gc, group); break; default: - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Error joining group [%d] %s, unknown reply: 0x%02x\n", - group->ext_id, group->title_utf8, reply); + group->ext_id, group->group_name_utf8, reply); } } @@ -273,7 +274,7 @@ g_return_if_fail(data != NULL); qd = (qq_data *) gc->proto_data; - ext_id_ptr = g_hash_table_lookup(data, QQ_ROOM_KEY_EXTERNAL_ID); + ext_id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_EXTERNAL_ID); g_return_if_fail(ext_id_ptr != NULL); errno = 0; ext_id = strtol(ext_id_ptr, NULL, 10); @@ -300,7 +301,7 @@ g_return_if_fail(data != NULL); - id_ptr = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID); + id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID); id = strtol(id_ptr, NULL, 10); g_return_if_fail(id > 0); @@ -311,7 +312,8 @@ purple_request_action(gc, _("QQ Qun Operation"), _("Are you sure you want to leave this Qun?"), - _("Note, if you are the creator, \nthis operation will eventually remove this Qun."), + _ + ("Note, if you are the creator, \nthis operation will eventually remove this Qun."), 1, purple_connection_get_account(gc), NULL, NULL, g, 2, _("Cancel"),
--- a/libpurple/protocols/qq/group_join.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_join.h Mon Sep 15 03:04:07 2008 +0000 @@ -30,15 +30,15 @@ #include "group.h" enum { - QQ_ROOM_AUTH_TYPE_NO_AUTH = 0x01, - QQ_ROOM_AUTH_TYPE_NEED_AUTH = 0x02, - QQ_ROOM_AUTH_TYPE_NO_ADD = 0x03 + QQ_GROUP_AUTH_TYPE_NO_AUTH = 0x01, + QQ_GROUP_AUTH_TYPE_NEED_AUTH = 0x02, + QQ_GROUP_AUTH_TYPE_NO_ADD = 0x03 }; enum { - QQ_ROOM_AUTH_REQUEST_APPLY = 0x01, - QQ_ROOM_AUTH_REQUEST_APPROVE = 0x02, - QQ_ROOM_AUTH_REQUEST_REJECT = 0x03 + QQ_GROUP_AUTH_REQUEST_APPLY = 0x01, + QQ_GROUP_AUTH_REQUEST_APPROVE = 0x02, + QQ_GROUP_AUTH_REQUEST_REJECT = 0x03 }; void qq_send_cmd_group_auth(PurpleConnection *gc, qq_group *group, guint8 opt, guint32 uid, const gchar *reason_utf8);
--- a/libpurple/protocols/qq/group_opt.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_opt.c Mon Sep 15 03:04:07 2008 +0000 @@ -38,7 +38,6 @@ #include "header_info.h" #include "packet_parse.h" #include "qq_network.h" -#include "qq_process.h" #include "utils.h" static int _compare_guint32(const void *a, @@ -68,7 +67,7 @@ } data_len = 6 + count * 4; data = g_newa(guint8, data_len); - + bytes = 0; bytes += qq_put8(data + bytes, operation); for (i = 0; i < count; i++) @@ -89,7 +88,7 @@ g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0); group = qq_room_search_id(g->gc, g->id); g_return_if_fail(group != NULL); - qq_send_cmd_group_auth(g->gc, group, QQ_ROOM_AUTH_REQUEST_REJECT, g->member, msg_utf8); + qq_send_cmd_group_auth(g->gc, group, QQ_GROUP_AUTH_REQUEST_REJECT, g->member, msg_utf8); g_free(g); } @@ -112,11 +111,11 @@ g_return_if_fail(g != NULL && g->gc != NULL && g->member > 0); msg1 = g_strdup_printf(_("You rejected %d's request"), g->member); - msg2 = g_strdup(_("Message:")); + msg2 = g_strdup(_("Enter your reason:")); nombre = uid_to_purple_name(g->member); purple_request_input(g->gc, /* title */ NULL, msg1, msg2, - _("Sorry, you are not my style..."), /* multiline */ TRUE, /* masked */ FALSE, + _("Sorry, you are not my type..."), /* multiline */ TRUE, /* masked */ FALSE, /* hint */ NULL, _("Send"), G_CALLBACK(_qq_group_reject_application_real), _("Cancel"), G_CALLBACK(_qq_group_do_nothing_with_struct), @@ -134,7 +133,7 @@ g_return_if_fail(g != NULL && g->gc != NULL && g->id > 0 && g->member > 0); group = qq_room_search_id(g->gc, g->id); g_return_if_fail(group != NULL); - qq_send_cmd_group_auth(g->gc, group, QQ_ROOM_AUTH_REQUEST_APPROVE, g->member, ""); + qq_send_cmd_group_auth(g->gc, group, QQ_GROUP_AUTH_REQUEST_APPROVE, g->member, ""); qq_group_find_or_add_member(g->gc, group, g->member); g_free(g); } @@ -190,9 +189,9 @@ qq_group_find_or_add_member(gc, group, add_members[i]); if (del > 0) - _qq_group_member_opt(gc, group, QQ_ROOM_MEMBER_DEL, del_members); + _qq_group_member_opt(gc, group, QQ_GROUP_MEMBER_DEL, del_members); if (add > 0) - _qq_group_member_opt(gc, group, QQ_ROOM_MEMBER_ADD, add_members); + _qq_group_member_opt(gc, group, QQ_GROUP_MEMBER_ADD, add_members); } void qq_group_process_modify_members_reply(guint8 *data, gint len, PurpleConnection *gc) @@ -210,10 +209,9 @@ group = qq_room_search_id(gc, id); g_return_if_fail(group != NULL); - purple_debug_info("QQ", "Succeed in modify members for room %d\n", group->ext_id); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify members for Qun %d\n", group->ext_id); - purple_notify_info(gc, _("QQ Qun Operation"), - _("You have successfully modified Qun member"), NULL); + purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun member"), NULL); } void qq_room_change_info(PurpleConnection *gc, qq_group *group) @@ -225,8 +223,8 @@ g_return_if_fail(group != NULL); - group_name = group->title_utf8 == NULL ? "" : utf8_to_qq(group->title_utf8, QQ_CHARSET_DEFAULT); - group_desc = group->desc_utf8 == NULL ? "" : utf8_to_qq(group->desc_utf8, QQ_CHARSET_DEFAULT); + group_name = group->group_name_utf8 == NULL ? "" : utf8_to_qq(group->group_name_utf8, QQ_CHARSET_DEFAULT); + group_desc = group->group_desc_utf8 == NULL ? "" : utf8_to_qq(group->group_desc_utf8, QQ_CHARSET_DEFAULT); notice = group->notice_utf8 == NULL ? "" : utf8_to_qq(group->notice_utf8, QQ_CHARSET_DEFAULT); data_len = 64 + strlen(group_name) + strlen(group_desc) + strlen(notice); @@ -239,7 +237,7 @@ /* 007-008 */ bytes += qq_put16(data + bytes, 0x0000); /* 009-010 */ - bytes += qq_put16(data + bytes, group->category); + bytes += qq_put16(data + bytes, group->group_category); bytes += qq_put8(data + bytes, strlen(group_name)); bytes += qq_putdata(data + bytes, (guint8 *) group_name, strlen(group_name)); @@ -253,7 +251,7 @@ bytes += qq_putdata(data + bytes, (guint8 *) group_desc, strlen(group_desc)); if (bytes > data_len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Overflow in qq_room_change_info, max %d bytes, now %d bytes\n", data_len, bytes); return; @@ -276,7 +274,7 @@ group = qq_room_search_id(gc, id); g_return_if_fail(group != NULL); - purple_debug_info("QQ", "Succeed in modify info for Qun %d\n", group->ext_id); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in modify info for Qun %d\n", group->ext_id); qq_group_refresh(gc, group); purple_notify_info(gc, _("QQ Qun Operation"), _("You have successfully modified Qun information"), NULL); @@ -299,9 +297,9 @@ bytes = 0; /* we create the simpleset group, only group name is given */ /* 001 */ - bytes += qq_put8(data + bytes, QQ_ROOM_TYPE_PERMANENT); + bytes += qq_put8(data + bytes, QQ_GROUP_TYPE_PERMANENT); /* 002 */ - bytes += qq_put8(data + bytes, QQ_ROOM_AUTH_TYPE_NEED_AUTH); + bytes += qq_put8(data + bytes, QQ_GROUP_AUTH_TYPE_NEED_AUTH); /* 003-004 */ bytes += qq_put16(data + bytes, 0x0000); /* 005-006 */ @@ -315,7 +313,7 @@ bytes += qq_put32(data + bytes, qd->uid); /* I am member of coz */ if (bytes > data_len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Overflow in qq_room_create, max %d bytes, now %d bytes\n", data_len, bytes); return; @@ -354,14 +352,14 @@ g_return_if_fail(id > 0 && ext_id); group = qq_group_create_internal_record(gc, id, ext_id, NULL); - group->my_role = QQ_ROOM_ROLE_ADMIN; + group->my_status = QQ_GROUP_MEMBER_STATUS_IS_ADMIN; group->creator_uid = qd->uid; qq_group_refresh(gc, group); qq_send_room_cmd_only(gc, QQ_ROOM_CMD_ACTIVATE, id); - qq_room_update(gc, 0, group->id); + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_INFO, id); - purple_debug_info("QQ", "Succeed in create Qun, external ID %d\n", group->ext_id); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in create Qun, external ID %d\n", group->ext_id); g = g_new0(gc_and_uid, 1); g->gc = gc; @@ -370,7 +368,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 up the Qun details now?"), 1, purple_connection_get_account(gc), NULL, NULL, g, 2, @@ -393,7 +391,7 @@ group = qq_room_search_id(gc, id); g_return_if_fail(group != NULL); - purple_debug_info("QQ", "Succeed in activate Qun %d\n", group->ext_id); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Succeed in activate Qun %d\n", group->ext_id); } void qq_group_manage_group(PurpleConnection *gc, GHashTable *data) @@ -404,7 +402,7 @@ g_return_if_fail(data != NULL); - id_ptr = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID); + id_ptr = g_hash_table_lookup(data, QQ_GROUP_KEY_INTERNAL_ID); id = strtol(id_ptr, NULL, 10); g_return_if_fail(id > 0);
--- a/libpurple/protocols/qq/group_opt.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_opt.h Mon Sep 15 03:04:07 2008 +0000 @@ -38,13 +38,13 @@ } group_member_opt; enum { - QQ_ROOM_TYPE_PERMANENT = 0x01, - QQ_ROOM_TYPE_TEMPORARY + QQ_GROUP_TYPE_PERMANENT = 0x01, + QQ_GROUP_TYPE_TEMPORARY }; enum { - QQ_ROOM_MEMBER_ADD = 0x01, - QQ_ROOM_MEMBER_DEL + QQ_GROUP_MEMBER_ADD = 0x01, + QQ_GROUP_MEMBER_DEL }; void qq_group_modify_members(PurpleConnection *gc, qq_group *group, guint32 *new_members);
--- a/libpurple/protocols/qq/group_search.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/group_search.c Mon Sep 15 03:04:07 2008 +0000 @@ -38,8 +38,8 @@ #include "qq_network.h" enum { - QQ_ROOM_SEARCH_TYPE_BY_ID = 0x01, - QQ_ROOM_SEARCH_TYPE_DEMO = 0x02 + QQ_GROUP_SEARCH_TYPE_BY_ID = 0x01, + QQ_GROUP_SEARCH_TYPE_DEMO = 0x02 }; /* send packet to search for qq_group */ @@ -49,7 +49,7 @@ gint bytes = 0; guint8 type; - type = (ext_id == 0x00000000) ? QQ_ROOM_SEARCH_TYPE_DEMO : QQ_ROOM_SEARCH_TYPE_BY_ID; + type = (ext_id == 0x00000000) ? QQ_GROUP_SEARCH_TYPE_DEMO : QQ_GROUP_SEARCH_TYPE_BY_ID; bytes = 0; bytes += qq_put8(raw_data + bytes, type); @@ -63,21 +63,21 @@ PurpleRoomlistRoom *room; gchar field[11]; - room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, group->title_utf8, NULL); + room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, group->group_name_utf8, NULL); g_snprintf(field, sizeof(field), "%d", group->ext_id); purple_roomlist_room_add_field(qd->roomlist, room, field); g_snprintf(field, sizeof(field), "%d", group->creator_uid); purple_roomlist_room_add_field(qd->roomlist, room, field); - purple_roomlist_room_add_field(qd->roomlist, room, group->desc_utf8); + purple_roomlist_room_add_field(qd->roomlist, room, group->group_desc_utf8); g_snprintf(field, sizeof(field), "%d", group->id); purple_roomlist_room_add_field(qd->roomlist, room, field); g_snprintf(field, sizeof(field), "%d", group->type8); purple_roomlist_room_add_field(qd->roomlist, room, field); g_snprintf(field, sizeof(field), "%d", group->auth_type); purple_roomlist_room_add_field(qd->roomlist, room, field); - g_snprintf(field, sizeof(field), "%d", group->category); + g_snprintf(field, sizeof(field), "%d", group->group_category); purple_roomlist_room_add_field(qd->roomlist, room, field); - purple_roomlist_room_add_field(qd->roomlist, room, group->title_utf8); + purple_roomlist_room_add_field(qd->roomlist, room, group->group_name_utf8); purple_roomlist_room_add(qd->roomlist, room); purple_roomlist_set_in_progress(qd->roomlist, FALSE); @@ -109,14 +109,14 @@ bytes += qq_get16(&(unknown), data + bytes); 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_get32(&(group.group_category), data + bytes); + bytes += convert_as_pascal_string(data + bytes, &(group.group_name_utf8), QQ_CHARSET_DEFAULT); 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 += convert_as_pascal_string(data + bytes, &(group.group_desc_utf8), QQ_CHARSET_DEFAULT); /* end of one qq_group */ if(bytes != len) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "group_cmd_search_group: Dangerous error! maybe protocol changed, notify developers!"); } @@ -125,7 +125,7 @@ qq_set_pending_id(&qd->joining_groups, group.ext_id, FALSE); if (qq_room_search_id(gc, group.id) == NULL) qq_group_create_internal_record(gc, - group.id, group.ext_id, group.title_utf8); + group.id, group.ext_id, group.group_name_utf8); qq_send_cmd_group_join_group(gc, &group); } else { _qq_setup_roomlist(qd, &group);
--- a/libpurple/protocols/qq/header_info.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/header_info.c Mon Sep 15 03:04:07 2008 +0000 @@ -122,7 +122,7 @@ case QQ_SERVER_0100: return "QQ Server 0100"; default: - return "Unknown Version"; + return "Unknown"; } } @@ -146,8 +146,8 @@ return "QQ_CMD_DEL_BUDDY"; case QQ_CMD_BUDDY_AUTH: return "QQ_CMD_BUDDY_AUTH"; - case QQ_CMD_CHANGE_STATUS: - return "QQ_CMD_CHANGE_STATUS"; + case QQ_CMD_CHANGE_ONLINE_STATUS: + return "QQ_CMD_CHANGE_ONLINE_STATUS"; case QQ_CMD_ACK_SYS_MSG: return "QQ_CMD_ACK_SYS_MSG"; case QQ_CMD_SEND_IM: @@ -172,10 +172,10 @@ return "QQ_CMD_TOKEN"; case QQ_CMD_RECV_MSG_SYS: return "QQ_CMD_RECV_MSG_SYS"; - case QQ_CMD_BUDDY_CHANGE_STATUS: - return "QQ_CMD_BUDDY_CHANGE_STATUS"; + case QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS: + return "QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS"; default: - return "Unknown CMD"; + return "Unknown"; } } @@ -204,8 +204,8 @@ return "QQ_ROOM_CMD_SEND_MSG"; case QQ_ROOM_CMD_GET_ONLINES: return "QQ_ROOM_CMD_GET_ONLINES"; - case QQ_ROOM_CMD_GET_BUDDIES: - return "QQ_ROOM_CMD_GET_BUDDIES"; + case QQ_ROOM_CMD_GET_MEMBER_INFO: + return "QQ_ROOM_CMD_GET_MEMBER_INFO"; case QQ_ROOM_CMD_CHANGE_CARD: return "QQ_ROOM_CMD_CHANGE_CARD"; case QQ_ROOM_CMD_GET_REALNAMES: @@ -231,6 +231,6 @@ case QQ_ROOM_CMD_TEMP_GET_MEMBERS: return "QQ_ROOM_CMD_TEMP_GET_MEMBERS"; default: - return "Unknown Room Command"; + return "Unknown QQ Room Command"; } }
--- a/libpurple/protocols/qq/header_info.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/header_info.h Mon Sep 15 03:04:07 2008 +0000 @@ -47,7 +47,7 @@ QQ_CMD_ADD_BUDDY_WO_AUTH = 0x0009, /* add buddy without auth */ QQ_CMD_DEL_BUDDY = 0x000a, /* delete a buddy */ QQ_CMD_BUDDY_AUTH = 0x000b, /* buddy authentication */ - QQ_CMD_CHANGE_STATUS = 0x000d, /* change my online status */ + QQ_CMD_CHANGE_ONLINE_STATUS = 0x000d, /* change my online status */ QQ_CMD_ACK_SYS_MSG = 0x0012, /* ack system message */ QQ_CMD_SEND_IM = 0x0016, /* send message */ QQ_CMD_RECV_IM = 0x0017, /* receive message */ @@ -59,11 +59,11 @@ QQ_CMD_GET_BUDDIES_ONLINE = 0x0027, /* get online buddies list */ QQ_CMD_CELL_PHONE_2 = 0x0029, /* cell phone 2 */ QQ_CMD_ROOM = 0x0030, /* room command */ - QQ_CMD_GET_BUDDIES_AND_ROOMS = 0x0058, + QQ_CMD_GET_BUDDIES_AND_ROOMS = 0x0058, QQ_CMD_GET_LEVEL = 0x005C, /* get level for one or more buddies */ QQ_CMD_TOKEN = 0x0062, /* get login token */ QQ_CMD_RECV_MSG_SYS = 0x0080, /* receive a system message */ - QQ_CMD_BUDDY_CHANGE_STATUS = 0x0081, /* buddy change status */ + QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS = 0x0081, /* buddy change status */ }; const gchar *qq_get_cmd_desc(gint type); @@ -80,7 +80,7 @@ QQ_ROOM_CMD_QUIT = 0x09, QQ_ROOM_CMD_SEND_MSG = 0x0a, QQ_ROOM_CMD_GET_ONLINES = 0x0b, - QQ_ROOM_CMD_GET_BUDDIES = 0x0c, + QQ_ROOM_CMD_GET_MEMBER_INFO = 0x0c, QQ_ROOM_CMD_CHANGE_CARD = 0x0E, QQ_ROOM_CMD_GET_REALNAMES = 0x0F,
--- a/libpurple/protocols/qq/im.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/im.c Mon Sep 15 03:04:07 2008 +0000 @@ -209,17 +209,21 @@ 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_FROM_BUDDY_2006: - return "QQ_RECV_IM_FROM_BUDDY_2006"; - case QQ_RECV_IM_FROM_UNKNOWN_2006: - return "QQ_RECV_IM_FROM_UNKNOWN_2006"; default: return "QQ_RECV_IM_UNKNOWN"; } } +/* when we receive a message, + * we send an ACK which is the first 16 bytes of incoming packet */ +static void _qq_send_packet_recv_im_ack(PurpleConnection *gc, guint16 seq, guint8 *data) +{ + qq_data *qd; + + qd = (qq_data *) gc->proto_data; + qq_send_cmd_detail(qd, QQ_CMD_RECV_IM, seq, FALSE, data, 16); +} + /* read the common parts of the normal_im, * returns the bytes read if succeed, or -1 if there is any error */ static gint _qq_normal_im_common_read(guint8 *data, gint len, qq_recv_normal_im_common *common) @@ -236,61 +240,13 @@ bytes += qq_get16(&(common->normal_im_type), data + bytes); if (bytes != 28) { /* read common place fail */ - purple_debug_error("QQ", "Expect 28 bytes, read %d bytes\n", bytes); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Expect 28 bytes, read %d bytes\n", bytes); return -1; } return bytes; } -static void _qq_process_recv_news(guint8 *data, gint data_len, PurpleConnection *gc) -{ - qq_data *qd = (qq_data *) gc->proto_data; - gint bytes; - guint8 *temp; - guint8 temp_len; - gchar *title, *brief, *url; - gchar *content, *content_utf8; - - g_return_if_fail(data != NULL && data_len != 0); - -#if 0 - qq_show_packet("Rcv news", data, data_len); -#endif - - temp = g_newa(guint8, data_len); - bytes = 4; // ignore unknown 4 bytes - - bytes += qq_get8(&temp_len, data + bytes); - g_return_if_fail(bytes + temp_len <= data_len); - bytes += qq_getdata(temp, temp_len, data+bytes); - title = g_strndup((gchar *)temp, temp_len); - - bytes += qq_get8(&temp_len, data + bytes); - g_return_if_fail(bytes + temp_len <= data_len); - bytes += qq_getdata(temp, temp_len, data+bytes); - brief = g_strndup((gchar *)temp, temp_len); - - bytes += qq_get8(&temp_len, data + bytes); - g_return_if_fail(bytes + temp_len <= data_len); - bytes += qq_getdata(temp, temp_len, data+bytes); - url = g_strndup((gchar *)temp, temp_len); - - content = g_strdup_printf(_("Title: %s\nBrief: %s\n\n%s"), title, brief, url); - content_utf8 = qq_to_utf8(content, QQ_CHARSET_DEFAULT); - - if (qd->is_show_news) { - purple_notify_info(gc, NULL, _("QQ Server News"), content_utf8); - } else { - purple_debug_info("QQ", "QQ Server news:\n%s", content_utf8); - } - g_free(title); - g_free(brief); - g_free(url); - g_free(content); - g_free(content_utf8); -} - /* process received normal text IM */ static void _qq_process_recv_normal_im_text(guint8 *data, gint len, qq_recv_normal_im_common *common, PurpleConnection *gc) { @@ -310,7 +266,7 @@ /* now it is QQ_NORMAL_IM_TEXT */ /* if (*cursor >= (data + len - 1)) { - purple_debug_warning("QQ", "Received normal IM text is empty\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received normal IM text is empty\n"); return; } else */ @@ -357,9 +313,9 @@ } qq_b = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; if (qq_b != NULL) { - qq_b->client_version = common->sender_ver; + qq_b->client_version = common->sender_ver; } - + purple_msg_type = (im_text->msg_type == QQ_IM_AUTO_REPLY) ? PURPLE_MESSAGE_AUTO_RESP : 0; msg_with_purple_smiley = qq_smiley_to_purple(im_text->msg); @@ -394,18 +350,19 @@ bytes = _qq_normal_im_common_read(data, len, common); if (bytes < 0) { - purple_debug_error("QQ", "Fail read the common part of normal IM\n"); + purple_debug (PURPLE_DEBUG_ERROR, "QQ", + "Fail read the common part of normal IM\n"); return; } switch (common->normal_im_type) { case QQ_NORMAL_IM_TEXT: - purple_debug_info("QQ", + purple_debug (PURPLE_DEBUG_INFO, "QQ", "Normal IM, text type:\n [%d] => [%d], src: %s (%04X)\n", common->sender_uid, common->receiver_uid, qq_get_ver_desc (common->sender_ver), common->sender_ver); if (bytes >= len - 1) { - purple_debug_warning("QQ", "Received normal IM text is empty\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received normal IM text is empty\n"); return; } _qq_process_recv_normal_im_text(data + bytes, len - bytes, common, gc); @@ -425,50 +382,16 @@ case QQ_NORMAL_IM_FILE_NOTIFY: qq_process_recv_file_notify(data + bytes, len - bytes, common->sender_uid, gc); break; - case QQ_NORMAL_IM_FILE_REQUEST_TCP: - /* Check ReceivedFileIM::parseContents in eva*/ - /* some client use this function for detect invisable buddy*/ - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_REQUEST_TCP\n"); - qq_show_packet ("Not support", data, len); - break; - case QQ_NORMAL_IM_FILE_APPROVE_TCP: - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_APPROVE_TCP\n"); - qq_show_packet ("Not support", data, len); - break; - case QQ_NORMAL_IM_FILE_REJECT_TCP: - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_REJECT_TCP\n"); - qq_show_packet ("Not support", data, len); - break; - case QQ_NORMAL_IM_FILE_PASV: - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_PASV\n"); - qq_show_packet ("Not support", data, len); - break; - case QQ_NORMAL_IM_FILE_EX_REQUEST_UDP: - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_REQUEST_TCP\n"); - qq_show_packet ("QQ", data, len); - break; - case QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT: - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_EX_REQUEST_ACCEPT\n"); - qq_show_packet ("QQ", data, len); - break; - case QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL: - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_EX_REQUEST_CANCEL\n"); - qq_show_packet ("Not support", data, len); - break; - case QQ_NORMAL_IM_FILE_EX_NOTIFY_IP: - purple_debug_warning("QQ", "Normal IM, not support QQ_NORMAL_IM_FILE_EX_NOTIFY_IP\n"); - qq_show_packet ("Not support", data, len); - break; default: im_unprocessed = g_newa (qq_recv_normal_im_unprocessed, 1); im_unprocessed->common = common; im_unprocessed->unknown = data + bytes; im_unprocessed->length = len - bytes; /* a simple process here, maybe more later */ - purple_debug_warning("QQ", + purple_debug (PURPLE_DEBUG_WARNING, "QQ", "Normal IM, unprocessed type [0x%04x], len %d\n", common->normal_im_type, im_unprocessed->length); - qq_show_packet ("QQ", im_unprocessed->unknown, im_unprocessed->length); + qq_show_packet ("QQ unk-im", im_unprocessed->unknown, im_unprocessed->length); return; } } @@ -489,7 +412,7 @@ reply = strtol(segments[0], NULL, 10); if (reply == QQ_RECV_SYS_IM_KICK_OUT) - purple_debug_warning("QQ", "We are kicked out by QQ server\n"); + purple_debug(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); } @@ -552,7 +475,7 @@ g_datalist_clear(&attribs); } - purple_debug_info("QQ_MESG", "send mesg: %s\n", msg); + purple_debug(PURPLE_DEBUG_INFO, "QQ_MESG", "send mesg: %s\n", msg); msg_filtered = purple_markup_strip_html(msg); msg_len = strlen(msg_filtered); now = time(NULL); @@ -603,9 +526,9 @@ qq_show_packet("QQ_raw_data debug", raw_data, bytes); if (bytes == raw_len) /* create packet OK */ - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); + qq_send_cmd(qd, QQ_CMD_SEND_IM, raw_data, bytes); else - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail creating send_im packet, expect %d bytes, build %d bytes\n", raw_len, bytes); if (font_color) @@ -626,10 +549,10 @@ qd = gc->proto_data; if (data[0] != QQ_SEND_IM_REPLY_OK) { - purple_debug_warning("QQ", "Send IM fail\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Send IM fail\n"); purple_notify_error(gc, _("Error"), _("Failed to send IM."), NULL); } else { - purple_debug_info("QQ", "IM ACK OK\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "IM ACK OK\n"); } } @@ -646,17 +569,16 @@ qd = (qq_data *) gc->proto_data; if (data_len < 16) { /* we need to ack with the first 16 bytes */ - purple_debug_error("QQ", "MSG is too short\n"); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "IM is too short\n"); return; } else { - /* when we receive a message, - * we send an ACK which is the first 16 bytes of incoming packet */ - qq_send_server_reply(gc, QQ_CMD_RECV_IM, seq, data, 16); + _qq_send_packet_recv_im_ack(gc, seq, data); } /* check len first */ if (data_len < 20) { /* length of im_header */ - purple_debug_error("QQ", "Invald MSG header, len %d < 20\n", data_len); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "Fail read recv IM header, len should longer than 20 bytes, read %d bytes\n", data_len); return; } @@ -672,71 +594,77 @@ /* im_header prepared */ if (im_header->receiver_uid != qd->uid) { /* should not happen */ - purple_debug_error("QQ", "MSG to [%d], NOT me\n", im_header->receiver_uid); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "IM to [%d], NOT me\n", im_header->receiver_uid); return; } /* check bytes */ if (bytes >= data_len - 1) { - purple_debug_warning("QQ", "Empty MSG\n"); + purple_debug (PURPLE_DEBUG_WARNING, "QQ", "Received IM is empty\n"); return; } switch (im_header->im_type) { - case QQ_RECV_IM_NEWS: - _qq_process_recv_news(data + bytes, data_len - bytes, gc); + case QQ_RECV_IM_TO_BUDDY: + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM from buddy [%d], I am in his/her buddy list\n", im_header->sender_uid); + _qq_process_recv_normal_im(data + bytes, data_len - bytes, gc); /* position and rest length */ break; - case QQ_RECV_IM_FROM_BUDDY_2006: - case QQ_RECV_IM_FROM_UNKNOWN_2006: case QQ_RECV_IM_TO_UNKNOWN: - case QQ_RECV_IM_TO_BUDDY: - purple_debug_info("QQ", "MSG from buddy [%d]\n", im_header->sender_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM from buddy [%d], I am a stranger to him/her\n", im_header->sender_uid); _qq_process_recv_normal_im(data + bytes, data_len - bytes, gc); break; case QQ_RECV_IM_UNKNOWN_QUN_IM: case QQ_RECV_IM_TEMP_QUN_IM: case QQ_RECV_IM_QUN_IM: - purple_debug_info("QQ", "MSG from room [%d]\n", im_header->sender_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "IM from group, internal_id [%d]\n", im_header->sender_uid); /* sender_uid is in fact id */ - qq_process_room_msg_normal(data + bytes, data_len - bytes, im_header->sender_uid, gc, im_header->im_type); + qq_process_recv_group_im(data + bytes, data_len - bytes, im_header->sender_uid, gc, im_header->im_type); break; case QQ_RECV_IM_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from [%d], Added\n", im_header->sender_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM from group, added by group internal_id [%d]\n", im_header->sender_uid); /* sender_uid 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, im_header->sender_uid, gc); + qq_process_recv_group_im_been_added(data + bytes, data_len - bytes, im_header->sender_uid, gc); break; case QQ_RECV_IM_DEL_FROM_QUN: - purple_debug_info("QQ", "Notice from room [%d], Removed\n", im_header->sender_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM from group, removed by group internal_ID [%d]\n", im_header->sender_uid); /* sender_uid is group id */ - qq_process_room_msg_been_removed(data + bytes, data_len - bytes, im_header->sender_uid, gc); + qq_process_recv_group_im_been_removed(data + bytes, data_len - bytes, im_header->sender_uid, gc); break; case QQ_RECV_IM_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Joined\n", im_header->sender_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM from group, apply to join group internal_ID [%d]\n", im_header->sender_uid); /* sender_uid is group id */ - qq_process_room_msg_apply_join(data + bytes, data_len - bytes, im_header->sender_uid, gc); + qq_process_recv_group_im_apply_join(data + bytes, data_len - bytes, im_header->sender_uid, gc); break; case QQ_RECV_IM_APPROVE_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Confirm add in\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM for group system info, approved by group internal_id [%d]\n", im_header->sender_uid); /* sender_uid is group id */ - qq_process_room_msg_been_approved(data + bytes, data_len - bytes, im_header->sender_uid, gc); + qq_process_recv_group_im_been_approved(data + bytes, data_len - bytes, im_header->sender_uid, gc); break; case QQ_RECV_IM_REJCT_APPLY_ADD_TO_QUN: - purple_debug_info("QQ", "Notice from room [%d], Refuse add in\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM for group system info, rejected by group internal_id [%d]\n", im_header->sender_uid); /* sender_uid is group id */ - qq_process_room_msg_been_rejected(data + bytes, data_len - bytes, im_header->sender_uid, gc); + qq_process_recv_group_im_been_rejected(data + bytes, data_len - bytes, im_header->sender_uid, gc); break; case QQ_RECV_IM_SYS_NOTIFICATION: - purple_debug_info("QQ", "Admin notice from [%d]\n", im_header->sender_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "IM from [%d], should be a system administrator\n", im_header->sender_uid); _qq_process_recv_sys_im(data + bytes, data_len - bytes, gc); break; default: - purple_debug_warning("QQ", "MSG from [%d], unknown type %s [0x%02x]\n", - im_header->sender_uid, qq_get_recv_im_type_str(im_header->im_type), - im_header->im_type); - qq_show_packet("Unknown MSG type", data, data_len); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "IM from [%d], [0x%02x] %s is not processed\n", + im_header->sender_uid, + im_header->im_type, qq_get_recv_im_type_str(im_header->im_type)); } }
--- a/libpurple/protocols/qq/im.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/im.h Mon Sep 15 03:04:07 2008 +0000 @@ -41,7 +41,6 @@ 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, @@ -51,9 +50,7 @@ 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_FROM_BUDDY_2006 = 0x0084, - QQ_RECV_IM_FROM_UNKNOWN_2006 = 0x0085, + QQ_RECV_IM_SYS_NOTIFICATION = 0x0030 }; guint8 *qq_get_send_im_tail(const gchar *font_color,
--- a/libpurple/protocols/qq/packet_parse.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/packet_parse.c Mon Sep 15 03:04:07 2008 +0000 @@ -46,8 +46,8 @@ memcpy(&b_dest, buf, sizeof(b_dest)); *b = b_dest; #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][get8] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][get8] b_dest 0x%2x, *b 0x%02x\n", b_dest, *b); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get8] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get8] b_dest 0x%2x, *b 0x%02x\n", b_dest, *b); #endif return sizeof(b_dest); } @@ -61,8 +61,8 @@ memcpy(&w_dest, buf, sizeof(w_dest)); *w = g_ntohs(w_dest); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][get16] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][get16] w_dest 0x%04x, *w 0x%04x\n", w_dest, *w); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get16] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get16] w_dest 0x%04x, *w 0x%04x\n", w_dest, *w); #endif return sizeof(w_dest); } @@ -75,8 +75,8 @@ memcpy(&dw_dest, buf, sizeof(dw_dest)); *dw = g_ntohl(dw_dest); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][get32] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][get32] dw_dest 0x%08x, *dw 0x%08x\n", dw_dest, *dw); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get32] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][get32] dw_dest 0x%08x, *dw 0x%08x\n", dw_dest, *dw); #endif return sizeof(dw_dest); } @@ -93,7 +93,7 @@ { memcpy(data, buf, datalen); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][getdata] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getdata] buf %p\n", (void *)buf); #endif return datalen; } @@ -107,12 +107,12 @@ guint32 dw_dest; memcpy(&dw_dest, buf, sizeof(dw_dest)); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][getime] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][getime] dw_dest before 0x%08x\n", dw_dest); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getime] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getime] dw_dest before 0x%08x\n", dw_dest); #endif dw_dest = g_ntohl(dw_dest); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][getime] dw_dest after 0x%08x\n", dw_dest); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][getime] dw_dest after 0x%08x\n", dw_dest); #endif memcpy(t, &dw_dest, sizeof(dw_dest)); return sizeof(dw_dest); @@ -125,8 +125,8 @@ { memcpy(buf, &b, sizeof(b)); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][put8] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][put8] b 0x%02x\n", b); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put8] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put8] b 0x%02x\n", b); #endif return sizeof(b); } @@ -139,8 +139,8 @@ guint16 w_porter; w_porter = g_htons(w); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][put16] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][put16] w 0x%04x, w_porter 0x%04x\n", w, w_porter); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put16] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put16] w 0x%04x, w_porter 0x%04x\n", w, w_porter); #endif memcpy(buf, &w_porter, sizeof(w_porter)); return sizeof(w_porter); @@ -154,8 +154,8 @@ guint32 dw_porter; dw_porter = g_htonl(dw); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][put32] buf %p\n", (void *)buf); - purple_debug_info("QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put32] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][put32] dw 0x%08x, dw_porter 0x%08x\n", dw, dw_porter); #endif memcpy(buf, &dw_porter, sizeof(dw_porter)); return sizeof(dw_porter); @@ -173,7 +173,7 @@ { memcpy(buf, data, datalen); #ifdef PARSER_DEBUG - purple_debug_info("QQ", "[DBG][putdata] buf %p\n", (void *)buf); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "[DBG][putdata] buf %p\n", (void *)buf); #endif return datalen; }
--- a/libpurple/protocols/qq/qq.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq.c Mon Sep 15 03:04:07 2008 +0000 @@ -24,6 +24,10 @@ #include "internal.h" +#ifdef _WIN32 +#define random rand +#endif + #include "accountopt.h" #include "debug.h" #include "notify.h" @@ -58,72 +62,79 @@ #define OPENQ_AUTHOR "Puzzlebird" #define OPENQ_WEBSITE "http://openq.sourceforge.net" -static GList *server_list_build(gchar select) -{ - GList *list = NULL; +#define QQ_TCP_PORT 8000 +#define QQ_UDP_PORT 8000 - if ( select == 'T' || select == 'A') { - list = g_list_append(list, "tcpconn.tencent.com:8000"); - list = g_list_append(list, "tcpconn2.tencent.com:8000"); - list = g_list_append(list, "tcpconn3.tencent.com:8000"); - list = g_list_append(list, "tcpconn4.tencent.com:8000"); - list = g_list_append(list, "tcpconn5.tencent.com:8000"); - list = g_list_append(list, "tcpconn6.tencent.com:8000"); - } - if ( select == 'U' || select == 'A') { - list = g_list_append(list, "sz.tencent.com:8000"); - list = g_list_append(list, "sz2.tencent.com:8000"); - list = g_list_append(list, "sz3.tencent.com:8000"); - list = g_list_append(list, "sz4.tencent.com:8000"); - list = g_list_append(list, "sz5.tencent.com:8000"); - list = g_list_append(list, "sz6.tencent.com:8000"); - list = g_list_append(list, "sz7.tencent.com:8000"); - list = g_list_append(list, "sz8.tencent.com:8000"); - list = g_list_append(list, "sz9.tencent.com:8000"); - } - return list; -} - -static void server_list_create(PurpleAccount *account) -{ +static void server_list_create(PurpleAccount *account) { PurpleConnection *gc; qq_data *qd; - PurpleProxyInfo *gpi; const gchar *user_server; + int port; + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Create server list\n"); gc = purple_account_get_connection(account); g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = gc->proto_data; - gpi = purple_proxy_get_setup(account); - - qd->use_tcp = TRUE; - if (purple_proxy_info_get_type(gpi) == PURPLE_PROXY_UDP) { - qd->use_tcp = FALSE; + qd->use_tcp = purple_account_get_bool(account, "use_tcp", TRUE); + port = purple_account_get_int(account, "port", 0); + if (port == 0) { + if (qd->use_tcp) { + port = QQ_TCP_PORT; + } else { + port = QQ_UDP_PORT; + } } + qd->user_port = port; + g_return_if_fail(qd->user_server == NULL); user_server = purple_account_get_string(account, "server", NULL); - purple_debug_info("QQ", "Select server '%s'\n", user_server); - if ( (user_server != NULL && strlen(user_server) > 0) && strcasecmp(user_server, "auto") != 0) { - qd->servers = g_list_append(qd->servers, g_strdup(user_server)); - return; + if (user_server != NULL && strlen(user_server) > 0) { + qd->user_server = g_strdup(user_server); } + if (qd->user_server != NULL) { + qd->servers = g_list_append(qd->servers, qd->user_server); + return; + } if (qd->use_tcp) { - qd->servers = server_list_build('T'); + qd->servers = g_list_append(qd->servers, "tcpconn.tencent.com"); + qd->servers = g_list_append(qd->servers, "tcpconn2.tencent.com"); + qd->servers = g_list_append(qd->servers, "tcpconn3.tencent.com"); + qd->servers = g_list_append(qd->servers, "tcpconn4.tencent.com"); + qd->servers = g_list_append(qd->servers, "tcpconn5.tencent.com"); + qd->servers = g_list_append(qd->servers, "tcpconn6.tencent.com"); return; } - - qd->servers = server_list_build('U'); + + qd->servers = g_list_append(qd->servers, "sz.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz2.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz3.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz4.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz5.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz6.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz7.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz8.tencent.com"); + qd->servers = g_list_append(qd->servers, "sz9.tencent.com"); } -static void server_list_remove_all(qq_data *qd) -{ +static void server_list_remove_all(qq_data *qd) { g_return_if_fail(qd != NULL); - purple_debug_info("QQ", "free server list\n"); + if (qd->real_hostname) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n"); + g_free(qd->real_hostname); + qd->real_hostname = NULL; + } + + if (qd->user_server != NULL) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "free user_server\n"); + g_free(qd->user_server); + qd->user_server = NULL; + } + + purple_debug(PURPLE_DEBUG_INFO, "QQ", "free server list\n"); g_list_free(qd->servers); - qd->curr_server = NULL; } static void qq_login(PurpleAccount *account) @@ -140,7 +151,6 @@ gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_AUTO_RESP; qd = g_new0(qq_data, 1); - memset(qd, 0, sizeof(qq_data)); qd->gc = gc; gc->proto_data = qd; @@ -155,31 +165,10 @@ } server_list_create(account); - purple_debug_info("QQ", "Server list has %d\n", g_list_length(qd->servers)); - - qd->is_show_notice = purple_account_get_bool(account, "show_notice", TRUE); - qd->is_show_news = purple_account_get_bool(account, "show_news", TRUE); - - qd->itv_config.resend = purple_account_get_int(account, "resend_interval", 10); - if (qd->itv_config.resend <= 0) qd->itv_config.resend = 10; - - qd->itv_config.keep_alive = purple_account_get_int(account, "keep_alive_interval", 60); - if (qd->itv_config.keep_alive < 30) qd->itv_config.keep_alive = 30; - qd->itv_config.keep_alive /= qd->itv_config.resend; - qd->itv_count.keep_alive = qd->itv_config.keep_alive; + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "Server list has %d\n", g_list_length(qd->servers)); - qd->itv_config.update = purple_account_get_int(account, "update_interval", 300); - if (qd->itv_config.update > 0) { - if (qd->itv_config.update < qd->itv_config.keep_alive) { - qd->itv_config.update = qd->itv_config.keep_alive; - } - qd->itv_config.update /= qd->itv_config.resend; - qd->itv_count.update = qd->itv_config.update; - } else { - qd->itv_config.update = 0; - } - - qd->connect_watcher = purple_timeout_add_seconds(0, qq_connect_later, gc); + qq_connect(account); } /* clean up the given QQ connection and free all resources */ @@ -190,20 +179,12 @@ g_return_if_fail(gc != NULL && gc->proto_data); qd = gc->proto_data; - if (qd->check_watcher > 0) { - purple_timeout_remove(qd->check_watcher); - qd->check_watcher = 0; - } + qq_disconnect(gc); - if (qd->connect_watcher > 0) { - purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = 0; - } + server_list_remove_all(qd); + + g_free(qd); - qq_disconnect(gc); - server_list_remove_all(qd); - - g_free(qd); gc->proto_data = NULL; } @@ -231,7 +212,7 @@ g_string_append(status, _("Offline")); break; case QQ_BUDDY_ONLINE_NORMAL: - g_string_append(status, _("Online")); + return NULL; break; /* TODO What does this status mean? Labelling it as offline... */ case QQ_BUDDY_ONLINE_OFFLINE: @@ -322,8 +303,8 @@ g_string_append( str, _(" Video") ); } - if (q_bud->ext_flag & QQ_EXT_FLAG_ZONE) { - g_string_append( str, _(" Zone") ); + if (q_bud->ext_flag & QQ_EXT_FLAG_SPACE) { + g_string_append( str, _(" Space") ); } purple_notify_user_info_add_pair(user_info, _("Flag"), str->str); @@ -348,7 +329,7 @@ { /* each char** are refering to a filename in pixmaps/purple/status/default/ */ qq_buddy *q_bud; - + if (!b || !(q_bud = b->proto_data)) { return NULL; } @@ -393,11 +374,11 @@ } /* initiate QQ away with proper change_status packet */ -static void _qq_change_status(PurpleAccount *account, PurpleStatus *status) +static void _qq_set_away(PurpleAccount *account, PurpleStatus *status) { PurpleConnection *gc = purple_account_get_connection(account); - qq_request_change_status(gc, 0); + qq_send_packet_change_status(gc); } /* IMPORTANT: PurpleConvImFlags -> PurpleMessageFlags */ @@ -463,7 +444,7 @@ uid = purple_name_to_uid(who); if (uid <= 0) { - purple_debug_error("QQ", "Not valid QQid: %s\n", who); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Not valid QQid: %s\n", who); purple_notify_error(gc, NULL, _("Invalid name"), NULL); return; } @@ -535,8 +516,9 @@ g_string_append(info, "<hr>\n"); - g_string_append_printf(info, _("<b>Server</b>: %s<br>\n"), qd->curr_server); + g_string_append_printf(info, _("<b>Server</b>: %s: %d<br>\n"), qd->server_name, qd->real_port); g_string_append_printf(info, _("<b>Connection Mode</b>: %s<br>\n"), qd->use_tcp ? "TCP" : "UDP"); + g_string_append_printf(info, _("<b>Real hostname</b>: %s: %d<br>\n"), qd->real_hostname, qd->real_port); g_string_append_printf(info, _("<b>My Public IP</b>: %s<br>\n"), inet_ntoa(qd->my_ip)); g_string_append(info, "<hr>\n"); @@ -651,7 +633,7 @@ 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(_("Leave this QQ Qun"), PURPLE_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL); m = g_list_append(m, act); /* TODO: enable this @@ -726,7 +708,7 @@ NULL, /* set_info */ NULL, /* send_typing */ _qq_get_info, /* get_info */ - _qq_change_status, /* change status */ + _qq_set_away, /* set_away */ NULL, /* set_idle */ NULL, /* change_passwd */ qq_add_buddy, /* add_buddy */ @@ -818,50 +800,17 @@ static void init_plugin(PurplePlugin *plugin) { PurpleAccountOption *option; - PurpleKeyValuePair *kvp; - GList *list = NULL; - GList *kvlist = NULL; - GList *entry; - 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"); - - kvlist = NULL; - kvp = g_new0(PurpleKeyValuePair, 1); - kvp->key = g_strdup(_("Auto")); - kvp->value = g_strdup("auto"); - kvlist = g_list_append(kvlist, kvp); - - entry = list; - while(entry) { - if (entry->data != NULL && strlen(entry->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); - } - entry = entry->next; - } - - /* option = purple_account_option_string_new(_("Server"), "server", NULL); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_int_new(_("Port"), "port", 0); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - */ - option = purple_account_option_list_new(_("Server"), "server", kvlist); + + option = purple_account_option_bool_new(_("Connect using TCP"), "use_tcp", TRUE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - option = purple_account_option_bool_new(_("Show server notice"), "show_notice", TRUE); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); - - 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(_("Resend interval(s)"), "resend_interval", 10); + option = purple_account_option_int_new(_("resend interval(s)"), "resend_interval", 10); 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); @@ -874,7 +823,6 @@ 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/prompt_group_msg_on_recv", TRUE); - } PURPLE_INIT_PLUGIN(qq, init_plugin, info);
--- a/libpurple/protocols/qq/qq.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq.h Mon Sep 15 03:04:07 2008 +0000 @@ -36,11 +36,6 @@ #define QQ_KEY_LENGTH 16 -#ifdef _WIN32 -const char *qq_win32_buddy_icon_dir(void); -#define QQ_BUDDY_ICON_DIR qq_win32_buddy_icon_dir() -#endif - typedef struct _qq_data qq_data; typedef struct _qq_buddy qq_buddy; typedef struct _qq_interval qq_interval; @@ -68,46 +63,45 @@ guint16 timeRemainder; time_t signon; time_t idle; - time_t last_update; + time_t last_refresh; gint8 role; /* role in group, used only in group->members list */ }; -typedef struct _qq_connection qq_connection; -struct _qq_connection { - int fd; /* socket file handler */ - int input_handler; - - /* tcp related */ - int can_write_handler; /* use in tcp_send_out */ - PurpleCircBuffer *tcp_txbuf; - guint8 *tcp_rxqueue; - int tcp_rxlen; -}; - struct _qq_data { PurpleConnection *gc; - GSList *openconns; - gboolean use_tcp; /* network in tcp or udp */ - PurpleProxyConnectData *conn_data; - gint fd; /* socket file handler */ - + /* common network resource */ GList *servers; - gchar *curr_server; /* point to servers->data, do not free*/ + gchar *user_server; + gint user_port; + gboolean use_tcp; /* network in tcp or udp */ - struct in_addr redirect_ip; - guint16 redirect_port; - guint check_watcher; - guint connect_watcher; - gint connect_retry; + gchar *server_name; + gboolean is_redirect; + gchar *real_hostname; /* from real connction */ + guint16 real_port; + guint reconnect_timeout; + gint reconnect_times; + + PurpleProxyConnectData *connect_data; + gint fd; /* socket file handler */ + gint tx_handler; /* socket can_write handle, use in udp connecting and tcp send out */ qq_interval itv_config; qq_interval itv_count; - guint network_watcher; + guint network_timeout; GList *transactions; /* check ack packet and resend */ + /* tcp related */ + PurpleCircBuffer *tcp_txbuf; + guint8 *tcp_rxqueue; + int tcp_rxlen; + + /* udp related */ + PurpleDnsQueryData *udp_query_data; + guint32 uid; /* QQ number */ guint8 *token; /* get from server*/ int token_len; @@ -118,8 +112,7 @@ guint16 send_seq; /* send sequence number */ guint8 login_mode; /* online of invisible */ - gboolean is_login; /* used by qq-add_buddy */ - gboolean is_finish_update; + gboolean logged_in; /* used by qq-add_buddy */ PurpleXfer *xfer; /* file transfer handler */ @@ -150,9 +143,6 @@ /* TODO pass qq_send_packet_get_info() a callback and use signals to get rid of these */ gboolean modifying_info; gboolean modifying_face; - - gboolean is_show_notice; - gboolean is_show_news; }; #endif
--- a/libpurple/protocols/qq/qq_base.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_base.c Mon Sep 15 03:04:07 2008 +0000 @@ -48,7 +48,7 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0x14, 0x11, 0x20, 0x03, 0x9d, 0xb2, 0xe6, 0xb3, 0x11, 0xb7, 0x13, - 0x95, 0x67, 0xda, 0x2c, 0x01 + 0x95, 0x67, 0xda, 0x2c, 0x01 }; */ /* for QQ 2003iii 0304, fixed value */ @@ -139,7 +139,7 @@ { guint8 src[QQ_KEY_LENGTH + QQ_KEY_LENGTH]; gint bytes = 0; - + bytes += qq_put32(src + bytes, uid); bytes += qq_putdata(src + bytes, session_key, QQ_KEY_LENGTH); @@ -161,7 +161,7 @@ bytes += qq_get8(&lrop.result, data + bytes); /* 001-016: session key */ bytes += qq_getdata(lrop.session_key, sizeof(lrop.session_key), data + bytes); - purple_debug_info("QQ", "Got session_key\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Got session_key\n"); /* 017-020: login uid */ bytes += qq_get32(&lrop.uid, data + bytes); /* 021-024: server detected user public IP */ @@ -200,16 +200,16 @@ bytes += qq_getdata((guint8 *) &lrop.unknown6, 8, data + bytes); if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */ - purple_debug_warning("QQ", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Fail parsing login info, expect %d bytes, read %d bytes\n", QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); } /* but we still go on as login OK */ memcpy(qd->session_key, lrop.session_key, sizeof(qd->session_key)); get_session_md5(qd->session_md5, qd->uid, qd->session_key); - + qd->my_ip.s_addr = lrop.client_ip.s_addr; - + qd->my_port = lrop.client_port; qd->login_time = lrop.login_time; qd->last_login_time = lrop.last_login_time; @@ -237,19 +237,39 @@ bytes += qq_get16(&lrrp.new_server_port, data + bytes); if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) { - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); return QQ_LOGIN_REPLY_ERR_MISC; } - + /* redirect to new server, do not disconnect or connect here * those connect should be called at packet_process */ - qd->redirect_ip.s_addr = lrrp.new_server_ip.s_addr; - qd->redirect_port = lrrp.new_server_port; + if (qd->real_hostname) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n"); + g_free(qd->real_hostname); + qd->real_hostname = NULL; + } + qd->real_hostname = g_strdup( inet_ntoa(lrrp.new_server_ip) ); + qd->real_port = lrrp.new_server_port; + return QQ_LOGIN_REPLY_REDIRECT; } +/* process login reply which says wrong password */ +static gint8 process_login_wrong_pwd(PurpleConnection *gc, guint8 *data, gint len) +{ + gchar *server_reply, *server_reply_utf8; + server_reply = g_new0(gchar, len); + g_memmove(server_reply, data + 1, len - 1); + server_reply_utf8 = qq_to_utf8(server_reply, QQ_CHARSET_DEFAULT); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Wrong password, server msg in UTF8: %s\n", server_reply_utf8); + g_free(server_reply); + g_free(server_reply_utf8); + + return QQ_LOGIN_REPLY_ERR_PWD; +} + /* request before login */ void qq_send_packet_token(PurpleConnection *gc) { @@ -261,9 +281,9 @@ qd = (qq_data *) gc->proto_data; bytes += qq_put8(buf + bytes, 0); - + qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_TOKEN, qd->send_seq, buf, bytes, TRUE); + qq_send_data(qd, QQ_CMD_TOKEN, qd->send_seq, TRUE, buf, bytes); } /* send login packet to QQ server */ @@ -292,14 +312,14 @@ memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH); encrypted_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */ - + bytes = 0; /* now generate the encrypted data * 000-015 use password_twice_md5 as key to encrypt empty string */ encrypted_len = qq_encrypt(raw_data + bytes, (guint8 *) "", 0, qd->password_twice_md5); g_return_if_fail(encrypted_len == 16); bytes += encrypted_len; - + /* 016-016 */ bytes += qq_put8(raw_data + bytes, 0x00); /* 017-020, used to be IP, now zero */ @@ -329,15 +349,14 @@ bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len); qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); + qq_send_data(qd, QQ_CMD_LOGIN, qd->send_seq, TRUE, buf, bytes); } -guint8 qq_process_token_reply(PurpleConnection *gc, guint8 *buf, gint buf_len) +guint8 qq_process_token_reply(PurpleConnection *gc, gchar *error_msg, guint8 *buf, gint buf_len) { qq_data *qd; guint8 ret; int token_len; - gchar *error_msg; g_return_val_if_fail(buf != NULL && buf_len != 0, -1); @@ -345,37 +364,30 @@ qd = (qq_data *) gc->proto_data; ret = buf[0]; - + if (ret != QQ_TOKEN_REPLY_OK) { - purple_debug_error("QQ", "Failed to request token: %d\n", buf[0]); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown request login token reply code : %d\n", buf[0]); qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", buf, buf_len, ">>> [default] decrypt and dump"); error_msg = try_dump_as_gbk(buf, buf_len); - if (error_msg == NULL) { - error_msg = g_strdup_printf( _("Invalid token reply code, 0x%02X"), ret); - } - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); - g_free(error_msg); return ret; } - + token_len = buf_len-2; if (token_len <= 0) { error_msg = g_strdup_printf( _("Invalid token len, %d"), token_len); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); - g_free(error_msg); return -1; } - + if (buf[1] != token_len) { - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Invalid token len. Packet specifies length of %d, actual length is %d\n", buf[1], buf_len-2); } qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", buf+2, token_len, "<<< got a token -> [default] decrypt and dump"); - + qd->token = g_new0(guint8, token_len); qd->token_len = token_len; g_memmove(qd->token, buf + 2, qd->token_len); @@ -390,85 +402,48 @@ qd = (qq_data *) gc->proto_data; for (i = 0; i < 4; i++) - qq_send_cmd(gc, QQ_CMD_LOGOUT, qd->password_twice_md5, QQ_KEY_LENGTH); + qq_send_cmd_detail(qd, QQ_CMD_LOGOUT, 0xffff, FALSE, qd->password_twice_md5, QQ_KEY_LENGTH); - qd->is_login = FALSE; /* update login status AFTER sending logout packets */ + qd->logged_in = FALSE; /* update login status AFTER sending logout packets */ } /* process the login reply packet */ -guint8 qq_process_login_reply( PurpleConnection *gc, guint8 *data, gint data_len) +guint8 qq_process_login_reply(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; - guint8 ret = data[0]; - gchar *server_reply, *server_reply_utf8; - gchar *error_msg; + gchar* error_msg; g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR_MISC); qd = (qq_data *) gc->proto_data; - switch (ret) { + switch (data[0]) { case QQ_LOGIN_REPLY_OK: - purple_debug_info("QQ", "Login OK\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is OK\n"); return process_login_ok(gc, data, data_len); case QQ_LOGIN_REPLY_REDIRECT: - purple_debug_info("QQ", "Redirect new server\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is redirect\n"); return process_login_redirect(gc, data, data_len); - - case QQ_LOGIN_REPLY_REDIRECT_EX: - purple_debug_error("QQ", "Extend redirect new server, not supported yet\n"); - error_msg = g_strdup( _("Unable login for not support Redirect_EX now") ); - return QQ_LOGIN_REPLY_REDIRECT_EX; - case QQ_LOGIN_REPLY_ERR_PWD: - server_reply = g_strndup((gchar *)data + 1, data_len - 1); - server_reply_utf8 = qq_to_utf8(server_reply, QQ_CHARSET_DEFAULT); - - purple_debug_error("QQ", "Error password: %s\n", server_reply_utf8); - error_msg = g_strdup_printf( _("Error password: %s"), server_reply_utf8); - - g_free(server_reply); - g_free(server_reply_utf8); - - if (!purple_account_get_remember_password(gc->account)) { - purple_account_set_password(gc->account, NULL); - } - - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, error_msg); - g_free(error_msg); - - return QQ_LOGIN_REPLY_ERR_PWD; - + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is error password\n"); + return process_login_wrong_pwd(gc, data, data_len); case QQ_LOGIN_REPLY_NEED_REACTIVE: - server_reply = g_strndup((gchar *)data + 1, data_len - 1); - server_reply_utf8 = qq_to_utf8(server_reply, QQ_CHARSET_DEFAULT); - - purple_debug_error("QQ", "Need active: %s\n", server_reply_utf8); - error_msg = g_strdup_printf( _("Need active: %s"), server_reply_utf8); - - g_free(server_reply); - g_free(server_reply_utf8); - break; - + case QQ_LOGIN_REPLY_REDIRECT_EX: + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login reply is not actived or redirect extend\n"); default: - purple_debug_error("QQ", - "Unable login for unknow reply code 0x%02X\n", data[0]); - qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", - data, data_len, - ">>> [default] decrypt and dump"); - error_msg = try_dump_as_gbk(data, data_len); - if (error_msg == NULL) { - error_msg = g_strdup_printf( - _("Unable login for unknow reply code 0x%02X"), data[0] ); - } - break; + break; } - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); - g_free(error_msg); - return ret; + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown reply code: 0x%02X\n", data[0]); + qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", + data, data_len, + ">>> [default] decrypt and dump"); + error_msg = try_dump_as_gbk(data, data_len); + if (error_msg) { + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); + g_free(error_msg); + } + return QQ_LOGIN_REPLY_ERR_MISC; } /* send keep-alive packet to QQ server (it is a heart-beat) */ @@ -485,11 +460,11 @@ * the amount of online QQ users, my ip and port */ bytes += qq_put32(raw_data + bytes, qd->uid); - qq_send_cmd(gc, QQ_CMD_KEEP_ALIVE, raw_data, 4); + qq_send_cmd(qd, QQ_CMD_KEEP_ALIVE, raw_data, 4); } /* parse the return of keep-alive packet, it includes some system information */ -gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc) +gboolean qq_process_keep_alive(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; gchar **segments; @@ -503,7 +478,7 @@ /* the last one is 60, don't know what it is */ if (NULL == (segments = split_data(data, data_len, "\x1f", 6))) return TRUE; - + /* segments[0] and segment[1] are all 0x30 ("0") */ qd->total_online = strtol(segments[2], NULL, 10); if(0 == qd->total_online) { @@ -513,9 +488,9 @@ qd->my_ip.s_addr = inet_addr(segments[3]); qd->my_port = strtol(segments[4], NULL, 10); - purple_debug_info("QQ", "keep alive, %s:%d\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "keep alive, %s:%d\n", inet_ntoa(qd->my_ip), qd->my_port); - + g_strfreev(segments); return TRUE; }
--- a/libpurple/protocols/qq/qq_base.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_base.h Mon Sep 15 03:04:07 2008 +0000 @@ -44,10 +44,10 @@ #define QQ_UPDATE_ONLINE_INTERVAL 300 /* in sec */ void qq_send_packet_token(PurpleConnection *gc); -guint8 qq_process_token_reply(PurpleConnection *gc, guint8 *buf, gint buf_len); +guint8 qq_process_token_reply(PurpleConnection *gc, gchar *error_msg, guint8 *buf, gint buf_len); void qq_send_packet_login(PurpleConnection *gc); -guint8 qq_process_login_reply( PurpleConnection *gc, guint8 *data, gint data_len); +guint8 qq_process_login_reply(guint8 *data, gint data_len, PurpleConnection *gc); void qq_send_packet_logout(PurpleConnection *gc);
--- a/libpurple/protocols/qq/qq_network.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_network.c Mon Sep 15 03:04:07 2008 +0000 @@ -26,6 +26,11 @@ #include "debug.h" #include "internal.h" +#ifdef _WIN32 +#define random rand +#define srandom srand +#endif + #include "buddy_info.h" #include "group_info.h" #include "group_free.h" @@ -39,100 +44,63 @@ #include "utils.h" #include "qq_process.h" -#define QQ_DEFAULT_PORT 8000 - -/* set QQ_CONNECT_MAX to 1, when test reconnecting */ -#define QQ_CONNECT_MAX 3 -#define QQ_CONNECT_INTERVAL 2 -#define QQ_CONNECT_CHECK 5 -#define QQ_KEEP_ALIVE_INTERVAL 60 -#define QQ_TRANS_INTERVAL 10 - -gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port); - -static qq_connection *connection_find(qq_data *qd, int fd) { - qq_connection *ret = NULL; - GSList *entry = qd->openconns; - while(entry) { - ret = entry->data; - if(ret->fd == fd) return ret; - entry = entry->next; - } - return NULL; -} +/* set QQ_RECONNECT_MAX to 1, when test reconnecting */ +#define QQ_RECONNECT_MAX 4 +#define QQ_RECONNECT_INTERVAL 5000 +#define QQ_KEEP_ALIVE_INTERVAL 60000 +#define QQ_TRANS_INTERVAL 10000 -static qq_connection *connection_create(qq_data *qd, int fd) { - qq_connection *ret = g_new0(qq_connection, 1); - ret->fd = fd; - qd->openconns = g_slist_append(qd->openconns, ret); - return ret; -} - -static void connection_remove(qq_data *qd, int fd) { - qq_connection *conn = connection_find(qd, fd); - qd->openconns = g_slist_remove(qd->openconns, conn); - - g_return_if_fail( conn != NULL ); - - purple_debug_info("QQ", "Close socket %d\n", conn->fd); - if(conn->input_handler > 0) purple_input_remove(conn->input_handler); - if(conn->can_write_handler > 0) purple_input_remove(conn->can_write_handler); - - if (conn->fd >= 0) close(conn->fd); - if(conn->tcp_txbuf != NULL) purple_circ_buffer_destroy(conn->tcp_txbuf); - if (conn->tcp_rxqueue != NULL) g_free(conn->tcp_rxqueue); - - g_free(conn); -} - -static void connection_free_all(qq_data *qd) { - qq_connection *ret = NULL; - GSList *entry = qd->openconns; - while(entry) { - ret = entry->data; - connection_remove(qd, ret->fd); - entry = qd->openconns; - } -} static gboolean set_new_server(qq_data *qd) { gint count; gint index; GList *it = NULL; - + g_return_val_if_fail(qd != NULL, FALSE); if (qd->servers == NULL) { - purple_debug_info("QQ", "Server list is NULL\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Server list is NULL\n"); return FALSE; } + if (qd->real_hostname) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n"); + g_free(qd->real_hostname); + qd->real_hostname = NULL; + } + /* remove server used before */ - if (qd->curr_server != NULL) { - purple_debug_info("QQ", - "Remove current [%s] from server list\n", qd->curr_server); - qd->servers = g_list_remove(qd->servers, qd->curr_server); - qd->curr_server = NULL; + if (qd->server_name != NULL) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "Remove previous server [%s]\n", qd->server_name); + qd->servers = g_list_remove(qd->servers, qd->server_name); + qd->server_name = NULL; } - + count = g_list_length(qd->servers); - purple_debug_info("QQ", "Server list has %d\n", count); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Server list has %d\n", count); if (count <= 0) { /* no server left, disconnect when result is false */ qd->servers = NULL; return FALSE; } - + /* get new server */ - index = rand() % count; + index = random() % count; it = g_list_nth(qd->servers, index); - qd->curr_server = it->data; /* do not free server_name */ - if (qd->curr_server == NULL || strlen(qd->curr_server) <= 0 ) { - purple_debug_info("QQ", "Server name at %d is empty\n", index); + qd->server_name = it->data; /* do not free server_name */ + if (qd->server_name == NULL || strlen(qd->server_name) <= 0 ) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Server name at %d is empty\n", index); return FALSE; } - purple_debug_info("QQ", "set new server to %s\n", qd->curr_server); + qd->real_hostname = g_strdup(qd->server_name); + qd->real_port = qd->user_port; + + qd->reconnect_times = QQ_RECONNECT_MAX; + + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "set new server to %s:%d\n", qd->real_hostname, qd->real_port); return TRUE; } @@ -147,208 +115,152 @@ return bytes; } -static gboolean connect_check(gpointer data) +static gboolean reconnect_later_cb(gpointer data) { - PurpleConnection *gc = (PurpleConnection *) data; + PurpleConnection *gc; qq_data *qd; - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); - qd = (qq_data *) gc->proto_data; - - if (qd->connect_watcher > 0) { - purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = 0; - } - - if (qd->fd >= 0 && qd->token != NULL && qd->token_len >= 0) { - purple_debug_info("QQ", "Connect ok\n"); - return FALSE; - } - - qd->connect_watcher = purple_timeout_add_seconds(0, qq_connect_later, gc); - return FALSE; -} - -/* Warning: qq_connect_later destory all connection - * Any function should be care of use qq_data after call this function - * Please conside tcp_pending and udp_pending */ -gboolean qq_connect_later(gpointer data) -{ - PurpleConnection *gc = (PurpleConnection *) data; - qq_data *qd; - char *server; - int port; - gchar **segments; - + gc = (PurpleConnection *) data; g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); qd = (qq_data *) gc->proto_data; - if (qd->check_watcher > 0) { - purple_timeout_remove(qd->check_watcher); - qd->check_watcher = 0; - } - qq_disconnect(gc); - - if (qd->redirect_ip.s_addr != 0) { - /* redirect to new server */ - server = g_strdup_printf("%s:%d", inet_ntoa(qd->redirect_ip), qd->redirect_port); - qd->servers = g_list_append(qd->servers, server); - qd->curr_server = server; - - qd->redirect_ip.s_addr = 0; - qd->redirect_port = 0; - qd->connect_retry = QQ_CONNECT_MAX; - } + qd->reconnect_timeout = 0; - if (qd->curr_server == NULL || strlen (qd->curr_server) == 0 || qd->connect_retry <= 0) { - if ( set_new_server(qd) != TRUE) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Failed to connect all servers")); - return FALSE; - } - qd->connect_retry = QQ_CONNECT_MAX; - } - - segments = g_strsplit_set(qd->curr_server, ":", 0); - server = g_strdup(segments[0]); - port = atoi(segments[1]); - if (port <= 0) { - purple_debug_info("QQ", "Port not define in %s\n", qd->curr_server); - port = QQ_DEFAULT_PORT; - } - g_strfreev(segments); - - qd->connect_retry--; - if ( !connect_to_server(gc, server, port) ) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect.")); - } - - qd->check_watcher = purple_timeout_add_seconds(QQ_CONNECT_CHECK, connect_check, gc); + qq_connect(gc->account); return FALSE; /* timeout callback stops */ } +static void reconnect_later(PurpleConnection *gc) +{ + qq_data *qd; + + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + qd = (qq_data *) gc->proto_data; + + qd->reconnect_times--; + if (qd->reconnect_times < 0) { + if ( set_new_server(qd) != TRUE) { + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Failed to connect server")); + return; + } + } + + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "Reconnect to server %s:%d next retries %d in %d ms\n", + qd->real_hostname, qd->real_port, + qd->reconnect_times, QQ_RECONNECT_INTERVAL); + + qd->reconnect_timeout = purple_timeout_add(QQ_RECONNECT_INTERVAL, + reconnect_later_cb, gc); +} + /* process the incoming packet from qq_pending */ -static gboolean packet_process(PurpleConnection *gc, guint8 *buf, gint buf_len) +static void packet_process(PurpleConnection *gc, guint8 *buf, gint buf_len) { qq_data *qd; gint bytes, bytes_not_read; - gboolean prev_update_status; - + gboolean prev_login_status; + guint8 header_tag; guint16 source_tag; guint16 cmd; guint16 seq; /* May be ack_seq or send_seq, depends on cmd */ + guint8 room_cmd; guint32 room_id; - gint update_class; - guint32 ship32; qq_transaction *trans; - g_return_val_if_fail(buf != NULL && buf_len > 0, TRUE); + g_return_if_fail(buf != NULL && buf_len > 0); qd = (qq_data *) gc->proto_data; + prev_login_status = qd->logged_in; + /* Len, header and tail tag have been checked before */ bytes = 0; bytes += packet_get_header(&header_tag, &source_tag, &cmd, &seq, buf + bytes); #if 1 - purple_debug_info("QQ", "==> [%05d] 0x%04X %s, source tag 0x%04X len %d\n", - seq, cmd, qq_get_cmd_desc(cmd), source_tag, buf_len); -#endif - /* this is the length of all the encrypted data (also remove tail tag) */ + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "==> [%05d] 0x%04X %s, from (0x%04X %s) len %d\n", + seq, cmd, qq_get_cmd_desc(cmd), source_tag, qq_get_ver_desc(source_tag), buf_len); +#endif bytes_not_read = buf_len - bytes - 1; /* ack packet, we need to update send tranactions */ /* we do not check duplication for server ack */ - trans = qq_trans_find_rcved(gc, cmd, seq); + trans = qq_trans_find_rcved(qd, cmd, seq); if (trans == NULL) { /* new server command */ - qq_trans_add_server_cmd(gc, cmd, seq, buf + bytes, bytes_not_read); - if ( qd->is_finish_update ) { + qq_trans_add_server_cmd(qd, cmd, seq, buf + bytes, bytes_not_read); + if ( qd->logged_in ) { qq_proc_cmd_server(gc, cmd, seq, buf + bytes, bytes_not_read); } - return TRUE; + return; } if (qq_trans_is_dup(trans)) { - purple_debug_info("QQ", "dup [%05d] %s, discard...\n", seq, qq_get_cmd_desc(cmd)); - return TRUE; + purple_debug(PURPLE_DEBUG_WARNING, + "QQ", "dup [%05d] %s, discard...\n", seq, qq_get_cmd_desc(cmd)); + return; } if (qq_trans_is_server(trans)) { - if ( qd->is_finish_update ) { + if ( qd->logged_in ) { qq_proc_cmd_server(gc, cmd, seq, buf + bytes, bytes_not_read); } - return TRUE; + return; } - update_class = qq_trans_get_class(trans); - ship32 = qq_trans_get_ship(trans); - - prev_update_status = qd->is_finish_update; - switch (cmd) { - case QQ_CMD_TOKEN: - if (qq_process_token_reply(gc, buf + bytes, bytes_not_read) == QQ_TOKEN_REPLY_OK) { - qq_send_packet_login(gc); - } - break; - case QQ_CMD_LOGIN: - qq_proc_cmd_login(gc, buf + bytes, bytes_not_read); - /* check is redirect or not, and do it now */ - if (qd->redirect_ip.s_addr != 0) { - if (qd->check_watcher > 0) { - purple_timeout_remove(qd->check_watcher); - qd->check_watcher = 0; - } - if (qd->connect_watcher > 0) purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = purple_timeout_add_seconds(QQ_CONNECT_INTERVAL, qq_connect_later, gc); - return FALSE; /* do nothing after this function and return now */ - } - break; - case QQ_CMD_ROOM: - room_cmd = qq_trans_get_room_cmd(trans); - room_id = qq_trans_get_room_id(trans); + /* this is the length of all the encrypted data (also remove tail tag */ + if (cmd == QQ_CMD_ROOM) { + room_cmd = qq_trans_get_room_cmd(trans); + room_id = qq_trans_get_room_id(trans); #if 1 - purple_debug_info("QQ", "%s (0x%02X) for room %d, len %d\n", - qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); -#endif - qq_proc_room_cmd_reply(gc, seq, room_cmd, room_id, buf + bytes, bytes_not_read, update_class, ship32); - break; - default: - qq_proc_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read, update_class, ship32); - break; + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "%s (0x%02X ) for room %d, len %d\n", + qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); +#endif + qq_proc_room_cmd_reply(gc, seq, room_cmd, room_id, buf + bytes, bytes_not_read); + } else { + qq_proc_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read); + } + + /* check is redirect or not, and do it now */ + if (qd->is_redirect) { + /* free resource except real_hostname and port */ + qq_disconnect(gc); + qd->reconnect_times = QQ_RECONNECT_MAX; + reconnect_later(gc); + return; } - if (prev_update_status != qd->is_finish_update && qd->is_finish_update == TRUE) { - /* is_login, but we have packets before login */ - qq_trans_process_before_login(gc); - return TRUE; + if (prev_login_status != qd->logged_in && qd->logged_in == TRUE) { + /* logged_in, but we have packets before login */ + qq_trans_process_before_login(qd); } - return TRUE; } static void tcp_pending(gpointer data, gint source, PurpleInputCondition cond) { - PurpleConnection *gc = (PurpleConnection *) data; + PurpleConnection *gc; qq_data *qd; - qq_connection *conn; guint8 buf[1024]; /* set to 16 when test tcp_rxqueue */ gint buf_len; gint bytes; - + guint8 *pkt; guint16 pkt_len; - + gchar *error_msg; guint8 *jump; gint jump_len; + gc = (PurpleConnection *) data; g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; if(cond != PURPLE_INPUT_READ) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, @@ -356,9 +268,8 @@ return; } - conn = connection_find(qd, source); - g_return_if_fail(conn != NULL); - + qd = (qq_data *) gc->proto_data; + /* test code, not using tcp_rxqueue memset(pkt,0, sizeof(pkt)); buf_len = read(qd->fd, pkt, sizeof(pkt)); @@ -367,8 +278,8 @@ } return; */ - - buf_len = read(source, buf, sizeof(buf)); + + buf_len = read(qd->fd, buf, sizeof(buf)); if (buf_len < 0) { if (errno == EAGAIN) /* No worries */ @@ -388,93 +299,93 @@ * QQ need a keep alive packet in every 60 seconds gc->last_received = time(NULL); */ - /* purple_debug_info("TCP_PENDING", "Read %d bytes, rxlen is %d\n", buf_len, conn->tcp_rxlen); */ - conn->tcp_rxqueue = g_realloc(conn->tcp_rxqueue, buf_len + conn->tcp_rxlen); - memcpy(conn->tcp_rxqueue + conn->tcp_rxlen, buf, buf_len); - conn->tcp_rxlen += buf_len; - + /* + purple_debug(PURPLE_DEBUG_INFO, "TCP_PENDING", + "Read %d bytes from socket, rxlen is %d\n", buf_len, qd->tcp_rxlen); + */ + qd->tcp_rxqueue = g_realloc(qd->tcp_rxqueue, buf_len + qd->tcp_rxlen); + memcpy(qd->tcp_rxqueue + qd->tcp_rxlen, buf, buf_len); + qd->tcp_rxlen += buf_len; + pkt = g_newa(guint8, MAX_PACKET_SIZE); - while (PURPLE_CONNECTION_IS_VALID(gc)) { - if (qd->openconns == NULL) { + while (1) { + if (qd->tcp_rxlen < QQ_TCP_HEADER_LENGTH) { break; } - if (conn->tcp_rxqueue == NULL) { - conn->tcp_rxlen = 0; - break; - } - if (conn->tcp_rxlen < QQ_TCP_HEADER_LENGTH) { + + bytes = 0; + bytes += qq_get16(&pkt_len, qd->tcp_rxqueue + bytes); + if (qd->tcp_rxlen < pkt_len) { break; } - bytes = 0; - bytes += qq_get16(&pkt_len, conn->tcp_rxqueue + bytes); - if (conn->tcp_rxlen < pkt_len) { - break; - } - - /* purple_debug_info("TCP_PENDING", "Packet len=%d, rxlen=%d\n", pkt_len, conn->tcp_rxlen); */ + /* + purple_debug(PURPLE_DEBUG_INFO, "TCP_PENDING", + "Packet len is %d bytes, rxlen is %d\n", pkt_len, qd->tcp_rxlen); + */ if ( pkt_len < QQ_TCP_HEADER_LENGTH - || *(conn->tcp_rxqueue + bytes) != QQ_PACKET_TAG - || *(conn->tcp_rxqueue + pkt_len - 1) != QQ_PACKET_TAIL) { + || *(qd->tcp_rxqueue + bytes) != QQ_PACKET_TAG + || *(qd->tcp_rxqueue + pkt_len - 1) != QQ_PACKET_TAIL) { /* HEY! This isn't even a QQ. What are you trying to pull? */ - purple_debug_warning("TCP_PENDING", "Packet error, no header or tail tag\n"); + + purple_debug(PURPLE_DEBUG_ERROR, "TCP_PENDING", + "Packet error, failed to check header and tail tag\n"); - jump = memchr(conn->tcp_rxqueue + 1, QQ_PACKET_TAIL, conn->tcp_rxlen - 1); + jump = memchr(qd->tcp_rxqueue + 1, QQ_PACKET_TAIL, qd->tcp_rxlen - 1); if ( !jump ) { - purple_debug_warning("TCP_PENDING", "Failed to find next tail, clear receive buffer\n"); - g_free(conn->tcp_rxqueue); - conn->tcp_rxqueue = NULL; - conn->tcp_rxlen = 0; + purple_debug(PURPLE_DEBUG_INFO, "TCP_PENDING", + "Failed to find next QQ_PACKET_TAIL, clear receive buffer\n"); + g_free(qd->tcp_rxqueue); + qd->tcp_rxqueue = NULL; + qd->tcp_rxlen = 0; return; } /* jump and over QQ_PACKET_TAIL */ - jump_len = (jump - conn->tcp_rxqueue) + 1; - purple_debug_warning("TCP_PENDING", "Find next tail at %d, jump %d\n", jump_len, jump_len + 1); - g_memmove(conn->tcp_rxqueue, jump, conn->tcp_rxlen - jump_len); - conn->tcp_rxlen -= jump_len; + jump_len = (jump - qd->tcp_rxqueue) + 1; + purple_debug(PURPLE_DEBUG_INFO, "TCP_PENDING", + "Find next QQ_PACKET_TAIL at %d, jump %d bytes\n", jump_len, jump_len + 1); + g_memmove(qd->tcp_rxqueue, jump, qd->tcp_rxlen - jump_len); + qd->tcp_rxlen -= jump_len; continue; } memset(pkt, 0, MAX_PACKET_SIZE); - g_memmove(pkt, conn->tcp_rxqueue + bytes, pkt_len - bytes); - + g_memmove(pkt, qd->tcp_rxqueue + bytes, pkt_len - bytes); + /* jump to next packet */ - conn->tcp_rxlen -= pkt_len; - if (conn->tcp_rxlen) { - /* purple_debug_info("TCP_PENDING", "shrink tcp_rxqueue to %d\n", conn->tcp_rxlen); */ - jump = g_memdup(conn->tcp_rxqueue + pkt_len, conn->tcp_rxlen); - g_free(conn->tcp_rxqueue); - conn->tcp_rxqueue = jump; + qd->tcp_rxlen -= pkt_len; + if (qd->tcp_rxlen) { + /* + purple_debug(PURPLE_DEBUG_ERROR, "TCP_PENDING", "shrink tcp_rxqueue to %d\n", qd->tcp_rxlen); + */ + jump = g_memdup(qd->tcp_rxqueue + pkt_len, qd->tcp_rxlen); + g_free(qd->tcp_rxqueue); + qd->tcp_rxqueue = jump; } else { - /* purple_debug_info("TCP_PENDING", "free tcp_rxqueue\n"); */ - g_free(conn->tcp_rxqueue); - conn->tcp_rxqueue = NULL; + /* purple_debug(PURPLE_DEBUG_ERROR, "TCP_PENDING", "free tcp_rxqueue\n"); */ + g_free(qd->tcp_rxqueue); + qd->tcp_rxqueue = NULL; } if (pkt == NULL) { continue; } - /* packet_process may call disconnect and destory data like conn - * do not call packet_process before jump, - * break if packet_process return FALSE */ - if (packet_process(gc, pkt, pkt_len - bytes) == FALSE) { - purple_debug_info("TCP_PENDING", "Connection has been destory\n"); - break; - } + /* do not call packet_process before jump + * packet_process may call disconnect and destory tcp_rxqueue */ + packet_process(gc, pkt, pkt_len - bytes); } } static void udp_pending(gpointer data, gint source, PurpleInputCondition cond) { - PurpleConnection *gc = (PurpleConnection *) data; + PurpleConnection *gc; qq_data *qd; guint8 *buf; gint buf_len; gc = (PurpleConnection *) data; g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; if(cond != PURPLE_INPUT_READ) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, @@ -482,10 +393,13 @@ return; } + qd = (qq_data *) gc->proto_data; + g_return_if_fail(qd->fd >= 0); + buf = g_newa(guint8, MAX_PACKET_SIZE); /* here we have UDP proxy suppport */ - buf_len = read(source, buf, MAX_PACKET_SIZE); + buf_len = read(qd->fd, buf, MAX_PACKET_SIZE); if (buf_len <= 0) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to read from socket")); @@ -505,95 +419,73 @@ return; } } - - /* packet_process may call disconnect and destory data like conn - * do not call packet_process before jump, - * break if packet_process return FALSE */ + packet_process(gc, buf, buf_len); } -static gint udp_send_out(PurpleConnection *gc, guint8 *data, gint data_len) +static gint udp_send_out(qq_data *qd, guint8 *data, gint data_len) { - qq_data *qd; gint ret; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; + g_return_val_if_fail(qd != NULL && qd->fd >= 0 && data != NULL && data_len > 0, -1); -#if 0 - purple_debug_info("UDP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); -#endif - + /* + purple_debug(PURPLE_DEBUG_INFO, "UDP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); + */ + errno = 0; ret = send(qd->fd, data, data_len, 0); if (ret < 0 && errno == EAGAIN) { return ret; } - + if (ret < 0) { /* TODO: what to do here - do we really have to disconnect? */ - purple_debug_error("UDP_SEND_OUT", "Send failed: %d, %s\n", errno, g_strerror(errno)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno)); + purple_debug(PURPLE_DEBUG_ERROR, "UDP_SEND_OUT", "Send failed: %d, %s\n", errno, g_strerror(errno)); + purple_connection_error_reason(qd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno)); } return ret; } static void tcp_can_write(gpointer data, gint source, PurpleInputCondition cond) { - PurpleConnection *gc = (PurpleConnection *) data; - qq_data *qd; - qq_connection *conn; + qq_data *qd = data; int ret, writelen; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - conn = connection_find(qd, source); - g_return_if_fail(conn != NULL); - - writelen = purple_circ_buffer_get_max_read(conn->tcp_txbuf); + writelen = purple_circ_buffer_get_max_read(qd->tcp_txbuf); if (writelen == 0) { - purple_input_remove(conn->can_write_handler); - conn->can_write_handler = 0; + purple_input_remove(qd->tx_handler); + qd->tx_handler = 0; return; } - ret = write(source, conn->tcp_txbuf->outptr, writelen); - purple_debug_info("TCP_CAN_WRITE", "total %d bytes is sent %d\n", writelen, ret); + ret = write(qd->fd, qd->tcp_txbuf->outptr, writelen); + purple_debug(PURPLE_DEBUG_ERROR, "TCP_CAN_WRITE", + "total %d bytes is sent %d\n", writelen, ret); if (ret < 0 && errno == EAGAIN) return; else if (ret < 0) { /* TODO: what to do here - do we really have to disconnect? */ - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + purple_connection_error_reason(qd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Write Error")); return; } - purple_circ_buffer_mark_read(conn->tcp_txbuf, ret); + purple_circ_buffer_mark_read(qd->tcp_txbuf, ret); } -static gint tcp_send_out(PurpleConnection *gc, guint8 *data, gint data_len) +static gint tcp_send_out(qq_data *qd, guint8 *data, gint data_len) { - qq_data *qd; - qq_connection *conn; gint ret; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; + g_return_val_if_fail(qd != NULL && qd->fd >= 0 && data != NULL && data_len > 0, -1); - conn = connection_find(qd, qd->fd); - g_return_val_if_fail(conn, -1); + /* + purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); + */ -#if 0 - purple_debug_info("TCP_SEND_OUT", "Send %d bytes to socket %d\n", data_len, qd->fd); -#endif - - if (conn->can_write_handler == 0) { + if (qd->tx_handler == 0) { ret = write(qd->fd, data, data_len); } else { ret = -1; @@ -601,28 +493,28 @@ } /* - purple_debug_info("TCP_SEND_OUT", + purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Socket %d, total %d bytes is sent %d\n", qd->fd, data_len, ret); */ if (ret < 0 && errno == EAGAIN) { /* socket is busy, send later */ - purple_debug_info("TCP_SEND_OUT", "Socket is busy and send later\n"); + purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Socket is busy and send later\n"); ret = 0; } else if (ret <= 0) { /* TODO: what to do here - do we really have to disconnect? */ - purple_debug_error("TCP_SEND_OUT", + purple_debug(PURPLE_DEBUG_ERROR, "TCP_SEND_OUT", "Send to socket %d failed: %d, %s\n", qd->fd, errno, g_strerror(errno)); - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno)); + purple_connection_error_reason(qd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, g_strerror(errno)); return ret; } if (ret < data_len) { - purple_debug_info("TCP_SEND_OUT", + purple_debug(PURPLE_DEBUG_INFO, "TCP_SEND_OUT", "Add %d bytes to buffer\n", data_len - ret); - if (conn->can_write_handler == 0) { - conn->can_write_handler = purple_input_add(qd->fd, PURPLE_INPUT_WRITE, tcp_can_write, gc); + if (qd->tx_handler == 0) { + qd->tx_handler = purple_input_add(qd->fd, PURPLE_INPUT_WRITE, tcp_can_write, qd); } - purple_circ_buffer_append(conn->tcp_txbuf, data + ret, data_len - ret); + purple_circ_buffer_append(qd->tcp_txbuf, data + ret, data_len - ret); } return ret; } @@ -636,17 +528,17 @@ g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, TRUE); qd = (qq_data *) gc->proto_data; - is_lost_conn = qq_trans_scan(gc); + is_lost_conn = qq_trans_scan(qd); if (is_lost_conn) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Connection lost")); return TRUE; } - if ( !qd->is_login ) { + if ( !qd->logged_in ) { return TRUE; } - + qd->itv_count.keep_alive--; if (qd->itv_count.keep_alive <= 0) { qd->itv_count.keep_alive = qd->itv_config.keep_alive; @@ -661,30 +553,55 @@ qd->itv_count.update--; if (qd->itv_count.update <= 0) { qd->itv_count.update = qd->itv_config.update; - qq_update_online(gc, 0); + qq_send_packet_get_buddies_online(gc, 0); + + qq_send_cmd_group_all_get_online_members(gc); return TRUE; } return TRUE; /* if return FALSE, timeout callback stops */ } -static void do_request_token(PurpleConnection *gc) +/* the callback function after socket is built + * we setup the qq protocol related configuration here */ +static void qq_connect_cb(gpointer data, gint source, const gchar *error_message) { qq_data *qd; + PurpleConnection *gc; gchar *conn_msg; const gchar *passwd; + PurpleAccount *account ; + + gc = (PurpleConnection *) data; + + if (!PURPLE_CONNECTION_IS_VALID(gc)) { + purple_debug(PURPLE_DEBUG_INFO, "QQ_CONN", "Invalid connection\n"); + close(source); + return; + } + + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + + qd = (qq_data *) gc->proto_data; + account = purple_connection_get_account(gc); + + /* Connect is now complete; clear the PurpleProxyConnectData */ + qd->connect_data = NULL; + + if (source < 0) { /* socket returns -1 */ + purple_debug(PURPLE_DEBUG_INFO, "QQ_CONN", "Invalid connection, source is < 0\n"); + qq_disconnect(gc); + reconnect_later(gc); + return; + } /* _qq_show_socket("Got login socket", source); */ - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - /* QQ use random seq, to minimize duplicated packets */ - srand(time(NULL)); - qd->send_seq = rand() & 0xffff; - - qd->is_login = FALSE; - qd->is_finish_update = FALSE; + srandom(time(NULL)); + qd->send_seq = random() & 0x0000ffff; + qd->fd = source; + qd->logged_in = FALSE; qd->channel = 1; qd->uid = strtol(purple_account_get_username(purple_connection_get_account(gc)), NULL, 10); @@ -697,94 +614,260 @@ qq_get_md5(qd->password_twice_md5, sizeof(qd->password_twice_md5), qd->password_twice_md5, sizeof(qd->password_twice_md5)); - g_return_if_fail(qd->network_watcher == 0); - qd->network_watcher = purple_timeout_add_seconds(qd->itv_config.resend, network_timeout, gc); + g_return_if_fail(qd->network_timeout == 0); + qd->itv_config.resend = purple_account_get_int(account, "resend_interval", 10); + if (qd->itv_config.resend <= 0) qd->itv_config.resend = 10; + + qd->itv_config.keep_alive = purple_account_get_int(account, "keep_alive_interval", 60); + if (qd->itv_config.keep_alive < 30) qd->itv_config.keep_alive = 30; + qd->itv_config.keep_alive /= qd->itv_config.resend; + qd->itv_count.keep_alive = qd->itv_config.keep_alive; + + qd->itv_config.update = purple_account_get_int(account, "update_interval", 300); + if (qd->itv_config.update > 0) { + if (qd->itv_config.update < qd->itv_config.keep_alive) { + qd->itv_config.update = qd->itv_config.keep_alive; + } + qd->itv_config.update /= qd->itv_config.resend; + qd->itv_count.update = qd->itv_config.update; + } else { + qd->itv_config.update = 0; + } + + qd->network_timeout = purple_timeout_add(qd->itv_config.resend *1000, network_timeout, gc); + + if (qd->use_tcp) + gc->inpa = purple_input_add(qd->fd, PURPLE_INPUT_READ, tcp_pending, gc); + else + gc->inpa = purple_input_add(qd->fd, PURPLE_INPUT_READ, udp_pending, gc); /* Update the login progress status display */ - conn_msg = g_strdup_printf(_("Request token")); - purple_connection_update_progress(gc, conn_msg, 2, QQ_CONNECT_STEPS); + conn_msg = g_strdup_printf("Login as %d", qd->uid); + purple_connection_update_progress(gc, conn_msg, QQ_CONNECT_STEPS - 1, QQ_CONNECT_STEPS); g_free(conn_msg); qq_send_packet_token(gc); } -/* the callback function after socket is built - * we setup the qq protocol related configuration here */ -static void connect_cb(gpointer data, gint source, const gchar *error_message) +static void udp_can_write(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc; qq_data *qd; - PurpleAccount *account ; - qq_connection *conn; + socklen_t len; + int error=0, ret; + + gc = (PurpleConnection *) data; + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + + qd = (qq_data *) gc->proto_data; + + + purple_debug_info("proxy", "Connected.\n"); + + /* + * getsockopt after a non-blocking connect returns -1 if something is + * really messed up (bad descriptor, usually). Otherwise, it returns 0 and + * error holds what connect would have returned if it blocked until now. + * Thus, error == 0 is success, error == EINPROGRESS means "try again", + * and anything else is a real error. + * + * (error == EINPROGRESS can happen after a select because the kernel can + * be overly optimistic sometimes. select is just a hint that you might be + * able to do something.) + */ + len = sizeof(error); + ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len); + if (ret == 0 && error == EINPROGRESS) + return; /* we'll be called again later */ + + purple_input_remove(qd->tx_handler); + qd->tx_handler = 0; + if (ret < 0 || error != 0) { + if(ret != 0) + error = errno; + + close(source); + + purple_debug_error("proxy", "getsockopt SO_ERROR check: %s\n", g_strerror(error)); + + qq_connect_cb(gc, -1, _("Unable to connect")); + return; + } + + qq_connect_cb(gc, source, NULL); +} + +static void udp_host_resolved(GSList *hosts, gpointer data, const char *error_message) { + PurpleConnection *gc; + qq_data *qd; + struct sockaddr server_addr; + int addr_size; + gint fd = -1; + int flags; gc = (PurpleConnection *) data; g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; - account = purple_connection_get_account(gc); + + /* udp_query_data must be set as NULL. + * Otherwise purple_dnsquery_destroy in qq_disconnect cause glib double free error */ + qd->udp_query_data = NULL; - /* conn_data will be destoryed */ - qd->conn_data = NULL; - - if (!PURPLE_CONNECTION_IS_VALID(gc)) { - purple_debug_info("QQ_CONN", "Invalid connection\n"); - close(source); + if (!hosts || !hosts->data) { + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Couldn't resolve host")); return; } - if (source < 0) { /* socket returns -1 */ - purple_debug_info("QQ_CONN", - "Could not establish a connection with the server:\n%s\n", - error_message); - if (qd->connect_watcher > 0) purple_timeout_remove(qd->connect_watcher); - qd->connect_watcher = purple_timeout_add_seconds(QQ_CONNECT_INTERVAL, qq_connect_later, gc); + addr_size = GPOINTER_TO_INT(hosts->data); + hosts = g_slist_remove(hosts, hosts->data); + memcpy(&server_addr, hosts->data, addr_size); + g_free(hosts->data); + + hosts = g_slist_remove(hosts, hosts->data); + while(hosts) { + hosts = g_slist_remove(hosts, hosts->data); + g_free(hosts->data); + hosts = g_slist_remove(hosts, hosts->data); + } + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "Unable to create socket: %s\n", g_strerror(errno)); return; } - /* _qq_show_socket("Got login socket", source); */ - qd->fd = source; - conn = connection_create(qd, source); - if (qd->use_tcp) { - conn->input_handler = purple_input_add(source, PURPLE_INPUT_READ, tcp_pending, gc); - } else { - conn->input_handler = purple_input_add(source, PURPLE_INPUT_READ, udp_pending, gc); + /* we use non-blocking mode to speed up connection */ + flags = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, flags | O_NONBLOCK); +#ifndef _WIN32 + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + + /* From Unix-socket-FAQ: http://www.faqs.org/faqs/unix-faq/socket/ + * + * If a UDP socket is unconnected, which is the normal state after a + * bind() call, then send() or write() are not allowed, since no + * destination is available; only sendto() can be used to send data. + * + * Calling connect() on the socket simply records the specified address + * and port number as being the desired communications partner. That + * means that send() or write() are now allowed; they use the destination + * address and port given on the connect call as the destination of packets. + */ + if (connect(fd, &server_addr, addr_size) >= 0) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Connected.\n"); + flags = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + qq_connect_cb(gc, fd, NULL); + return; } + + /* [EINPROGRESS] + * The socket is marked as non-blocking and the connection cannot be + * completed immediately. It is possible to select for completion by + * selecting the socket for writing. + * [EINTR] + * A signal interrupted the call. + * The connection is established asynchronously. + */ + if ((errno == EINPROGRESS) || (errno == EINTR)) { + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Connect in asynchronous mode.\n"); + qd->tx_handler = purple_input_add(fd, PURPLE_INPUT_WRITE, udp_can_write, gc); + return; + } - do_request_token( gc ); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Connection failed: %s\n", g_strerror(errno)); + close(fd); } -gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port) +/* establish a generic QQ connection + * TCP/UDP, and direct/redirected */ +void qq_connect(PurpleAccount *account) { - PurpleAccount *account ; + PurpleConnection *gc; qq_data *qd; gchar *conn_msg; - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); - account = purple_connection_get_account(gc); + gc = purple_account_get_connection(account); + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + qd = (qq_data *) gc->proto_data; - if (server == NULL || strlen(server) == 0 || port == 0) { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Invalid server or port")); - return FALSE; + + /* test set_new_server + while (set_new_server(qd)) { + purple_debug(PURPLE_DEBUG_INFO, "QQ_TEST", + "New server %s:%d Real server %s:%d\n", + qd->server_name, qd->user_port, qd->real_hostname, qd->real_port); + } + purple_debug(PURPLE_DEBUG_INFO, "QQ_TEST", "qd->servers %lu\n", + qd->servers); + exit(1); + */ + if (qd->server_name == NULL) { + /* must be first call this function */ + if ( set_new_server(qd) != TRUE) { + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Failed to connect server")); + return; + } } - conn_msg = g_strdup_printf( _("Connecting server %s, retries %d"), server, port); + if (qd->real_hostname == NULL || qd->real_port == 0) { + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("hostname is NULL or port is 0")); + return; + } + + conn_msg = g_strdup_printf( _("Connecting server %s, retries %d"), + qd->real_hostname, qd->reconnect_times); purple_connection_update_progress(gc, conn_msg, 1, QQ_CONNECT_STEPS); g_free(conn_msg); - purple_debug_info("QQ", "Connect to %s:%d\n", server, port); + if (qd->is_redirect) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Redirect to %s:%d\n", + qd->real_hostname, qd->real_port); + } + qd->is_redirect = FALSE; - if (qd->conn_data != NULL) { - purple_proxy_connect_cancel(qd->conn_data); - qd->conn_data = NULL; + qd->fd = -1; + qd->tx_handler = 0; + + /* QQ connection via UDP/TCP. + * Now use Purple proxy function to provide TCP proxy support, + * and qq_udp_proxy.c to add UDP proxy support (thanks henry) */ + if(qd->use_tcp) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "TCP Connect to %s:%d\n", + qd->real_hostname, qd->real_port); + + /* TODO: is there a good default grow size? */ + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Create tcp_txbuf\n"); + qd->tcp_txbuf = purple_circ_buffer_new(0); + + qd->connect_data = purple_proxy_connect(NULL, account, + qd->real_hostname, qd->real_port, qq_connect_cb, gc); + if (qd->connect_data == NULL) { + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Unable to connect.")); + } + return; } - qd->conn_data = purple_proxy_connect(gc, account, server, port, connect_cb, gc); - if ( qd->conn_data == NULL ) { - purple_debug_error("QQ", _("Couldn't create socket")); - return FALSE; + + purple_debug(PURPLE_DEBUG_INFO, "QQ", "UDP Connect to %s:%d\n", + qd->real_hostname, qd->real_port); + + g_return_if_fail(qd->udp_query_data == NULL); + qd->udp_query_data = purple_dnsquery_a(qd->real_hostname, qd->real_port, + udp_host_resolved, gc); + if (qd->udp_query_data == NULL) { + purple_connection_error_reason(qd->gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Could not resolve hostname")); } - return TRUE; } /* clean up qq_data structure and all its components @@ -796,32 +879,65 @@ g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; - purple_debug_info("QQ", "Disconnecting ...\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Disconnecting ...\n"); - if (qd->network_watcher > 0) { - purple_debug_info("QQ", "Remove network watcher\n"); - purple_timeout_remove(qd->network_watcher); - qd->network_watcher = 0; + if (qd->network_timeout > 0) { + purple_timeout_remove(qd->network_timeout); + qd->network_timeout = 0; } /* finish all I/O */ - if (qd->fd >= 0 && qd->is_login) { + if (qd->fd >= 0 && qd->logged_in) { qq_send_packet_logout(gc); } - /* not connected */ - if (qd->conn_data != NULL) { - purple_debug_info("QQ", "Connect cancel\n"); - purple_proxy_connect_cancel(qd->conn_data); - qd->conn_data = NULL; + if (gc->inpa > 0) { + purple_input_remove(gc->inpa); + gc->inpa = 0; + } + + if (qd->fd >= 0) { + close(qd->fd); + qd->fd = -1; + } + + if (qd->reconnect_timeout > 0) { + purple_timeout_remove(qd->reconnect_timeout); + qd->reconnect_timeout = 0; + } + + if (qd->connect_data != NULL) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Cancel connect_data\n"); + purple_proxy_connect_cancel(qd->connect_data); } - connection_free_all(qd); - qd->fd = -1; + + if(qd->tcp_txbuf != NULL) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "destroy tcp_txbuf\n"); + purple_circ_buffer_destroy(qd->tcp_txbuf); + qd->tcp_txbuf = NULL; + } + + if (qd->tx_handler) { + purple_input_remove(qd->tx_handler); + qd->tx_handler = 0; + } + if (qd->tcp_rxqueue != NULL) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "destroy tcp_rxqueue\n"); + g_free(qd->tcp_rxqueue); + qd->tcp_rxqueue = NULL; + qd->tcp_rxlen = 0; + } + + if (qd->udp_query_data != NULL) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "destroy udp_query_data\n"); + purple_dnsquery_destroy(qd->udp_query_data); + qd->udp_query_data = NULL; + } - qq_trans_remove_all(gc); - + qq_trans_remove_all(qd); + if (qd->token) { - purple_debug_info("QQ", "free token\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "free token\n"); g_free(qd->token); qd->token = NULL; qd->token_len = 0; @@ -839,13 +955,13 @@ qq_buddies_list_free(gc->account, qd); } -static gint packet_encap(qq_data *qd, guint8 *buf, gint maxlen, guint16 cmd, guint16 seq, +static gint encap(qq_data *qd, guint8 *buf, gint maxlen, guint16 cmd, guint16 seq, guint8 *data, gint data_len) { gint bytes = 0; g_return_val_if_fail(qd != NULL && buf != NULL && maxlen > 0, -1); g_return_val_if_fail(data != NULL && data_len > 0, -1); - + /* QQ TCP packet has two bytes in the begining defines packet length * so leave room here to store packet size */ if (qd->use_tcp) { @@ -855,7 +971,7 @@ bytes += qq_put8(buf + bytes, QQ_PACKET_TAG); bytes += qq_put16(buf + bytes, QQ_CLIENT); bytes += qq_put16(buf + bytes, cmd); - + bytes += qq_put16(buf + bytes, seq); bytes += qq_put32(buf + bytes, qd->uid); @@ -871,144 +987,109 @@ } /* data has been encrypted before */ -static gint packet_send_out(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len) +gint qq_send_data(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack, + guint8 *data, gint data_len) { - qq_data *qd; guint8 *buf; gint buf_len; gint bytes_sent; - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *)gc->proto_data; + g_return_val_if_fail(qd != NULL, -1); g_return_val_if_fail(data != NULL && data_len > 0, -1); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); - buf_len = packet_encap(qd, buf, MAX_PACKET_SIZE, cmd, seq, data, data_len); + buf_len = encap(qd, buf, MAX_PACKET_SIZE, cmd, seq, data, data_len); if (buf_len <= 0) { return -1; } if (qd->use_tcp) { - bytes_sent = tcp_send_out(gc, buf, buf_len); + bytes_sent = tcp_send_out(qd, buf, buf_len); } else { - bytes_sent = udp_send_out(gc, buf, buf_len); + bytes_sent = udp_send_out(qd, buf, buf_len); } + if (need_ack) { + qq_trans_add_client_cmd(qd, cmd, seq, data, data_len); + } + +#if 1 + /* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */ + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "<== [%05d], 0x%04X %s, total %d bytes is sent %d\n", + seq, cmd, qq_get_cmd_desc(cmd), buf_len, bytes_sent); +#endif return bytes_sent; } -gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len, gboolean need_ack) +/* Encrypt data with session_key, then call qq_send_data */ +gint qq_send_cmd_detail(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack, + guint8 *data, gint data_len) { - gint send_len; - -#if 1 - purple_debug_info("QQ", "<== [%05d], %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, data_len); -#endif - - send_len = packet_send_out(gc, cmd, seq, data, data_len); - if (need_ack) { - qq_trans_add_client_cmd(gc, cmd, seq, data, data_len, 0, 0); - } - return send_len; -} - -/* Encrypt data with session_key, and send packet out */ -static gint send_cmd_detail(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len, gboolean need_ack, gint update_class, guint32 ship32) -{ - qq_data *qd; guint8 *encrypted_data; gint encrypted_len; - gint bytes_sent; - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *)gc->proto_data; + g_return_val_if_fail(qd != NULL, -1); g_return_val_if_fail(data != NULL && data_len > 0, -1); /* at most 16 bytes more */ encrypted_data = g_newa(guint8, data_len + 16); +#if 0 + purple_debug(PURPLE_DEBUG_INFO, "QQ_ENCRYPT", + "Before %d: [%05d] 0x%04X %s\n", + data_len, seq, cmd, qq_get_cmd_desc(cmd)); +#endif encrypted_len = qq_encrypt(encrypted_data, data, data_len, qd->session_key); if (encrypted_len < 16) { - purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] 0x%04X %s\n", + purple_debug(PURPLE_DEBUG_ERROR, "QQ_ENCRYPT", + "Error len %d: [%05d] 0x%04X %s\n", encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); return -1; } - bytes_sent = packet_send_out(gc, cmd, seq, encrypted_data, encrypted_len); - - if (need_ack) { - qq_trans_add_client_cmd(gc, cmd, seq, encrypted_data, encrypted_len, update_class, ship32); - } - return bytes_sent; +#if 0 + purple_debug(PURPLE_DEBUG_INFO, "QQ_ENCRYPT", + "After %d: [%05d] 0x%04X %s\n", + encrypted_len, seq, cmd, qq_get_cmd_desc(cmd)); +#endif + return qq_send_data(qd, cmd, seq, need_ack, encrypted_data, encrypted_len); } -gint qq_send_cmd_mess(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len, - gint update_class, guint32 ship32) +/* set seq and need_ack, then call qq_send_cmd_detail */ +gint qq_send_cmd(qq_data *qd, guint16 cmd, guint8 *data, gint data_len) { - qq_data *qd; - guint16 seq; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; + g_return_val_if_fail(qd != NULL, -1); g_return_val_if_fail(data != NULL && data_len > 0, -1); - seq = ++qd->send_seq; -#if 1 - purple_debug_info("QQ", "<== [%05d], %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, data_len); -#endif - return send_cmd_detail(gc, cmd, seq, data, data_len, TRUE, update_class, ship32); + qd->send_seq++; + return qq_send_cmd_detail(qd, cmd, qd->send_seq, TRUE, data, data_len); } -/* set seq and need_ack, then call send_cmd_detail */ -gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len) +gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd, + guint8 *data, gint data_len) +{ + return qq_send_room_cmd(gc, room_cmd, 0, data, data_len); +} + +gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) +{ + g_return_val_if_fail(room_cmd > 0 && room_id > 0, -1); + return qq_send_room_cmd(gc, room_cmd, room_id, NULL, 0); +} + +gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, + guint8 *data, gint data_len) { qq_data *qd; - guint16 seq; - gboolean need_ack; - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); - qd = (qq_data *) gc->proto_data; - g_return_val_if_fail(data != NULL && data_len > 0, -1); - - if (cmd != QQ_CMD_LOGOUT) { - seq = ++qd->send_seq; - need_ack = TRUE; - } else { - seq = 0xFFFF; - need_ack = FALSE; - } -#if 1 - purple_debug_info("QQ", "<== [%05d], %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, data_len); -#endif - return send_cmd_detail(gc, cmd, seq, data, data_len, need_ack, 0, 0); -} - -/* set seq and need_ack, then call send_cmd_detail */ -gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len) -{ -#if 1 - purple_debug_info("QQ", "<== [SRV-%05d], %s(0x%04X), datalen %d\n", - seq, qq_get_cmd_desc(cmd), cmd, data_len); -#endif - return send_cmd_detail(gc, cmd, seq, data, data_len, FALSE, 0, 0); -} - -static gint send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, gint update_class, guint32 ship32) -{ - qq_data *qd; guint8 *buf; gint buf_len; guint8 *encrypted_data; gint encrypted_len; gint bytes_sent; guint16 seq; - + g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1); qd = (qq_data *) gc->proto_data; @@ -1025,7 +1106,6 @@ if (data != NULL && data_len > 0) { buf_len += qq_putdata(buf + buf_len, data, data_len); } - qd->send_seq++; seq = qd->send_seq; @@ -1034,43 +1114,32 @@ encrypted_data = g_newa(guint8, buf_len + 16); encrypted_len = qq_encrypt(encrypted_data, buf, buf_len, qd->session_key); if (encrypted_len < 16) { - purple_debug_error("QQ_ENCRYPT", "Error len %d: [%05d] %s (0x%02X)\n", - encrypted_len, seq, qq_get_room_cmd_desc(room_cmd), room_cmd); + purple_debug(PURPLE_DEBUG_ERROR, "QQ_ENCRYPT", + "Error len %d: [%05d] QQ_CMD_ROOM.(0x%02X %s)\n", + encrypted_len, seq, room_cmd, qq_get_room_cmd_desc(room_cmd)); + return -1; + } + + /* Encap header to buf */ + buf_len = encap(qd, buf, MAX_PACKET_SIZE, QQ_CMD_ROOM, seq, encrypted_data, encrypted_len); + if (buf_len <= 0) { return -1; } - bytes_sent = packet_send_out(gc, QQ_CMD_ROOM, seq, encrypted_data, encrypted_len); + if (qd->use_tcp) { + bytes_sent = tcp_send_out(qd, buf, buf_len); + } else { + bytes_sent = udp_send_out(qd, buf, buf_len); + } + + qq_trans_add_room_cmd(qd, seq, room_cmd, room_id, buf, buf_len); + #if 1 /* qq_show_packet("QQ_SEND_DATA", buf, buf_len); */ - purple_debug_info("QQ", - "<== [%05d], %s (0x%02X) to room %d, datalen %d\n", - seq, qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); + purple_debug(PURPLE_DEBUG_INFO, "QQ", + "<== [%05d], QQ_CMD_ROOM.(0x%02X %s) to room %d, total %d bytes is sent %d\n", + seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, + buf_len, bytes_sent); #endif - - qq_trans_add_room_cmd(gc, seq, room_cmd, room_id, buf, buf_len, update_class, ship32); return bytes_sent; } - -gint qq_send_room_cmd_mess(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, gint update_class, guint32 ship32) -{ - return send_room_cmd(gc, room_cmd, room_id, data, data_len, update_class, ship32); -} - -gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len) -{ - return send_room_cmd(gc, room_cmd, room_id, data, data_len, 0, 0); -} - -gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd, - guint8 *data, gint data_len) -{ - return send_room_cmd(gc, room_cmd, 0, data, data_len, 0, 0); -} - -gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - g_return_val_if_fail(room_cmd > 0 && room_id > 0, -1); - return send_room_cmd(gc, room_cmd, room_id, NULL, 0, 0, 0); -}
--- a/libpurple/protocols/qq/qq_network.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_network.h Mon Sep 15 03:04:07 2008 +0000 @@ -32,23 +32,19 @@ #define QQ_CONNECT_STEPS 3 /* steps in connection */ -gboolean qq_connect_later(gpointer data); +void qq_connect(PurpleAccount *account); void qq_disconnect(PurpleConnection *gc); +void qq_connect_later(PurpleConnection *gc); -gint qq_send_cmd_encrypted(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len, gboolean need_ack); -gint qq_send_cmd(PurpleConnection *gc, guint16 cmd, guint8 *data, gint datalen); -gint qq_send_cmd_mess(PurpleConnection *gc, guint16 cmd, guint8 *data, gint data_len, - gint update_class, guint32 ship32); - -gint qq_send_server_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len); +gint qq_send_cmd(qq_data *qd, guint16 cmd, guint8 *data, gint datalen); +gint qq_send_data(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack, + guint8 *data, gint data_len); +gint qq_send_cmd_detail(qq_data *qd, guint16 cmd, guint16 seq, gboolean need_ack, + guint8 *data, gint data_len); gint qq_send_room_cmd(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len); -gint qq_send_room_cmd_mess(PurpleConnection *gc, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, gint update_class, guint32 ship32); gint qq_send_room_cmd_only(PurpleConnection *gc, guint8 room_cmd, guint32 room_id); -gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd, +gint qq_send_room_cmd_noid(PurpleConnection *gc, guint8 room_cmd, guint8 *data, gint data_len); #endif
--- a/libpurple/protocols/qq/qq_process.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_process.c Mon Sep 15 03:04:07 2008 +0000 @@ -26,6 +26,11 @@ #include "debug.h" #include "internal.h" +#ifdef _WIN32 +#define random rand +#define srandom srand +#endif + #include "buddy_info.h" #include "buddy_list.h" #include "buddy_opt.h" @@ -83,7 +88,8 @@ } } -void qq_proc_cmd_server(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len) +void qq_proc_cmd_server(PurpleConnection *gc, + guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len) { qq_data *qd; @@ -96,20 +102,20 @@ data = g_newa(guint8, rcved_len); data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); if (data_len < 0) { - purple_debug_warning("QQ", - "Can not decrypt server cmd by session key, [%05d], 0x%04X %s, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Can not decrypt server cmd by session key, [%05d], 0x%04X %s, len %d\n", seq, cmd, qq_get_cmd_desc(cmd), rcved_len); qq_show_packet("Can not decrypted", rcved, rcved_len); return; } if (data_len <= 0) { - purple_debug_warning("QQ", - "Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Server cmd decrypted is empty, [%05d], 0x%04X %s, len %d\n", seq, cmd, qq_get_cmd_desc(cmd), rcved_len); return; } - + /* now process the packet */ switch (cmd) { case QQ_CMD_RECV_IM: @@ -118,7 +124,7 @@ case QQ_CMD_RECV_MSG_SYS: qq_process_msg_sys(data, data_len, seq, gc); break; - case QQ_CMD_BUDDY_CHANGE_STATUS: + case QQ_CMD_RECV_MSG_BUDDY_CHANGE_STATUS: qq_process_buddy_change_status(data, data_len, gc); break; default: @@ -127,8 +133,74 @@ } } -static void process_room_cmd_notify(PurpleConnection *gc, - guint8 room_cmd, guint8 room_id, guint8 reply, guint8 *data, gint data_len) +static void process_cmd_login(PurpleConnection *gc, guint8 *data, gint data_len) +{ + qq_data *qd; + guint ret_8; + + g_return_if_fail (gc != NULL && gc->proto_data != NULL); + + qd = (qq_data *) gc->proto_data; + + ret_8 = qq_process_login_reply(data, data_len, gc); + if (ret_8 == QQ_LOGIN_REPLY_OK) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login repliess OK; everything is fine\n"); + + purple_connection_set_state(gc, PURPLE_CONNECTED); + qd->logged_in = TRUE; /* must be defined after sev_finish_login */ + + /* now initiate QQ Qun, do it first as it may take longer to finish */ + qq_group_init(gc); + + /* Now goes on updating my icon/nickname, not showing info_window */ + qd->modifying_face = FALSE; + + qq_send_packet_get_info(gc, qd->uid, FALSE); + /* grab my level */ + qq_send_packet_get_level(gc, qd->uid); + + qq_send_packet_change_status(gc); + + /* refresh buddies */ + qq_send_packet_get_buddies_list(gc, 0); + + /* refresh groups */ + qq_send_packet_get_buddies_and_rooms(gc, 0); + + return; + } + + if (ret_8 == QQ_LOGIN_REPLY_REDIRECT) { + qd->is_redirect = TRUE; + /* + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Redirected to new server: %s:%d\n", qd->real_hostname, qd->real_port); + */ + return; + } + + if (ret_8 == QQ_LOGIN_REPLY_ERR_PWD) { + if (!purple_account_get_remember_password(gc->account)) { + purple_account_set_password(gc->account, NULL); + } + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password.")); + return; + } + + if (ret_8 == QQ_LOGIN_REPLY_ERR_MISC) { + if (purple_debug_is_enabled()) + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login. Check debug log.")); + else + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to login")); + return; + } +} + +static void process_room_cmd_notify(PurpleConnection *gc, + guint8 room_cmd, guint8 room_id, guint8 reply_cmd, guint8 reply, guint8 *data, gint data_len) { gchar *msg, *msg_utf8; g_return_if_fail(data != NULL && data_len > 0); @@ -136,189 +208,23 @@ msg = g_strndup((gchar *) data, data_len); /* it will append 0x00 */ msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); g_free(msg); - - msg = g_strdup_printf(_("Command %s(0x%02X) id %d, reply [0x%02X]:\n%s"), - qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, reply, msg_utf8); - - purple_notify_error(gc, NULL, _("Invalid QQ Qun reply"), msg); + + msg = g_strdup_printf(_( + "Reply %s(0x%02X )\n" + "Sent %s(0x%02X )\n" + "Room id %d, reply [0x%02X]: \n" + "%s"), + qq_get_room_cmd_desc(reply_cmd), reply_cmd, + qq_get_room_cmd_desc(room_cmd), room_cmd, + room_id, reply, msg_utf8); + + purple_notify_error(gc, NULL, _("Failed room reply"), msg); g_free(msg); g_free(msg_utf8); } -void qq_room_update(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - qq_data *qd; - qq_group *group; - gint ret; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - group = qq_room_search_id(gc, room_id); - if (group == NULL && room_id <= 0) { - purple_debug_info("QQ", "No room, nothing update\n"); - return; - } - if (group == NULL ) { - purple_debug_warning("QQ", "Failed search room id [%d]\n", room_id); - return; - } - - switch (room_cmd) { - case 0: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, group->id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ROOM, 0); - break; - case QQ_ROOM_CMD_GET_INFO: - ret = qq_request_room_get_buddies(gc, group, QQ_CMD_CLASS_UPDATE_ROOM); - if (ret <= 0) { - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, group->id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ROOM, 0); - } - break; - case QQ_ROOM_CMD_GET_BUDDIES: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, group->id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ROOM, 0); - break; - case QQ_ROOM_CMD_GET_ONLINES: - /* last command */ - default: - break; - } -} - -static void update_all_rooms(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - qq_data *qd; - gboolean is_new_turn = FALSE; - qq_group *next_group; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - next_group = qq_room_get_next(gc, room_id); - if (next_group == NULL && room_id <= 0) { - purple_debug_info("QQ", "No room, nothing update\n"); - qd->is_finish_update = TRUE; - return; - } - if (next_group == NULL ) { - is_new_turn = TRUE; - next_group = qq_room_get_next(gc, 0); - g_return_if_fail(next_group != NULL); - } - - switch (room_cmd) { - case 0: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, next_group->id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - break; - case QQ_ROOM_CMD_GET_INFO: - if (!is_new_turn) { - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_INFO, next_group->id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - } else { - qq_request_room_get_buddies(gc, next_group, QQ_CMD_CLASS_UPDATE_ALL); - } - break; - case QQ_ROOM_CMD_GET_BUDDIES: - /* last command */ - if (!is_new_turn) { - qq_request_room_get_buddies(gc, next_group, QQ_CMD_CLASS_UPDATE_ALL); - } else { - qd->is_finish_update = TRUE; - } - break; - default: - break; - } -} - -void qq_update_all(PurpleConnection *gc, guint16 cmd) -{ - qq_data *qd; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - switch (cmd) { - case 0: - qq_request_buddy_info(gc, qd->uid, QQ_CMD_CLASS_UPDATE_ALL, QQ_BUDDY_INFO_UPDATE_ONLY); - break; - case QQ_CMD_GET_USER_INFO: - qq_request_change_status(gc, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_CHANGE_STATUS: - qq_request_get_buddies_list(gc, 0, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_GET_BUDDIES_LIST: - qq_request_get_buddies_and_rooms(gc, 0, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_GET_BUDDIES_AND_ROOMS: - qq_request_get_buddies_levels(gc, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_GET_LEVEL: - qq_request_get_buddies_online(gc, 0, QQ_CMD_CLASS_UPDATE_ALL); - break; - case QQ_CMD_GET_BUDDIES_ONLINE: - /* last command */ - update_all_rooms(gc, 0, 0); - break; - default: - break; - } -} - -static void update_all_rooms_online(PurpleConnection *gc, guint8 room_cmd, guint32 room_id) -{ - qq_data *qd; - qq_group *next_group; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - next_group = qq_room_get_next_conv(gc, room_id); - if (next_group == NULL && room_id <= 0) { - purple_debug_info("QQ", "No room, no update online buddies\n"); - return; - } - if (next_group == NULL ) { - purple_debug_info("QQ", "finished update online buddies\n"); - return; - } - - switch (room_cmd) { - case 0: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, next_group->id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - break; - case QQ_ROOM_CMD_GET_ONLINES: - qq_send_room_cmd_mess(gc, QQ_ROOM_CMD_GET_ONLINES, next_group->id, NULL, 0, - QQ_CMD_CLASS_UPDATE_ALL, 0); - break; - default: - break; - } -} - -void qq_update_online(PurpleConnection *gc, guint16 cmd) -{ - switch (cmd) { - case 0: - qq_request_get_buddies_online(gc, 0, QQ_CMD_CLASS_UPDATE_ONLINE); - break; - case QQ_CMD_GET_BUDDIES_ONLINE: - /* last command */ - update_all_rooms_online(gc, 0, 0); - break; - default: - break; - } -} - -void qq_proc_room_cmd_reply(PurpleConnection *gc, guint16 seq, - guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len, - gint update_class, guint32 ship32) +void qq_proc_room_cmd_reply(PurpleConnection *gc, + guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len) { qq_data *qd; guint8 *data; @@ -333,57 +239,58 @@ data = g_newa(guint8, rcved_len); data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); if (data_len < 0) { - purple_debug_warning("QQ", - "Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Can not decrypt room cmd by session key, [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); qq_show_packet("Can not decrypted", rcved, rcved_len); return; } if (room_id <= 0) { - purple_debug_warning("QQ", - "Invaild room id, [%05d], 0x%02X %s for %d, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Invaild room id, [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); return; } if (data_len <= 2) { - purple_debug_warning("QQ", - "Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Invaild len of room cmd decrypted, [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); return; } - + group = qq_room_search_id(gc, room_id); if (group == NULL) { - purple_debug_warning("QQ", - "Missing room id in [%05d], 0x%02X %s for %d, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Missing room id in [%05d], 0x%02X %s for %d, len %d\n", seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); } - + bytes = 0; bytes += qq_get8(&reply_cmd, data + bytes); bytes += qq_get8(&reply, data + bytes); if (reply_cmd != room_cmd) { - purple_debug_warning("QQ", - "Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Missing room cmd in reply 0x%02X %s, [%05d], 0x%02X %s for %d, len %d\n", reply_cmd, qq_get_room_cmd_desc(reply_cmd), seq, room_cmd, qq_get_room_cmd_desc(room_cmd), room_id, rcved_len); } - + /* now process the packet */ if (reply != QQ_ROOM_CMD_REPLY_OK) { if (group != NULL) { qq_set_pending_id(&qd->joining_groups, group->ext_id, FALSE); } - + switch (reply) { /* this should be all errors */ case QQ_ROOM_CMD_REPLY_NOT_MEMBER: if (group != NULL) { - purple_debug_warning("QQ", - _("You are not a member of QQ Qun \"%s\"\n"), group->title_utf8); - group->my_role = QQ_ROOM_ROLE_NO; + purple_debug(PURPLE_DEBUG_WARNING, + "QQ", + _("You are not a member of group \"%s\"\n"), group->group_name_utf8); + group->my_status = QQ_GROUP_MEMBER_STATUS_NOT_MEMBER; qq_group_refresh(gc, group); } break; @@ -393,7 +300,7 @@ purple_roomlist_set_in_progress(qd->roomlist, FALSE); } default: - process_room_cmd_notify(gc, reply_cmd, room_id, reply, data + bytes, data_len - bytes); + process_room_cmd_notify(gc, room_cmd, room_id, reply_cmd, reply, data + bytes, data_len - bytes); } return; } @@ -402,6 +309,10 @@ switch (reply_cmd) { case QQ_ROOM_CMD_GET_INFO: qq_process_room_cmd_get_info(data + bytes, data_len - bytes, gc); + if (group != NULL) { + qq_send_cmd_group_get_members_info(gc, group); + qq_send_cmd_group_get_online_members(gc, group); + } break; case QQ_ROOM_CMD_CREATE: qq_group_process_create_group_reply(data + bytes, data_len - bytes, gc); @@ -435,80 +346,20 @@ if (group != NULL) qq_group_conv_refresh_online_member(gc, group); break; - case QQ_ROOM_CMD_GET_BUDDIES: - qq_process_room_cmd_get_buddies(data + bytes, data_len - bytes, gc); + case QQ_ROOM_CMD_GET_MEMBER_INFO: + qq_process_room_cmd_get_members(data + bytes, data_len - bytes, gc); if (group != NULL) qq_group_conv_refresh_online_member(gc, group); break; default: - purple_debug_warning("QQ", "Unknow room cmd 0x%02X %s\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Unknow room cmd 0x%02X %s\n", reply_cmd, qq_get_room_cmd_desc(reply_cmd)); } - - purple_debug_info("QQ", "Update class %d\n", update_class); - if (update_class == QQ_CMD_CLASS_UPDATE_ALL) { - update_all_rooms(gc, room_cmd, room_id); - return; - } - if (update_class == QQ_CMD_CLASS_UPDATE_ONLINE) { - update_all_rooms_online(gc, room_cmd, room_id); - return; - } - if (update_class == QQ_CMD_CLASS_UPDATE_ROOM) { - qq_room_update(gc, room_cmd, room_id); - } } -void qq_proc_cmd_login(PurpleConnection *gc, guint8 *rcved, gint rcved_len) -{ - qq_data *qd; - guint8 *data; - gint data_len; - guint ret_8; - - g_return_if_fail (gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - data = g_newa(guint8, rcved_len); - /* May use password_twice_md5 in the past version like QQ2005*/ - data_len = qq_decrypt(data, rcved, rcved_len, qd->inikey); - if (data_len >= 0) { - purple_debug_warning("QQ", - "Decrypt login reply packet with inikey, %d bytes\n", data_len); - } else { - data_len = qq_decrypt(data, rcved, rcved_len, qd->password_twice_md5); - if (data_len >= 0) { - purple_debug_warning("QQ", - "Decrypt login reply packet with password_twice_md5, %d bytes\n", data_len); - } else { - purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Can not decrypt login reply")); - return; - } - } - - ret_8 = qq_process_login_reply(gc, data, data_len); - if (ret_8 != QQ_LOGIN_REPLY_OK) { - return; - } - - 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 */ - - /* now initiate QQ Qun, do it first as it may take longer to finish */ - qq_group_init(gc); - - /* Now goes on updating my icon/nickname, not showing info_window */ - qd->modifying_face = FALSE; - - qq_update_all(gc, 0); - return; -} - -void qq_proc_cmd_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len, gint update_class, guint32 ship32) +void qq_proc_cmd_reply(PurpleConnection *gc, + guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len) { qq_data *qd; @@ -518,7 +369,7 @@ guint8 ret_8 = 0; guint16 ret_16 = 0; guint32 ret_32 = 0; - gboolean is_unknow = FALSE; + gchar *error_msg = NULL; g_return_if_fail(rcved_len > 0); @@ -526,23 +377,61 @@ qd = (qq_data *) gc->proto_data; data = g_newa(guint8, rcved_len); - data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); - if (data_len < 0) { - purple_debug_warning("QQ", - "Reply can not be decrypted by session key, [%05d], 0x%04X %s, len %d\n", - seq, cmd, qq_get_cmd_desc(cmd), rcved_len); - qq_show_packet("Can not decrypted", rcved, rcved_len); - return; + if (cmd == QQ_CMD_TOKEN) { + g_memmove(data, rcved, rcved_len); + data_len = rcved_len; + } else if (cmd == QQ_CMD_LOGIN) { + /* May use password_twice_md5 in the past version like QQ2005*/ + data_len = qq_decrypt(data, rcved, rcved_len, qd->inikey); + if (data_len >= 0) { + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Decrypt login reply packet with inikey, %d bytes\n", data_len); + } else { + data_len = qq_decrypt(data, rcved, rcved_len, qd->password_twice_md5); + if (data_len >= 0) { + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Decrypt login reply packet with password_twice_md5, %d bytes\n", data_len); + } else { + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, + _("Can not decrypt login reply")); + return; + } + } + } else { + data_len = qq_decrypt(data, rcved, rcved_len, qd->session_key); + if (data_len < 0) { + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Can not reply by session key, [%05d], 0x%04X %s, len %d\n", + seq, cmd, qq_get_cmd_desc(cmd), rcved_len); + qq_show_packet("Can not decrypted", rcved, rcved_len); + return; + } } - + if (data_len <= 0) { - purple_debug_warning("QQ", - "Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Reply decrypted is empty, [%05d], 0x%04X %s, len %d\n", seq, cmd, qq_get_cmd_desc(cmd), rcved_len); return; } switch (cmd) { + case QQ_CMD_TOKEN: + ret_8 = qq_process_token_reply(gc, error_msg, data, data_len); + if (ret_8 != QQ_TOKEN_REPLY_OK) { + if (error_msg == NULL) { + error_msg = g_strdup_printf( _("Invalid token reply code, 0x%02X"), ret_8); + } + purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); + g_free(error_msg); + return; + } + + qq_send_packet_login(gc); + break; + case QQ_CMD_LOGIN: + process_cmd_login(gc, data, data_len); + break; case QQ_CMD_UPDATE_INFO: qq_process_modify_info_reply(data, data_len, gc); break; @@ -561,7 +450,7 @@ case QQ_CMD_GET_USER_INFO: qq_process_get_info_reply(data, data_len, gc); break; - case QQ_CMD_CHANGE_STATUS: + case QQ_CMD_CHANGE_ONLINE_STATUS: qq_process_change_status_reply(data, data_len, gc); break; case QQ_CMD_SEND_IM: @@ -573,53 +462,41 @@ case QQ_CMD_GET_BUDDIES_ONLINE: ret_8 = qq_process_get_buddies_online_reply(data, data_len, gc); if (ret_8 > 0 && ret_8 < 0xff) { - purple_debug_info("QQ", "Requesting for more online buddies\n"); - qq_request_get_buddies_online(gc, ret_8, update_class); - return; + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more online buddies\n"); + qq_send_packet_get_buddies_online(gc, ret_8); + } else { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "All online buddies received\n"); + /* Fixme: this should not be called once*/ + qq_send_packet_get_buddies_levels(gc); + + qq_refresh_all_buddy_status(gc); } - purple_debug_info("QQ", "All online buddies received\n"); - qq_refresh_all_buddy_status(gc); break; case QQ_CMD_GET_LEVEL: qq_process_get_level_reply(data, data_len, gc); break; case QQ_CMD_GET_BUDDIES_LIST: ret_16 = qq_process_get_buddies_list_reply(data, data_len, gc); - if (ret_16 > 0 && ret_16 < 0xffff) { - purple_debug_info("QQ", "Requesting for more buddies\n"); - qq_request_get_buddies_list(gc, ret_16, update_class); - return; + if (ret_16 > 0 && ret_16 < 0xffff) { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies\n"); + qq_send_packet_get_buddies_list(gc, ret_16); + } else { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies received. Requesting buddies' levels\n"); + qq_send_packet_get_buddies_online(gc, 0); } - purple_debug_info("QQ", "All buddies received. Requesting buddies' levels\n"); break; case QQ_CMD_GET_BUDDIES_AND_ROOMS: ret_32 = qq_process_get_buddies_and_rooms(data, data_len, gc); if (ret_32 > 0 && ret_32 < 0xffffffff) { - purple_debug_info("QQ", "Requesting for more buddies and groups\n"); - qq_request_get_buddies_and_rooms(gc, ret_32, update_class); - return; + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Requesting for more buddies and groups\n"); + qq_send_packet_get_buddies_and_rooms(gc, ret_32); + } else { + purple_debug(PURPLE_DEBUG_INFO, "QQ", "All buddies and groups received\n"); } - purple_debug_info("QQ", "All buddies and groups received\n"); break; default: process_cmd_unknow(gc, "Unknow reply CMD", data, data_len, cmd, seq); - is_unknow = TRUE; break; } - if (is_unknow) - return; - - if (update_class == QQ_CMD_CLASS_NONE) - return; - - purple_debug_info("QQ", "Update class %d\n", update_class); - if (update_class == QQ_CMD_CLASS_UPDATE_ALL) { - qq_update_all(gc, cmd); - return; - } - if (update_class == QQ_CMD_CLASS_UPDATE_ONLINE) { - qq_update_online(gc, cmd); - return; - } }
--- a/libpurple/protocols/qq/qq_process.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_process.h Mon Sep 15 03:04:07 2008 +0000 @@ -30,24 +30,12 @@ #include "qq.h" -enum { - QQ_CMD_CLASS_NONE = 0, - QQ_CMD_CLASS_UPDATE_ALL, - QQ_CMD_CLASS_UPDATE_ONLINE, - QQ_CMD_CLASS_UPDATE_ROOM, -}; - -void qq_proc_cmd_login(PurpleConnection *gc, guint8 *rcved, gint rcved_len); -void qq_proc_cmd_reply(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *rcved, gint rcved_len, gint update_class, guint32 ship32); -void qq_proc_room_cmd_reply(PurpleConnection *gc, guint16 seq, - guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len, - gint update_class, guint32 ship32); - -void qq_proc_cmd_server(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len); - -void qq_update_all(PurpleConnection *gc, guint16 cmd); -void qq_update_online(PurpleConnection *gc, guint16 cmd); -void qq_room_update(PurpleConnection *gc, guint8 room_cmd, guint32 room_id); +void qq_proc_cmd_reply(PurpleConnection *gc, + guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len); +void qq_proc_room_cmd_reply(PurpleConnection *gc, + guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *rcved, gint rcved_len); + +void qq_proc_cmd_server(PurpleConnection *gc, + guint16 cmd, guint16 seq, guint8 *rcved, gint rcved_len); #endif
--- a/libpurple/protocols/qq/qq_trans.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_trans.c Mon Sep 15 03:04:07 2008 +0000 @@ -37,35 +37,8 @@ #define QQ_RESEND_MAX 3 /* max resend per packet */ -enum { - QQ_TRANS_IS_SERVER = 0x01, /* Is server command or client command */ - QQ_TRANS_IS_IMPORT = 0x02, /* Only notice if not get reply; or resend, disconn if reties get 0*/ - QQ_TRANS_BEFORE_LOGIN = 0x04, /* server command before login*/ -}; - -struct _qq_transaction { - guint8 flag; - guint16 seq; - guint16 cmd; - - guint8 room_cmd; - guint32 room_id; - - guint8 *data; - gint data_len; - - gint fd; - gint send_retries; - gint rcved_times; - gint scan_times; - - gint update_class; - guint32 ship32; -}; - -qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq) +qq_transaction *qq_trans_find_rcved(qq_data *qd, guint16 cmd, guint16 seq) { - qq_data *qd = (qq_data *)gc->proto_data; GList *curr; GList *next; qq_transaction *trans; @@ -77,21 +50,19 @@ next = qd->transactions; while( (curr = next) ) { next = curr->next; - + trans = (qq_transaction *) (curr->data); if(trans->cmd == cmd && trans->seq == seq) { if (trans->rcved_times == 0) { trans->scan_times = 0; } trans->rcved_times++; - /* server may not get our confirm reply before, send reply again*/ - /* only rcved buffer stored in transaction if (qq_trans_is_server(trans) && qq_trans_is_dup(trans)) { + /* server may not get our confirm reply before, send reply again*/ if (trans->data != NULL && trans->data_len > 0) { - qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); + qq_send_data(qd, trans->cmd, trans->seq, FALSE, trans->data, trans->data_len); } } - */ return trans; } } @@ -99,20 +70,20 @@ return NULL; } -gboolean qq_trans_is_server(qq_transaction *trans) +gboolean qq_trans_is_server(qq_transaction *trans) { g_return_val_if_fail(trans != NULL, FALSE); - + if (trans->flag & QQ_TRANS_IS_SERVER) return TRUE; else return FALSE; } -gboolean qq_trans_is_dup(qq_transaction *trans) +gboolean qq_trans_is_dup(qq_transaction *trans) { g_return_val_if_fail(trans != NULL, TRUE); - + if (trans->rcved_times > 1) return TRUE; else @@ -131,122 +102,115 @@ return trans->room_id; } -gint qq_trans_get_class(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, QQ_CMD_CLASS_NONE); - return trans->update_class; -} - -gint qq_trans_get_ship(qq_transaction *trans) -{ - g_return_val_if_fail(trans != NULL, 0); - return trans->ship32; -} - -static qq_transaction *trans_create(PurpleConnection *gc, gint fd, - guint16 cmd, guint16 seq, guint8 *data, gint data_len, gint update_class, guint32 ship32) +/* Remove a packet with seq from send trans */ +static void trans_remove(qq_data *qd, qq_transaction *trans) { - qq_data *qd; - qq_transaction *trans; - - g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL); - qd = (qq_data *) gc->proto_data; - - trans = g_new0(qq_transaction, 1); - - memset(trans, 0, sizeof(qq_transaction)); - trans->fd = fd; - trans->cmd = cmd; - trans->seq = seq; - - trans->data = NULL; - trans->data_len = 0; - if (data != NULL && data_len > 0) { - /* don't use g_strdup, may have 0x00 */ - trans->data = g_memdup(data, data_len); - trans->data_len = data_len; - } - - trans->update_class = update_class; - return trans; -} - -/* Remove a packet with seq from send trans */ -static void trans_remove(PurpleConnection *gc, qq_transaction *trans) -{ - qq_data *qd = (qq_data *)gc->proto_data; g_return_if_fail(qd != NULL && trans != NULL); - -#if 0 - purple_debug_info("QQ_TRANS", + + purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Remove [%s%05d] retry %d rcved %d scan %d %s\n", (trans->flag & QQ_TRANS_IS_SERVER) ? "SRV-" : "", trans->seq, trans->send_retries, trans->rcved_times, trans->scan_times, qq_get_cmd_desc(trans->cmd)); -#endif + if (trans->data) g_free(trans->data); qd->transactions = g_list_remove(qd->transactions, trans); g_free(trans); } -void qq_trans_add_client_cmd(PurpleConnection *gc, - guint16 cmd, guint16 seq, guint8 *data, gint data_len, gint update_class, guint32 ship32) +void qq_trans_add_client_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len) { - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, update_class, ship32); + qq_transaction *trans = g_new0(qq_transaction, 1); + g_return_if_fail(trans != NULL); + + trans->flag = 0; if (cmd == QQ_CMD_TOKEN || cmd == QQ_CMD_LOGIN || cmd == QQ_CMD_KEEP_ALIVE) { - trans->flag |= QQ_TRANS_IS_IMPORT; + trans->flag |= QQ_TRANS_CLI_IMPORT; } + trans->fd = qd->fd; + trans->cmd = cmd; + trans->seq = seq; + trans->room_cmd = 0; + trans->room_id = 0; trans->send_retries = QQ_RESEND_MAX; -#if 0 - purple_debug_info("QQ_TRANS", "Add client cmd, seq %d, data %p, len %d\n", + trans->rcved_times = 0; + trans->scan_times = 0; + + trans->data = NULL; + trans->data_len = 0; + if (data != NULL && data_len > 0) { + trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */ + trans->data_len = data_len; + } + purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", + "Add client cmd, seq = %d, data = %p, len = %d\n", trans->seq, trans->data, trans->data_len); -#endif qd->transactions = g_list_append(qd->transactions, trans); } -void qq_trans_add_room_cmd(PurpleConnection *gc, - guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len, - gint update_class, guint32 ship32) +void qq_trans_add_room_cmd(qq_data *qd, guint16 seq, guint8 room_cmd, guint32 room_id, + guint8 *data, gint data_len) { - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, QQ_CMD_ROOM, seq, data, data_len, - update_class, ship32); + qq_transaction *trans = g_new0(qq_transaction, 1); + + g_return_if_fail(trans != NULL); + trans->flag = 0; + trans->fd = qd->fd; + trans->seq = seq; + trans->cmd = QQ_CMD_ROOM; trans->room_cmd = room_cmd; trans->room_id = room_id; trans->send_retries = QQ_RESEND_MAX; -#if 0 - purple_debug_info("QQ_TRANS", "Add room cmd, seq %d, data %p, len %d\n", + trans->rcved_times = 0; + trans->scan_times = 0; + + trans->data = NULL; + trans->data_len = 0; + if (data != NULL && data_len > 0) { + trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */ + trans->data_len = data_len; + } + purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", + "Add room cmd, seq = %d, data = %p, len = %d\n", trans->seq, trans->data, trans->data_len); -#endif qd->transactions = g_list_append(qd->transactions, trans); } -void qq_trans_add_server_cmd(PurpleConnection *gc, - guint16 cmd, guint16 seq, guint8 *data, gint data_len) +void qq_trans_add_server_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len) { - qq_data *qd = (qq_data *)gc->proto_data; - qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, QQ_CMD_CLASS_NONE, 0); + qq_transaction *trans = g_new0(qq_transaction, 1); + + g_return_if_fail(trans != NULL); trans->flag = QQ_TRANS_IS_SERVER; - if ( !qd->is_login ) { + if ( !qd->logged_in ) { trans->flag |= QQ_TRANS_BEFORE_LOGIN; } + trans->fd = qd->fd; + trans->cmd = cmd; + trans->seq = seq; + trans->room_cmd = 0; + trans->room_id = 0; trans->send_retries = 0; trans->rcved_times = 1; -#if 0 - purple_debug_info("QQ_TRANS", "Add server cmd, seq %d, data %p, len %d\n", + trans->scan_times = 0; + trans->data = NULL; + trans->data_len = 0; + if (data != NULL && data_len > 0) { + trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */ + trans->data_len = data_len; + } + purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", + "Add server cmd, seq = %d, data = %p, len = %d\n", trans->seq, trans->data, trans->data_len); -#endif qd->transactions = g_list_append(qd->transactions, trans); } -void qq_trans_process_before_login(PurpleConnection *gc) +void qq_trans_process_before_login(qq_data *qd) { - qq_data *qd = (qq_data *)gc->proto_data; GList *curr; GList *next; qq_transaction *trans; @@ -257,44 +221,42 @@ while( (curr = next) ) { next = curr->next; trans = (qq_transaction *) (curr->data); -#if 0 - purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); -#endif + /* purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS", "Scan [%d]\n", trans->seq); */ + if ( !(trans->flag & QQ_TRANS_IS_SERVER) ) { continue; } if ( !(trans->flag & QQ_TRANS_BEFORE_LOGIN) ) { continue; } - /* set QQ_TRANS_BEFORE_LOGIN off */ + // set QQ_TRANS_BEFORE_LOGIN off trans->flag &= ~QQ_TRANS_BEFORE_LOGIN; - purple_debug_info("QQ_TRANS", + purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS", "Process server cmd before login, seq %d, data %p, len %d, send_retries %d\n", trans->seq, trans->data, trans->data_len, trans->send_retries); - qq_proc_cmd_reply(gc, trans->seq, trans->cmd, trans->data, trans->data_len, trans->update_class, trans->ship32); + qq_proc_cmd_reply(qd->gc, trans->seq, trans->cmd, trans->data, trans->data_len); } - /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ + /* purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Scan finished\n"); */ return; } -gboolean qq_trans_scan(PurpleConnection *gc) +gboolean qq_trans_scan(qq_data *qd) { - qq_data *qd = (qq_data *)gc->proto_data; GList *curr; GList *next; qq_transaction *trans; g_return_val_if_fail(qd != NULL, FALSE); - + next = qd->transactions; while( (curr = next) ) { next = curr->next; trans = (qq_transaction *) (curr->data); - /* purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); */ - + /* purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Scan [%d]\n", trans->seq); */ + if (trans->flag & QQ_TRANS_BEFORE_LOGIN) { /* keep server cmd before login*/ continue; @@ -308,60 +270,67 @@ if (trans->rcved_times > 0) { /* Has been received */ - trans_remove(gc, trans); + trans_remove(qd, trans); continue; } if (trans->flag & QQ_TRANS_IS_SERVER) { continue; } - + /* Never get reply */ trans->send_retries--; if (trans->send_retries <= 0) { - purple_debug_warning("QQ_TRANS", + purple_debug(PURPLE_DEBUG_WARNING, "QQ_TRANS", "[%d] %s is lost.\n", trans->seq, qq_get_cmd_desc(trans->cmd)); - if (trans->flag & QQ_TRANS_IS_IMPORT) { + if (trans->flag & QQ_TRANS_CLI_IMPORT) { return TRUE; } - purple_debug_error("QQ_TRANS", + purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS", "Lost [%d] %s, data %p, len %d, retries %d\n", trans->seq, qq_get_cmd_desc(trans->cmd), trans->data, trans->data_len, trans->send_retries); - trans_remove(gc, trans); + trans_remove(qd, trans); continue; } - purple_debug_error("QQ_TRANS", + purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS", "Resend [%d] %s data %p, len %d, send_retries %d\n", trans->seq, qq_get_cmd_desc(trans->cmd), trans->data, trans->data_len, trans->send_retries); - qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); + qq_send_data(qd, trans->cmd, trans->seq, FALSE, trans->data, trans->data_len); } - /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ + /* purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Scan finished\n"); */ return FALSE; } /* clean up send trans and free all contents */ -void qq_trans_remove_all(PurpleConnection *gc) +void qq_trans_remove_all(qq_data *qd) { - qq_data *qd = (qq_data *)gc->proto_data; + GList *curr; + GList *next; qq_transaction *trans; gint count = 0; - while(qd->transactions != NULL) { - trans = (qq_transaction *) (qd->transactions->data); - qd->transactions = g_list_remove(qd->transactions, trans); - - if (trans->data) g_free(trans->data); - g_free(trans); + curr = qd->transactions; + while(curr) { + next = curr->next; + + trans = (qq_transaction *) (curr->data); + /* + purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS", + "Remove to transaction, seq = %d, buf = %p, len = %d\n", + trans->seq, trans->buf, trans->len); + */ + trans_remove(qd, trans); count++; + curr = next; } - if (count > 0) { - purple_debug_info("QQ_TRANS", "Free all %d packets\n", count); - } + g_list_free(qd->transactions); + + purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Free all %d packets\n", count); }
--- a/libpurple/protocols/qq/qq_trans.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/qq_trans.h Mon Sep 15 03:04:07 2008 +0000 @@ -28,27 +28,44 @@ #include <glib.h> #include "qq.h" -typedef struct _qq_transaction qq_transaction; +enum { + QQ_TRANS_IS_SERVER = 0x01, /* Is server command or client command */ + /* prefix QQ_TRANS_CLI is for client command*/ + QQ_TRANS_CLI_EMERGE = 0x02, /* send at once; or may wait for next reply*/ + QQ_TRANS_CLI_IMPORT = 0x04, /* Only notice if not get reply; or resend, disconn if reties get 0*/ + QQ_TRANS_BEFORE_LOGIN = 0x08, /* server command before login*/ +}; + +typedef struct _qq_transaction { + guint8 flag; + guint16 seq; + guint16 cmd; -qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq); + guint8 room_cmd; + guint32 room_id; + + guint8 *data; + gint data_len; + + gint fd; + gint send_retries; + gint rcved_times; + gint scan_times; +} qq_transaction; + +qq_transaction *qq_trans_find_rcved(qq_data *qd, guint16 cmd, guint16 seq); gboolean qq_trans_is_server(qq_transaction *trans) ; gboolean qq_trans_is_dup(qq_transaction *trans); guint8 qq_trans_get_room_cmd(qq_transaction *trans); guint32 qq_trans_get_room_id(qq_transaction *trans); -gint qq_trans_get_class(qq_transaction *trans); -gint qq_trans_get_ship(qq_transaction *trans); -void qq_trans_add_client_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, - guint8 *data, gint data_len, gint update_class, guint32 ship32); -void qq_trans_add_room_cmd(PurpleConnection *gc, - guint16 seq, guint8 room_cmd, guint32 room_id, - guint8 *data, gint data_len, gint update_class, guint32 ship32); - -void qq_trans_add_server_cmd(PurpleConnection *gc, guint16 cmd, guint16 seq, +void qq_trans_add_client_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len); +void qq_trans_add_server_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len); +void qq_trans_add_room_cmd(qq_data *qd, guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len); -void qq_trans_process_before_login(PurpleConnection *gc); -gboolean qq_trans_scan(PurpleConnection *gc); -void qq_trans_remove_all(PurpleConnection *gc); +void qq_trans_process_before_login(qq_data *qd); +gboolean qq_trans_scan(qq_data *qd); +void qq_trans_remove_all(qq_data *qd); #endif
--- a/libpurple/protocols/qq/send_file.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/send_file.c Mon Sep 15 03:04:07 2008 +0000 @@ -54,7 +54,7 @@ static int _qq_in_same_lan(ft_info *info) { if (info->remote_internet_ip == info->local_internet_ip) return 1; - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "Not in the same LAN, remote internet ip[%x], local internet ip[%x]\n", info->remote_internet_ip , info->local_internet_ip); @@ -87,7 +87,7 @@ info = (ft_info *) xfer->data; sinlen = sizeof(sin); r = recvfrom(info->recv_fd, buf, len, 0, (struct sockaddr *) &sin, &sinlen); - purple_debug_info("QQ", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "==> recv %d bytes from File UDP Channel, remote ip[%s], remote port[%d]\n", r, inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port)); return r; @@ -121,12 +121,12 @@ sin.sin_port = g_htons(info->remote_minor_port); sin.sin_addr.s_addr = g_htonl(info->remote_real_ip); } - purple_debug_info("QQ", "sending to channel: %d.%d.%d.%d:%d\n", - sin.sin_addr.s_addr & 0xff, - (sin.sin_addr.s_addr >> 8) & 0xff, - (sin.sin_addr.s_addr >> 16) & 0xff, - sin.sin_addr.s_addr >> 24, - g_ntohs(sin.sin_port) + purple_debug(PURPLE_DEBUG_INFO, "QQ", "sending to channel: %d.%d.%d.%d:%d\n", + (int)sin.sin_addr.s_addr & 0xff, + (int)(sin.sin_addr.s_addr >> 8) & 0xff, + (int)(sin.sin_addr.s_addr >> 16) & 0xff, + (int)sin.sin_addr.s_addr >> 24, + (int)g_ntohs(sin.sin_port) ); return sendto(info->sender_fd, buf, len, 0, (struct sockaddr *) &sin, sizeof(sin)); } @@ -207,20 +207,20 @@ qq_xfer_close_file(xfer); if (info->dest_fp != NULL) { fclose(info->dest_fp); - purple_debug_info("QQ", "file closed\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "file closed\n"); } if (info->major_fd != 0) { close(info->major_fd); - purple_debug_info("QQ", "major port closed\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "major port closed\n"); } if (info->minor_fd != 0) { close(info->minor_fd); - purple_debug_info("QQ", "minor port closed\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "minor port closed\n"); } /* if (info->buffer != NULL) { munmap(info->buffer, purple_xfer_get_size(xfer)); - purple_debug_info("QQ", "file mapping buffer is freed.\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "file mapping buffer is freed.\n"); } */ g_free(info); @@ -235,7 +235,7 @@ real_ip_str = gen_ip_str((guint8 *) &ip); ip = g_htonl(info->remote_internet_ip); internet_ip_str = gen_ip_str((guint8 *) &ip); - purple_debug_info("QQ", "remote internet ip[%s:%d], major port[%d], real ip[%s], minor port[%d]\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "remote internet ip[%s:%d], major port[%d], real ip[%s], minor port[%d]\n", internet_ip_str, info->remote_internet_port, info->remote_major_port, real_ip_str, info->remote_minor_port ); @@ -393,7 +393,7 @@ info->local_real_ip = 0x7f000001; */ info->local_real_ip = g_ntohl(inet_addr(purple_network_get_my_ip(-1))); - purple_debug_info("QQ", "local real ip is %x", info->local_real_ip); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "local real ip is %x", info->local_real_ip); for (i = 0; i < 2; i++) { sockfd = socket(PF_INET, SOCK_DGRAM, 0); @@ -412,13 +412,13 @@ case 0: info->local_major_port = listen_port; info->major_fd = sockfd; - purple_debug_info("QQ", "UDP Major Channel created on port[%d]\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "UDP Major Channel created on port[%d]\n", info->local_major_port); break; case 1: info->local_minor_port = listen_port; info->minor_fd = sockfd; - purple_debug_info("QQ", "UDP Minor Channel created on port[%d]\n", + purple_debug(PURPLE_DEBUG_INFO, "QQ", "UDP Minor Channel created on port[%d]\n", info->local_minor_port); break; } @@ -475,9 +475,9 @@ bytes += qq_putdata (raw_data + bytes, (guint8 *) filelen_str, filelen_strlen); if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); + qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes); else - purple_debug_info("qq_send_packet_file_request", + purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_request", "%d bytes expected but got %d bytes\n", packet_len, bytes); @@ -497,7 +497,7 @@ qd = (qq_data *) gc->proto_data; info = (ft_info *) qd->xfer->data; - purple_debug_info("QQ", "I've accepted the file transfer request from %d\n", to_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "I've accepted the file transfer request from %d\n", to_uid); _qq_xfer_init_socket(qd->xfer); packet_len = 79; @@ -516,9 +516,9 @@ info->local_real_ip = real_ip; if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); + qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes); else - purple_debug_info("qq_send_packet_file_accept", + purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_accept", "%d bytes expected but got %d bytes\n", packet_len, bytes); } @@ -539,13 +539,13 @@ raw_data = g_newa (guint8, packet_len); bytes = 0; - purple_debug_info("QQ", "<== sending qq file notify ip packet\n"); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "<== sending qq file notify ip packet\n"); bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_NOTIFY, qd, TRUE); bytes += qq_fill_conn_info(raw_data + bytes, info); if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); + qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes); else - purple_debug_info("qq_send_packet_file_notify", + purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_notify", "%d bytes expected but got %d bytes\n", packet_len, bytes); @@ -561,7 +561,7 @@ guint8 *raw_data; gint packet_len, bytes; - purple_debug_info("_qq_send_packet_file_reject", "start"); + purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_reject", "start"); qd = (qq_data *) gc->proto_data; packet_len = 64; @@ -571,9 +571,9 @@ bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_DENY_UDP, qd, TRUE); if (packet_len == bytes) - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); + qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes); else - purple_debug_info("qq_send_packet_file", + purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file", "%d bytes expected but got %d bytes\n", packet_len, bytes); } @@ -585,27 +585,27 @@ guint8 *raw_data; gint packet_len, bytes; - purple_debug_info("_qq_send_packet_file_cancel", "start\n"); + purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "start\n"); qd = (qq_data *) gc->proto_data; packet_len = 64; raw_data = g_newa (guint8, packet_len); bytes = 0; - purple_debug_info("_qq_send_packet_file_cancel", "before create header\n"); + purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "before create header\n"); bytes += _qq_create_packet_file_header(raw_data + bytes, to_uid, QQ_FILE_TRANS_CANCEL, qd, TRUE); - purple_debug_info("_qq_send_packet_file_cancel", "end create header\n"); + purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "end create header\n"); if (packet_len == bytes) { - purple_debug_info("_qq_send_packet_file_cancel", "before send cmd\n"); - qq_send_cmd(gc, QQ_CMD_SEND_IM, raw_data, bytes); + purple_debug(PURPLE_DEBUG_INFO, "_qq_send_packet_file_cancel", "before send cmd\n"); + qq_send_cmd (qd, QQ_CMD_SEND_IM, raw_data, bytes); } else - purple_debug_info("qq_send_packet_file", + purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file", "%d bytes expected but got %d bytes\n", packet_len, bytes); - purple_debug_info("qq_send_packet_file_cancel", "end\n"); + purple_debug (PURPLE_DEBUG_INFO, "qq_send_packet_file_cancel", "end\n"); } /* request to send a file */ @@ -694,7 +694,7 @@ /* border has been checked before if (*cursor >= (data + data_len - 1)) { - purple_debug_warning("QQ", + purple_debug (PURPLE_DEBUG_WARNING, "QQ", "Received file reject message is empty\n"); return; } @@ -724,7 +724,8 @@ /* border has been checked before if (*cursor >= (data + data_len - 1)) { - purple_debug_warning("QQ", "Received file reject message is empty\n"); + purple_debug (PURPLE_DEBUG_WARNING, "QQ", + "Received file reject message is empty\n"); return; } */ @@ -754,7 +755,8 @@ info = (ft_info *) qd->xfer->data; if (data_len <= 30 + QQ_CONN_INFO_LEN) { - purple_debug_warning("QQ", "Received file reject message is empty\n"); + purple_debug (PURPLE_DEBUG_WARNING, "QQ", + "Received file reject message is empty\n"); return; } @@ -787,7 +789,8 @@ info->to_uid = sender_uid; if (data_len <= 2 + 30 + QQ_CONN_INFO_LEN) { - purple_debug_warning("QQ", "Received file request message is empty\n"); + purple_debug (PURPLE_DEBUG_WARNING, "QQ", + "Received file request message is empty\n"); return; } bytes = 0; @@ -803,7 +806,7 @@ /* FACE from IP detector, ignored by gfhuang */ if(g_ascii_strcasecmp(fileinfo[0], "FACE") == 0) { - purple_debug_warning("QQ", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Received a FACE ip detect from qq-%d, so he/she must be online :)\n", sender_uid); b = purple_find_buddy(gc->account, sender_name); @@ -823,11 +826,11 @@ qq_update_buddy_contact(gc, q_bud); } else - purple_debug_info("QQ", "buddy %d is already online\n", sender_uid); + purple_debug(PURPLE_DEBUG_INFO, "QQ", "buddy %d is already online\n", sender_uid); } else - purple_debug_warning("QQ", "buddy %d is not in list\n", sender_uid); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "buddy %d is not in list\n", sender_uid); g_free(sender_name); g_strfreev(fileinfo); @@ -889,7 +892,8 @@ xfer = qd->xfer; info = (ft_info *) qd->xfer->data; if (data_len <= 2 + 30 + QQ_CONN_INFO_LEN) { - purple_debug_warning("QQ", "Received file notify message is empty\n"); + purple_debug (PURPLE_DEBUG_WARNING, "QQ", + "Received file notify message is empty\n"); return; }
--- a/libpurple/protocols/qq/sys_msg.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/sys_msg.c Mon Sep 15 03:04:07 2008 +0000 @@ -126,7 +126,7 @@ gint ack_len, bytes; qd = (qq_data *) gc->proto_data; - + str = g_strdup_printf("%d", from); bar = 0x1e; ack_len = 1 + 1 + strlen(str) + 1 + 2; @@ -142,9 +142,9 @@ g_free(str); if (bytes == ack_len) /* creation OK */ - qq_send_server_reply(gc, QQ_CMD_ACK_SYS_MSG, 0, ack, ack_len); + qq_send_cmd_detail(qd, QQ_CMD_ACK_SYS_MSG, 0, FALSE, ack, ack_len); else - purple_debug_error("QQ", + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail creating sys msg ACK, expect %d bytes, build %d bytes\n", ack_len, bytes); } @@ -194,8 +194,8 @@ g_return_if_fail(from != NULL && to != NULL); - message = g_strdup_printf(_("Requestion rejected by %s"), from); - reason = g_strdup_printf(_("Message: %s"), msg_utf8); + message = g_strdup_printf(_("User %s rejected your request"), from); + reason = g_strdup_printf(_("Reason: %s"), msg_utf8); _qq_sys_msg_log_write(gc, message, from); purple_notify_info(gc, NULL, message, reason); @@ -214,7 +214,7 @@ qd = (qq_data *) gc->proto_data; qq_add_buddy_by_recv_packet(gc, strtol(from, NULL, 10), TRUE, TRUE); - message = g_strdup_printf(_("Requestion approved by %s"), from); + message = g_strdup_printf(_("User %s approved your request"), from); _qq_sys_msg_log_write(gc, message, from); purple_notify_info(gc, NULL, message, NULL); @@ -263,9 +263,9 @@ g2 = g_new0(gc_and_uid, 1); g2->gc = gc; g2->uid = strtol(from, NULL, 10); - message = g_strdup_printf(_("%s is not in buddy list"), from); + message = g_strdup_printf(_("%s is not in your buddy list"), from); purple_request_action(gc, NULL, message, - _("Would you add?"), PURPLE_DEFAULT_ACTION_NONE, + _("Would you like to add him?"), PURPLE_DEFAULT_ACTION_NONE, purple_connection_get_account(gc), name, NULL, g2, 3, _("Cancel"), NULL, @@ -279,19 +279,14 @@ static void _qq_process_msg_sys_notice(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) { - qq_data *qd = (qq_data *) gc->proto_data; gchar *title, *content; g_return_if_fail(from != NULL && to != NULL); - title = g_strdup_printf(_("QQ Server Notice from %s:"), from); + title = g_strdup_printf(_("Notice from: %s"), from); content = g_strdup_printf(_("%s"), msg_utf8); - if (qd->is_show_notice) { - purple_notify_info(gc, NULL, title, content); - } else { - purple_debug_info("QQ", "Server notice from %s:\n%s", from, msg_utf8); -} + purple_notify_info(gc, NULL, title, content); g_free(title); g_free(content); } @@ -315,19 +310,12 @@ _qq_send_packet_ack_msg_sys(gc, code[0], strtol(from, NULL, 10), seq); if (strtol(to, NULL, 10) != qd->uid) { /* not to me */ - purple_debug_error("QQ", "Recv sys msg to [%s], not me!, discard\n", to); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Recv sys msg to [%s], not me!, discard\n", to); g_strfreev(segments); return; } msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - if (from == NULL && msg_utf8) { - purple_debug_error("QQ", "Recv NULL sys msg to [%s], discard\n", to); - g_strfreev(segments); - g_free(msg_utf8); - return; - } - switch (strtol(code, NULL, 10)) { case QQ_MSG_SYS_BEING_ADDED: _qq_process_msg_sys_being_added(gc, from, to, msg_utf8); @@ -345,12 +333,12 @@ _qq_process_msg_sys_notice(gc, from, to, msg_utf8); break; case QQ_MSG_SYS_NEW_VERSION: - purple_debug_warning("QQ", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "QQ server says there is newer version than %s\n", qq_get_ver_desc(QQ_CLIENT)); break; default: - purple_debug_warning("QQ", "Recv unknown sys msg code: %s\n", code); - purple_debug_warning("QQ", "the msg is : %s\n", msg_utf8); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Recv unknown sys msg code: %s\n", code); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "the msg is : %s\n", msg_utf8); } g_free(msg_utf8); g_strfreev(segments);
--- a/libpurple/protocols/qq/utils.c Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/utils.c Mon Sep 15 03:04:07 2008 +0000 @@ -47,8 +47,8 @@ struct sockaddr_in sin; socklen_t len = sizeof(sin); getsockname(fd, (struct sockaddr *)&sin, &len); - purple_debug_info(desc, "%s:%d\n", - inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port)); + purple_debug(PURPLE_DEBUG_INFO, desc, "%s:%d\n", + inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port)); } */ @@ -121,16 +121,16 @@ for (i = 0; segments[i] != NULL; i++) {; } if (i < expected_fields) { /* not enough fields */ - purple_debug_error("QQ", "Invalid data, expect %d fields, found only %d, discard\n", - expected_fields, i); + purple_debug(PURPLE_DEBUG_ERROR, "QQ", + "Invalid data, expect %d fields, found only %d, discard\n", expected_fields, i); g_strfreev(segments); 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); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Dangerous data, expect %d fields, found %d, return all\n", expected_fields, i); /* free up those not used */ for (j = expected_fields; j < i; j++) { - purple_debug_warning("QQ", "field[%d] is %s\n", j, segments[j]); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "field[%d] is %s\n", j, segments[j]); g_free(segments[j]); } @@ -218,7 +218,7 @@ msg_utf8 = i < len ? qq_to_utf8((gchar *) &incoming[i], QQ_CHARSET_DEFAULT) : NULL; if (msg_utf8 != NULL) { - purple_debug_warning("QQ", "Try extract GB msg: %s\n", msg_utf8); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Try extract GB msg: %s\n", msg_utf8); } return msg_utf8; } @@ -257,7 +257,7 @@ hex_buffer = strstrip(buffer); if (strlen(hex_buffer) % 2 != 0) { - purple_debug_warning("QQ", + purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Unable to convert an odd number of nibbles to a string of bytes!\n"); g_free(hex_buffer); return NULL; @@ -272,8 +272,8 @@ } else if (g_ascii_isalpha(*cursor) && (gint) *cursor - 87 < 16) { nibble1 = (gint) *cursor - 87; } else { - purple_debug_warning("QQ", "Invalid char \'%c\' found in hex string!\n", - *cursor); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Invalid char \'%c\' found in hex string!\n", *cursor); g_free(hex_str); return NULL; } @@ -284,7 +284,8 @@ } else if (g_ascii_isalpha(*cursor) && (gint) (*cursor - 87) < 16) { nibble2 = (gint) *cursor - 87; } else { - purple_debug_warning("QQ", "Invalid char found in hex string!\n"); + purple_debug(PURPLE_DEBUG_WARNING, "QQ", + "Invalid char found in hex string!\n"); g_free(hex_str); return NULL; } @@ -361,7 +362,22 @@ void qq_show_packet(const gchar *desc, const guint8 *buf, gint len) { - qq_hex_dump(PURPLE_DEBUG_INFO, "QQ", buf, len, desc); + /* + char buf1[8*len+2], buf2[10]; + int i; + buf1[0] = 0; + for (i = 0; i < len; i++) { + sprintf(buf2, " %02x(%d)", buf[i] & 0xff, buf[i] & 0xff); + strcat(buf1, buf2); + } + strcat(buf1, "\n"); + purple_debug(PURPLE_DEBUG_INFO, desc, "%s", buf1); + */ + + /* modified by s3e, 20080424 */ + qq_hex_dump(PURPLE_DEBUG_INFO, desc, + buf, len, + ""); } /* convert face num from packet (0-299) to local face (1-100) */ @@ -381,16 +397,5 @@ if (purple_prefs_exists("/prpl/qq/buddy_icon_dir")) return purple_prefs_get_string("/prpl/qq/buddy_icon_dir"); else - return QQ_BUDDY_ICON_DIR; + return NULL; } - -#ifdef _WIN32 -const char *qq_win32_buddy_icon_dir(void) -{ - static char *dir = NULL; - if (dir == NULL) - dir = g_build_filename(wpurple_install_dir(), "pixmaps", - "purple", "buddy_icons", "qq", NULL); - return dir; -} -#endif
--- a/libpurple/protocols/qq/utils.h Thu Sep 11 13:25:07 2008 +0000 +++ b/libpurple/protocols/qq/utils.h Mon Sep 15 03:04:07 2008 +0000 @@ -56,6 +56,5 @@ guint8 *hex_str_to_bytes(const gchar *buf, gint *out_len); const gchar *qq_buddy_icon_dir(void); -const gchar *qq_win32_buddy_icon_dir(void); #endif