# HG changeset patch # User SHiNE CsyFeK # Date 1224687512 0 # Node ID 1bdf7b60268495e608afa10efd6aa874bc308107 # Parent 0a92aa673a33bcc181fc9e75a4faf9d90b8c455e 2008.10.07 - ccpaging * Update qun conversation * Drop group_conv.c and group_conv.h diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/ChangeLog --- a/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:58:32 2008 +0000 @@ -1,3 +1,6 @@ +2008.10.07 - ccpaging + * Update qun conversation + 2008.10.05 - lonicerae * Bug fix in 'About OpenQ' dialog diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/Makefile.am --- a/libpurple/protocols/qq/Makefile.am Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/Makefile.am Wed Oct 22 14:58:32 2008 +0000 @@ -18,8 +18,6 @@ file_trans.h \ group.c \ group.h \ - group_conv.c \ - group_conv.h \ group_find.c \ group_find.h \ group_free.c \ diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/Makefile.mingw --- a/libpurple/protocols/qq/Makefile.mingw Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/Makefile.mingw Wed Oct 22 14:58:32 2008 +0000 @@ -46,7 +46,6 @@ qq_crypt.c \ file_trans.c \ group.c \ - group_conv.c \ group_find.c \ group_free.c \ group_internal.c \ diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/buddy_info.c --- a/libpurple/protocols/qq/buddy_info.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/buddy_info.c Wed Oct 22 14:58:32 2008 +0000 @@ -245,7 +245,7 @@ bytes += qq_put8(raw_data + bytes, bar); /* important! skip the first uid entry */ - join = g_strjoinv("\x1f", segments +1); + join = g_strjoinv("\x1f", segments + 1); bytes += qq_putdata(raw_data + bytes, (guint8 *)join, strlen(join)); g_free(join); @@ -569,55 +569,56 @@ } /* after getting info or modify myself, refresh the buddy list accordingly */ -static void qq_set_buddy_info(gchar **segments, PurpleConnection *gc) +static void qq_update_buddy_info(PurpleConnection *gc, gchar **segments) { - PurpleBuddy *purple_buddy; + PurpleBuddy *buddy; qq_data *qd; + qq_buddy *bd; guint32 uid; - qq_buddy *buddy; + gchar *who; gchar *alias_utf8; - gchar *purple_name; PurpleAccount *account = purple_connection_get_account(gc); qd = (qq_data *) gc->proto_data; uid = strtol(segments[QQ_INFO_UID], NULL, 10); - purple_name = uid_to_purple_name(uid); - + who = uid_to_purple_name(uid); + alias_utf8 = qq_to_utf8(segments[QQ_INFO_NICK], QQ_CHARSET_DEFAULT); - if (qd->uid == strtol(segments[QQ_INFO_UID], NULL, 10)) { /* it is me */ + if (uid == qd->uid) { /* it is me */ purple_debug_info("QQ", "Got my info\n"); qd->my_icon = strtol(segments[QQ_INFO_FACE], NULL, 10); - if (alias_utf8 != NULL) + if (alias_utf8 != NULL) { purple_account_set_alias(account, alias_utf8); - + } /* add me to buddy list */ - purple_buddy = purple_find_buddy(gc->account, purple_name); - if ( purple_buddy == NULL) { - purple_buddy = qq_create_buddy(gc, uid, TRUE, FALSE); - } - buddy = g_new0(qq_buddy, 1); - buddy->uid = uid; - buddy->status = QQ_BUDDY_ONLINE_NORMAL; - purple_buddy->proto_data = buddy; - qd->buddies = g_list_append(qd->buddies, buddy); + buddy = qq_buddy_find_or_new(gc, uid); + } else { + buddy = purple_find_buddy(gc->account, who); + } + + if (buddy == NULL && buddy->proto_data == NULL) { + g_free(who); + g_free(alias_utf8); + return; } /* update buddy list (including myself, if myself is the buddy) */ - purple_buddy = purple_find_buddy(gc->account, purple_name); - buddy = (purple_buddy == NULL) ? NULL : (qq_buddy *) purple_buddy->proto_data; - if (buddy != NULL) { /* I have this buddy */ - buddy->age = strtol(segments[QQ_INFO_AGE], NULL, 10); - buddy->gender = strtol(segments[QQ_INFO_GENDER], NULL, 10); - buddy->face = strtol(segments[QQ_INFO_FACE], NULL, 10); - if (alias_utf8 != NULL) - buddy->nickname = g_strdup(alias_utf8); - qq_update_buddy_contact(gc, buddy); - buddy_local_icon_upate(gc->account, purple_name, buddy->face); - } else { - purple_debug_info("QQ", "Can not find buddy data of %s\n", purple_name); + bd = (qq_buddy *)buddy->proto_data; + + bd->age = strtol(segments[QQ_INFO_AGE], NULL, 10); + bd->gender = strtol(segments[QQ_INFO_GENDER], NULL, 10); + bd->face = strtol(segments[QQ_INFO_FACE], NULL, 10); + if (alias_utf8 != NULL) { + if (bd->nickname) g_free(bd->nickname); + bd->nickname = g_strdup(alias_utf8); } - g_free(purple_name); + bd->last_update = time(NULL); + + purple_blist_server_alias_buddy(buddy, bd->nickname); + buddy_local_icon_upate(gc->account, who, bd->face); + + g_free(who); g_free(alias_utf8); } @@ -652,13 +653,13 @@ segments[QQ_INFO_FACE] = icon; request_modify_info(gc, segments); - qq_set_buddy_info(segments, gc); + qq_update_buddy_info(gc, segments); } g_strfreev(segments); return; } - qq_set_buddy_info(segments, gc); + qq_update_buddy_info(gc, segments); switch (action) { case QQ_BUDDY_INFO_DISPLAY: info_display_only(gc, segments); @@ -712,36 +713,35 @@ void qq_request_get_buddies_level(PurpleConnection *gc, gint update_class) { + qq_data *qd = (qq_data *) gc->proto_data; + PurpleBuddy *buddy; + qq_buddy *buddy_data; guint8 *buf; - guint16 size; - qq_buddy *q_bud; - qq_data *qd = (qq_data *) gc->proto_data; - GList *node = qd->buddies; - gint bytes = 0; - - if ( qd->buddies == NULL) { - return; - } + GSList *buddies, *it; + gint bytes; /* server only reply levels for online buddies */ - size = 4 * g_list_length(qd->buddies) + 1 + 4; - buf = g_newa(guint8, size); + buf = g_newa(guint8, MAX_PACKET_SIZE); + + bytes = 0; bytes += qq_put8(buf + bytes, 0x00); - while (NULL != node) { - q_bud = (qq_buddy *) node->data; - if (NULL != q_bud) { - bytes += qq_put32(buf + bytes, q_bud->uid); - } - node = node->next; + buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); + for (it = buddies; it; it = it->next) { + buddy = it->data; + if (buddy == NULL) continue; + if (buddy->proto_data == NULL) continue; + buddy_data = (qq_buddy *)buddy->proto_data; + if (buddy_data->uid == 0) continue; + if (buddy_data->uid == qd->uid) continue; + bytes += qq_put32(buf + bytes, buddy_data->uid); } - /* my id should be the end if included */ + /* my uid must 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_mess(gc, QQ_CMD_GET_LEVEL, buf, bytes, update_class, 0); } static void process_level(PurpleConnection *gc, guint8 *data, gint data_len) { - qq_data *qd = (qq_data *) gc->proto_data; gint bytes = 0; guint32 uid, onlineTime; guint16 level, timeRemainder; @@ -754,12 +754,8 @@ bytes += qq_get16(&timeRemainder, data + bytes); 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); - } - buddy = qq_get_buddy(gc, uid); + buddy = qq_buddy_find(gc, uid); if (buddy == NULL) { purple_debug_error("QQ", "Got levels of %d not in my buddy list\n", uid); continue; @@ -778,7 +774,6 @@ static void process_level_2007(PurpleConnection *gc, guint8 *data, gint data_len) { - qq_data *qd = (qq_data *) gc->proto_data; gint bytes; guint32 uid, onlineTime; guint16 level, timeRemainder; @@ -795,12 +790,7 @@ 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); - } - - buddy = qq_get_buddy(gc, uid); + buddy = qq_buddy_find(gc, uid); if (buddy == NULL) { purple_debug_error("QQ", "Got levels of %d not in my buddy list\n", uid); return; diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/buddy_list.c --- a/libpurple/protocols/qq/buddy_list.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/buddy_list.c Wed Oct 22 14:58:32 2008 +0000 @@ -82,7 +82,7 @@ /* 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_request_get_buddies(PurpleConnection *gc, guint16 position, gint update_class) { qq_data *qd; guint8 raw_data[16] = {0}; @@ -158,16 +158,24 @@ } /* process the reply packet for get_buddies_online packet */ -guint8 qq_process_get_buddies_online_reply(guint8 *data, gint data_len, PurpleConnection *gc) +guint8 qq_process_get_buddies_online(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; gint bytes, bytes_start; gint count; guint8 position; qq_buddy *buddy; - qq_buddy_online bo; int entry_len = 38; + qq_buddy_status bs; + struct { + guint16 unknown1; + guint8 ext_flag; + guint8 comm_flag; + guint16 unknown2; + guint8 ending; /* 0x00 */ + } packet; + g_return_val_if_fail(data != NULL && data_len != 0, -1); qd = (qq_data *) gc->proto_data; @@ -185,41 +193,42 @@ (data_len - bytes), entry_len); break; } - memset(&bo, 0 ,sizeof(bo)); + memset(&bs, 0 ,sizeof(bs)); + memset(&packet, 0 ,sizeof(packet)); /* set flag */ bytes_start = bytes; /* based on one online buddy entry */ /* 000-030 qq_buddy_status */ - bytes += get_buddy_status(&(bo.bs), data + bytes); + bytes += get_buddy_status(&bs, data + bytes); /* 031-032: */ - bytes += qq_get16(&bo.unknown1, data + bytes); + bytes += qq_get16(&packet.unknown1, data + bytes); /* 033-033: ext_flag */ - bytes += qq_get8(&bo.ext_flag, data + bytes); + bytes += qq_get8(&packet.ext_flag, data + bytes); /* 034-034: comm_flag */ - bytes += qq_get8(&bo.comm_flag, data + bytes); + bytes += qq_get8(&packet.comm_flag, data + bytes); /* 035-036: */ - bytes += qq_get16(&bo.unknown2, data + bytes); + bytes += qq_get16(&packet.unknown2, data + bytes); /* 037-037: */ - bytes += qq_get8(&bo.ending, data + bytes); /* 0x00 */ + bytes += qq_get8(&packet.ending, data + bytes); /* 0x00 */ /* skip 4 bytes in qq2007 */ if (qd->client_version >= 2007) bytes += 4; - if (bo.bs.uid == 0 || (bytes - bytes_start) != entry_len) { + if (bs.uid == 0 || (bytes - bytes_start) != entry_len) { purple_debug_error("QQ", "uid=0 or entry complete len(%d) != %d", (bytes - bytes_start), 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); + if (bs.uid == qd->uid) { + purple_debug_warning("QQ", "I am in online list %d\n", bs.uid); } /* update buddy information */ - buddy = qq_get_buddy(gc, bo.bs.uid); + buddy = qq_buddy_find(gc, bs.uid); if (buddy == NULL) { purple_debug_error("QQ", - "Got an online buddy %d, but not in my buddy list\n", bo.bs.uid); + "Got an online buddy %d, but not in my buddy list\n", bs.uid); continue; } /* we find one and update qq_buddy */ @@ -227,18 +236,18 @@ if(0 != fe->s->client_tag) q_bud->client_tag = fe->s->client_tag; */ - buddy->ip.s_addr = bo.bs.ip.s_addr; - buddy->port = bo.bs.port; - buddy->status = bo.bs.status; - buddy->ext_flag = bo.ext_flag; - buddy->comm_flag = bo.comm_flag; - qq_update_buddy_contact(gc, buddy); + buddy->ip.s_addr = bs.ip.s_addr; + buddy->port = bs.port; + buddy->status = bs.status; + buddy->ext_flag = packet.ext_flag; + buddy->comm_flag = packet.comm_flag; + qq_update_buddy_status(gc, bs.uid, bs.status, packet.comm_flag); count++; } if(bytes > data_len) { purple_debug_error("QQ", - "qq_process_get_buddies_online_reply: Dangerous error! maybe protocol changed, notify developers!\n"); + "qq_process_get_buddies_online: Dangerous error! maybe protocol changed, notify developers!\n"); } purple_debug_info("QQ", "Received %d online buddies, nextposition=%u\n", @@ -248,16 +257,15 @@ /* process reply for get_buddies_list */ -guint16 qq_process_get_buddies_list_reply(guint8 *data, gint data_len, PurpleConnection *gc) +guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; - qq_buddy *buddy; + qq_buddy bd; gint bytes_expected, count; gint bytes, buddy_bytes; gint nickname_len; guint16 position, unknown; - gchar *purple_name; - PurpleBuddy *purple_buddy; + PurpleBuddy *buddy; g_return_val_if_fail(data != NULL && data_len != 0, -1); @@ -273,26 +281,26 @@ /* the following data is buddy list in this packet */ count = 0; while (bytes < data_len) { - buddy = g_new0(qq_buddy, 1); + memset(&bd, 0, sizeof(bd)); /* set flag */ buddy_bytes = bytes; /* 000-003: uid */ - bytes += qq_get32(&buddy->uid, data + bytes); + bytes += qq_get32(&bd.uid, data + bytes); /* 004-005: icon index (1-255) */ - bytes += qq_get16(&buddy->face, data + bytes); + bytes += qq_get16(&bd.face, data + bytes); /* 006-006: age */ - bytes += qq_get8(&buddy->age, data + bytes); + bytes += qq_get8(&bd.age, data + bytes); /* 007-007: gender */ - bytes += qq_get8(&buddy->gender, data + bytes); + bytes += qq_get8(&bd.gender, data + bytes); - nickname_len = qq_get_vstr(&buddy->nickname, QQ_CHARSET_DEFAULT, data + bytes); + nickname_len = qq_get_vstr(&bd.nickname, QQ_CHARSET_DEFAULT, data + bytes); bytes += nickname_len; - qq_filter_str(buddy->nickname); + qq_filter_str(bd.nickname); /* Fixme: merge following as 32bit flag */ bytes += qq_get16(&unknown, data + bytes); - bytes += qq_get8(&buddy->ext_flag, data + bytes); - bytes += qq_get8(&buddy->comm_flag, data + bytes); + bytes += qq_get8(&bd.ext_flag, data + bytes); + bytes += qq_get8(&bd.comm_flag, data + bytes); if (qd->client_version >= 2007) { bytes += 4; /* skip 4 bytes */ @@ -301,11 +309,10 @@ bytes_expected = 12 + nickname_len; } - if (buddy->uid == 0 || (bytes - buddy_bytes) != bytes_expected) { + if (bd.uid == 0 || (bytes - buddy_bytes) != bytes_expected) { purple_debug_info("QQ", "Buddy entry, expect %d bytes, read %d bytes\n", bytes_expected, bytes - buddy_bytes); - g_free(buddy->nickname); - g_free(buddy); + g_free(bd.nickname); continue; } else { count++; @@ -313,25 +320,27 @@ #if 1 purple_debug_info("QQ", "buddy [%09d]: ext_flag=0x%02x, comm_flag=0x%02x, nick=%s\n", - buddy->uid, buddy->ext_flag, buddy->comm_flag, buddy->nickname); + bd.uid, bd.ext_flag, bd.comm_flag, bd.nickname); #endif - purple_name = uid_to_purple_name(buddy->uid); - purple_buddy = purple_find_buddy(gc->account, purple_name); - g_free(purple_name); + buddy = qq_buddy_find_or_new(gc, bd.uid); + if (buddy == NULL || buddy->proto_data == NULL) { + g_free(bd.nickname); + continue; + } + bd.last_update = time(NULL); + purple_blist_server_alias_buddy(buddy, bd.nickname); + qq_update_buddy_status(gc, bd.uid, bd.status, bd.comm_flag); - if (purple_buddy == NULL) { - purple_buddy = qq_create_buddy(gc, buddy->uid, TRUE, FALSE); - } - - purple_buddy->proto_data = buddy; - qd->buddies = g_list_append(qd->buddies, buddy); - qq_update_buddy_contact(gc, buddy); + g_memmove(buddy->proto_data, &bd, sizeof(qq_buddy)); + /* nickname has been copy to buddy_data do not free + g_free(bd.nickname); + */ } if(bytes > data_len) { purple_debug_error("QQ", - "qq_process_get_buddies_list_reply: Dangerous error! maybe protocol changed, notify developers!"); + "qq_process_get_buddies: Dangerous error! maybe protocol changed, notify developers!"); } purple_debug_info("QQ", "Received %d buddies, nextposition=%u\n", @@ -385,7 +394,7 @@ } if(0x1 == type) { /* a buddy */ /* don't do anything but count - buddies are handled by - * qq_request_get_buddies_list */ + * qq_request_get_buddies */ ++i; } else { /* a group */ group = qq_room_search_id(gc, uid); @@ -421,21 +430,6 @@ * 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 */ -gboolean is_online(guint8 status) -{ - switch(status) { - case QQ_BUDDY_ONLINE_NORMAL: - case QQ_BUDDY_ONLINE_AWAY: - case QQ_BUDDY_ONLINE_INVISIBLE: - case QQ_BUDDY_ONLINE_BUSY: - return TRUE; - case QQ_BUDDY_CHANGE_TO_OFFLINE: - return FALSE; - } - return FALSE; -} - /* Help calculate the correct icon index to tell the server. */ gint get_icon_offset(PurpleConnection *gc) { @@ -515,7 +509,7 @@ } /* parse the reply packet for change_status */ -void qq_process_change_status_reply(guint8 *data, gint data_len, PurpleConnection *gc) +void qq_process_change_status(guint8 *data, gint data_len, PurpleConnection *gc) { qq_data *qd; gint bytes; @@ -534,7 +528,7 @@ } /* purple_debug_info("QQ", "Change status OK\n"); */ - buddy = qq_get_buddy(gc, qd->uid); + buddy = qq_buddy_find(gc, qd->uid); if (buddy != NULL) { qq_update_buddy_contact(gc, buddy); } @@ -567,7 +561,7 @@ * QQ_BUDDY_ONLINE_INVISIBLE */ bytes += qq_get32(&my_uid, data + bytes); - buddy = qq_get_buddy(gc, bs.uid); + buddy = qq_buddy_find(gc, bs.uid); if (buddy == NULL) { purple_debug_warning("QQ", "Get status of unknown buddy %d\n", bs.uid); return; @@ -590,6 +584,55 @@ } /*TODO: maybe this should be qq_update_buddy_status() ?*/ +void qq_update_buddy_status(PurpleConnection *gc, guint32 uid, guint8 status, guint8 flag) +{ + gchar *who; + gchar *status_id; + + g_return_if_fail(uid != 0); + + who = uid_to_purple_name(uid); + + /* purple supports signon and idle time + * but it is not much use for QQ, I do not use them */ + /* serv_got_update(gc, name, online, 0, q_bud->signon, q_bud->idle, bud->uc); */ + status_id = "available"; + switch(status) { + case QQ_BUDDY_OFFLINE: + status_id = "offline"; + break; + case QQ_BUDDY_ONLINE_NORMAL: + status_id = "available"; + break; + case QQ_BUDDY_CHANGE_TO_OFFLINE: + status_id = "offline"; + break; + case QQ_BUDDY_ONLINE_AWAY: + status_id = "away"; + break; + case QQ_BUDDY_ONLINE_INVISIBLE: + status_id = "invisible"; + break; + case QQ_BUDDY_ONLINE_BUSY: + status_id = "busy"; + break; + default: + status_id = "invisible"; + purple_debug_error("QQ", "unknown status: %x\n", status); + break; + } + purple_debug_info("QQ", "Update buddy %s status as %s\n", who, status_id); + purple_prpl_got_user_status(gc->account, who, status_id, NULL); + + if (flag & QQ_COMM_FLAG_MOBILE && status != QQ_BUDDY_OFFLINE) + purple_prpl_got_user_status(gc->account, who, "mobile", NULL); + else + purple_prpl_got_user_status_deactive(gc->account, who, "mobile"); + + g_free(who); +} + +/*TODO: maybe this should be qq_update_buddy_status() ?*/ void qq_update_buddy_contact(PurpleConnection *gc, qq_buddy *buddy) { gchar *purple_name; @@ -655,24 +698,58 @@ /* refresh all buddies online/offline, * after receiving reply for get_buddies_online packet */ -void qq_refresh_all_buddy_status(PurpleConnection *gc) +void qq_update_buddyies_status(PurpleConnection *gc) { - time_t now; - GList *list; qq_data *qd; - qq_buddy *q_bud; + PurpleBuddy *buddy; + qq_buddy *bd; + GSList *buddies, *it; + time_t tm_limit = time(NULL); qd = (qq_data *) (gc->proto_data); - now = time(NULL); - list = qd->buddies; + + tm_limit -= QQ_UPDATE_ONLINE_INTERVAL; - while (list != NULL) { - q_bud = (qq_buddy *) list->data; - if (q_bud != NULL && now > q_bud->last_update + QQ_UPDATE_ONLINE_INTERVAL - && q_bud->status != QQ_BUDDY_ONLINE_INVISIBLE) { - q_bud->status = QQ_BUDDY_CHANGE_TO_OFFLINE; - qq_update_buddy_contact(gc, q_bud); - } - list = list->next; + buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); + for (it = buddies; it; it = it->next) { + buddy = it->data; + if (buddy == NULL) continue; + if (buddy->proto_data == NULL) continue; + + bd = (qq_buddy *)buddy->proto_data; + if (bd->uid == 0) continue; + if (bd->uid == qd->uid) continue; /* my status is always online in my buddy list */ + if (tm_limit < bd->last_update) continue; + if (bd->status == QQ_BUDDY_ONLINE_INVISIBLE) continue; + + bd->status = QQ_BUDDY_CHANGE_TO_OFFLINE; + qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag); } } + +void qq_buddy_data_free_all(PurpleConnection *gc) +{ + qq_data *qd; + PurpleBuddy *buddy; + GSList *buddies, *it; + gint count = 0; + + qd = (qq_data *) (gc->proto_data); + + buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); + for (it = buddies; it; it = it->next) { + buddy = it->data; + if (buddy == NULL) continue; + if (buddy->proto_data == NULL) continue; + + qq_buddy_data_free(buddy->proto_data); + buddy->proto_data = NULL; + + count++; + } + + if (count > 0) { + purple_debug_info("QQ", "%d buddies' data are freed\n", count); + } +} + diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/buddy_list.h --- a/libpurple/protocols/qq/buddy_list.h Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/buddy_list.h Wed Oct 22 14:58:32 2008 +0000 @@ -40,34 +40,23 @@ guint8 unknown_key[QQ_KEY_LENGTH]; } qq_buddy_status; -enum { - QQ_BUDDY_OFFLINE = 0x00, - QQ_BUDDY_ONLINE_NORMAL = 10, - QQ_BUDDY_CHANGE_TO_OFFLINE = 20, - QQ_BUDDY_ONLINE_AWAY = 30, - QQ_BUDDY_ONLINE_INVISIBLE = 40, - QQ_BUDDY_ONLINE_BUSY = 50, -}; +void qq_request_get_buddies_online(PurpleConnection *gc, guint8 position, gint update_class); +guint8 qq_process_get_buddies_online(guint8 *data, gint data_len, PurpleConnection *gc); -void qq_request_get_buddies_online(PurpleConnection *gc, guint8 position, gint update_class); -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); -guint16 qq_process_get_buddies_list_reply(guint8 *data, gint data_len, PurpleConnection *gc); +void qq_request_get_buddies(PurpleConnection *gc, guint16 position, gint update_class); +guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc); void qq_request_get_buddies_and_rooms(PurpleConnection *gc, guint32 position, gint update_class); guint32 qq_process_get_buddies_and_rooms(guint8 *data, gint data_len, PurpleConnection *gc); -void qq_refresh_all_buddy_status(PurpleConnection *gc); - -gboolean is_online(guint8 status); - gint get_icon_offset(PurpleConnection *gc); void qq_request_change_status(PurpleConnection *gc, gint update_class); -void qq_process_change_status_reply(guint8 *data, gint data_len, PurpleConnection *gc); +void qq_process_change_status(guint8 *data, gint data_len, PurpleConnection *gc); void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc); -void qq_refresh_all_buddy_status(PurpleConnection *gc); +void qq_update_buddyies_status(PurpleConnection *gc); +void qq_update_buddy_status(PurpleConnection *gc, guint32 uid, guint8 status, guint8 flag); void qq_update_buddy_contact(PurpleConnection *gc, qq_buddy *q_bud); +void qq_buddy_data_free_all(PurpleConnection *gc); #endif diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/buddy_opt.c --- a/libpurple/protocols/qq/buddy_opt.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/buddy_opt.c Wed Oct 22 14:58:32 2008 +0000 @@ -291,7 +291,6 @@ qq_data *qd; gchar *purple_name; PurpleBuddy *buddy; - qq_buddy *q_buddy; g_return_if_fail(add_req != NULL); if (add_req->gc == NULL || add_req->uid == 0) { @@ -312,12 +311,13 @@ return; } - q_buddy = (qq_buddy *) buddy->proto_data; - if (q_buddy != NULL) - qd->buddies = g_list_remove(qd->buddies, q_buddy); - else + if (buddy->proto_data != NULL) { + qq_buddy_data_free(buddy->proto_data); + buddy->proto_data = NULL; + } else { purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name); - + } + purple_blist_remove_buddy(buddy); g_free(add_req); } @@ -476,6 +476,7 @@ g_free(nombre); } else { /* add OK */ qq_create_buddy(gc, uid, TRUE, TRUE); + msg = g_strdup_printf(_("Successed adding into %d's buddy list"), uid); qq_got_attention(gc, msg); g_free(msg); @@ -483,7 +484,7 @@ g_strfreev(segments); } -PurpleGroup *qq_create_group(const gchar *group_name) +PurpleGroup *qq_group_find_or_new(const gchar *group_name) { PurpleGroup *g; @@ -520,7 +521,7 @@ group_name = g_strdup(PURPLE_GROUP_QQ_UNKNOWN); } - group = qq_create_group(group_name); + group = qq_group_find_or_new(group_name); buddy_name = uid_to_purple_name(uid); purple_buddy = purple_find_buddy(gc->account, buddy_name); @@ -544,7 +545,6 @@ buddy = g_new0(qq_buddy, 1); buddy->uid = uid; purple_buddy->proto_data = buddy; - qd->buddies = g_list_append(qd->buddies, buddy); qq_request_buddy_info(gc, uid, 0, 0); qq_request_get_buddies_online(gc, 0, 0); if (qd->client_version >= 2007) { @@ -555,7 +555,7 @@ } purple_blist_add_buddy(purple_buddy, NULL, group, NULL); - purple_debug_warning("QQ", "Add new buddy: [%s]\n", buddy_name); + purple_debug_info("QQ", "Add new buddy: [%s]\n", buddy_name); g_free(buddy_name); g_free(group_name); @@ -563,7 +563,16 @@ return purple_buddy; } -qq_buddy *qq_get_buddy(PurpleConnection *gc, guint32 uid) +static qq_buddy *qq_buddy_data_new(guint32 uid) +{ + qq_buddy *buddy = g_new0(qq_buddy, 1); + memset(buddy, 0, sizeof(qq_buddy)); + buddy->uid = uid; + buddy->status = QQ_BUDDY_ONLINE_NORMAL; + return buddy; +} + +qq_buddy *qq_buddy_find(PurpleConnection *gc, guint32 uid) { gchar *purple_name; PurpleBuddy *purple_buddy; @@ -574,20 +583,85 @@ purple_buddy = purple_find_buddy(purple_connection_get_account(gc), purple_name); g_free(purple_name); - if (purple_buddy == NULL) return NULL; - + if (purple_buddy == NULL) { + purple_debug_error("QQ", "Can not find purple buddy of %d\n", uid); + return NULL; + } if (purple_buddy->proto_data == NULL) { purple_debug_error("QQ", "Can not find buddy data of %d\n", uid); return NULL; } - return (qq_buddy *) purple_buddy->proto_data; + return (qq_buddy *)purple_buddy->proto_data; +} + +void qq_buddy_data_free(qq_buddy *bd) +{ + g_return_if_fail(bd != NULL); + + if (bd->nickname) g_free(bd->nickname); + g_free(bd); +} + +static PurpleBuddy *qq_buddy_new(PurpleConnection *gc, gchar *who) +{ + PurpleBuddy *buddy; + PurpleGroup *group; + gchar *group_name; + + g_return_val_if_fail(gc->account != NULL && who != NULL, NULL); + + group_name = g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, + purple_account_get_username(gc->account)); + group = qq_group_find_or_new(group_name); + if (group == NULL) { + purple_debug_error("QQ", "Failed creating group %s\n", group_name); + return NULL; + } + + buddy = purple_buddy_new(gc->account, who, NULL); /* alias is NULL */ + buddy->proto_data = NULL; + + purple_blist_add_buddy(buddy, NULL, group, NULL); + purple_debug_info("QQ", "Add new purple buddy: [%s]\n", who); + + g_free(group_name); + + return buddy; +} + +PurpleBuddy *qq_buddy_find_or_new(PurpleConnection *gc, guint32 uid) +{ + PurpleBuddy *buddy; + gchar *who; + + g_return_val_if_fail(gc->account != NULL && uid != 0, NULL); + + who = uid_to_purple_name(uid); + + buddy = purple_find_buddy(gc->account, who); + if (buddy == NULL) { + buddy = qq_buddy_new(gc, who); + if (buddy == NULL) { + g_free(who); + return NULL; + } + } + + if (buddy->proto_data != NULL) { + g_free(who); + return buddy; + } + + buddy->proto_data = qq_buddy_data_new(uid); + + g_free(who); + return buddy; } /* remove a buddy and send packet to QQ server accordingly */ void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) { qq_data *qd; - qq_buddy *q_bud; guint32 uid; g_return_if_fail(gc != NULL && gc->proto_data != NULL); @@ -602,44 +676,17 @@ request_buddy_remove(gc, uid); } - q_bud = (qq_buddy *) buddy->proto_data; - if (q_bud != NULL) - qd->buddies = g_list_remove(qd->buddies, q_bud); - else + if (buddy->proto_data) { + qq_buddy_data_free(buddy->proto_data); + buddy->proto_data = NULL; + } else { purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name); - + } + /* Do not call purple_blist_remove_buddy, * otherwise purple segmentation fault */ } -/* free all qq_buddy */ -void qq_buddies_list_free(PurpleAccount *account, qq_data *qd) -{ - gint count; - qq_buddy *p; - gchar *name; - PurpleBuddy *b; - - count = 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->proto_data = NULL; - else - purple_debug_info("QQ", "qq_buddy %s not found in purple proto_data\n", name); - g_free(name); - - g_free(p); - count++; - } - if (count > 0) { - purple_debug_info("QQ", "%d qq_buddy structures are freed!\n", count); - } -} - /* someone wants to add you to his buddy list */ static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8) { diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/buddy_opt.h --- a/libpurple/protocols/qq/buddy_opt.h Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/buddy_opt.h Wed Oct 22 14:58:32 2008 +0000 @@ -30,15 +30,16 @@ #include "qq.h" +void qq_buddy_data_free(qq_buddy *bd); + void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); -qq_buddy *qq_get_buddy(PurpleConnection *gc, guint32 uid); +qq_buddy *qq_buddy_find(PurpleConnection *gc, guint32 uid); void qq_change_buddys_group(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group); void qq_remove_buddy_and_me(PurpleBlistNode * node); void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group); PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean is_create_data); -void qq_buddies_list_free(PurpleAccount *account, qq_data *qd); void qq_process_buddy_remove(guint8 *buf, gint buf_len, PurpleConnection *gc); void qq_process_buddy_remove_me(guint8 *data, gint data_len, PurpleConnection *gc); @@ -47,6 +48,7 @@ void qq_process_buddy_from_server(PurpleConnection *gc, int funct, gchar *from, gchar *to, gchar *msg_utf8); -PurpleGroup *qq_create_group(const gchar *group_name); +PurpleGroup *qq_group_find_or_new(const gchar *group_name); +PurpleBuddy *qq_buddy_find_or_new(PurpleConnection *gc, guint32 uid); #endif diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_conv.c --- a/libpurple/protocols/qq/group_conv.c Wed Oct 22 14:55:09 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/** - * @file group_conv.c - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include -#include "qq.h" - -#include "group_conv.h" -#include "buddy_list.h" -#include "qq_define.h" -#include "qq_network.h" -#include "qq_process.h" -#include "utils.h" - -/* show group conversation window */ -PurpleConversation *qq_room_conv_create(PurpleConnection *gc, qq_group *group) -{ - PurpleConversation *conv; - qq_data *qd; - gchar *topic_utf8; - - g_return_val_if_fail(group != NULL, NULL); - qd = (qq_data *) gc->proto_data; - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - group->title_utf8, purple_connection_get_account(gc)); - if (conv != NULL) { - /* show only one conversation per group */ - return conv; - } - - 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)); - if (conv != NULL) { - topic_utf8 = g_strdup_printf("%d %s", group->ext_id, group->notice_utf8); - purple_debug_info("QQ", "Set chat topic to %s\n", topic_utf8); - purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, topic_utf8); - g_free(topic_utf8); - - if (group->is_got_info) - qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, group->id); - else - qq_update_room(gc, 0, group->id); - return conv; - } - return NULL; -} - -/* refresh online member in group conversation window */ -void qq_group_conv_refresh_online_member(PurpleConnection *gc, qq_group *group) -{ - GList *names, *list, *flags; - qq_buddy *member; - gchar *member_name, *member_uid; - PurpleConversation *conv; - gint flag; - gboolean is_find; - g_return_if_fail(group != NULL); - - conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, - group->title_utf8, purple_connection_get_account(gc)); - - g_return_if_fail (conv != NULL && group->members != NULL); - - names = NULL; - flags = NULL; - - list = group->members; - while (list != NULL) { - member = (qq_buddy *) list->data; - - /* we need unique identifiers for everyone in the chat or else we'll - * run into problems with functions like get_cb_real_name from qq.c */ - member_name = (member->nickname != NULL && *(member->nickname) != '\0') ? - g_strdup_printf("%s (%u)", member->nickname, member->uid) : - g_strdup_printf("(%u)", member->uid); - member_uid = g_strdup_printf("(%u)", member->uid); - - flag = 0; - /* TYPING to put online above OP and FOUNDER */ - if (is_online(member->status)) flag |= (PURPLE_CBFLAGS_TYPING | PURPLE_CBFLAGS_VOICE); - if(1 == (member->role & 1)) flag |= PURPLE_CBFLAGS_OP; - if(member->uid == group->creator_uid) flag |= PURPLE_CBFLAGS_FOUNDER; - - is_find = TRUE; - if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_name)) - { - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), - member_name, - flag); - } else if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_uid)) - { - purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), - member_uid, - flag); - purple_conv_chat_rename_user(PURPLE_CONV_CHAT(conv), member_uid, member_name); - } else { - is_find = FALSE; - } - if (!is_find) { - /* always put it even offline */ - names = g_list_append(names, member_name); - flags = g_list_append(flags, GINT_TO_POINTER(flag)); - } else { - g_free(member_name); - } - g_free(member_uid); - list = list->next; - } - - if (names != NULL && flags != NULL) { - purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE); - } - - /* clean up names */ - while (names != NULL) { - member_name = (gchar *) names->data; - names = g_list_remove(names, member_name); - g_free(member_name); - } - g_list_free(flags); -} diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_conv.h --- a/libpurple/protocols/qq/group_conv.h Wed Oct 22 14:55:09 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/** - * @file group_conv.h - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _QQ_GROUP_CONV_H_ -#define _QQ_GROUP_CONV_H_ - -#include "connection.h" -#include "conversation.h" -#include "group.h" - -PurpleConversation *qq_room_conv_create(PurpleConnection *gc, qq_group *group); -void qq_group_conv_refresh_online_member(PurpleConnection *gc, qq_group *group); - -#endif diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_free.c --- a/libpurple/protocols/qq/group_free.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/group_free.c Wed Oct 22 14:58:32 2008 +0000 @@ -61,12 +61,15 @@ g_free(group); } -void qq_group_free_all(qq_data *qd) +void qq_group_free_all(PurpleConnection *gc) { + qq_data *qd; qq_group *group; gint count; - g_return_if_fail(qd != NULL); + g_return_if_fail (gc != NULL && gc->proto_data != NULL); + qd = (qq_data *) gc->proto_data; + count = 0; while (qd->groups != NULL) { group = (qq_group *) qd->groups->data; diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_free.h --- a/libpurple/protocols/qq/group_free.h Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/group_free.h Wed Oct 22 14:58:32 2008 +0000 @@ -30,6 +30,6 @@ #include "group.h" void qq_group_free(qq_group *group); -void qq_group_free_all(qq_data *qd); +void qq_group_free_all(PurpleConnection *gc); #endif diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_im.c --- a/libpurple/protocols/qq/group_im.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/group_im.c Wed Oct 22 14:58:32 2008 +0000 @@ -37,7 +37,6 @@ #include "group_info.h" #include "group_im.h" #include "group_opt.h" -#include "group_conv.h" #include "im.h" #include "qq_define.h" #include "packet_parse.h" @@ -45,6 +44,118 @@ #include "qq_process.h" #include "utils.h" +/* show group conversation window */ +PurpleConversation *qq_room_conv_new(PurpleConnection *gc, qq_group *group) +{ + PurpleConversation *conv; + qq_data *qd; + gchar *topic_utf8; + + g_return_val_if_fail(group != NULL, NULL); + qd = (qq_data *) gc->proto_data; + + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + group->title_utf8, purple_connection_get_account(gc)); + if (conv != NULL) { + /* show only one conversation per group */ + return conv; + } + + 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)); + if (conv != NULL) { + topic_utf8 = g_strdup_printf("%d %s", group->ext_id, group->notice_utf8); + purple_debug_info("QQ", "Set chat topic to %s\n", topic_utf8); + purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, topic_utf8); + g_free(topic_utf8); + + if (group->is_got_info) + qq_send_room_cmd_only(gc, QQ_ROOM_CMD_GET_ONLINES, group->id); + else + qq_update_room(gc, 0, group->id); + return conv; + } + return NULL; +} + +/* refresh online member in group conversation window */ +void qq_room_conv_set_onlines(PurpleConnection *gc, qq_group *group) +{ + GList *names, *list, *flags; + qq_buddy *member; + gchar *member_name, *member_uid; + PurpleConversation *conv; + gint flag; + gboolean is_find; + g_return_if_fail(group != NULL); + + conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, + group->title_utf8, purple_connection_get_account(gc)); + if (conv == NULL) { + purple_debug_warning("QQ", "Conversation \"%s\" is not opened\n", group->title_utf8); + return; + } + g_return_if_fail(group->members != NULL); + + names = NULL; + flags = NULL; + + list = group->members; + while (list != NULL) { + member = (qq_buddy *) list->data; + + /* we need unique identifiers for everyone in the chat or else we'll + * run into problems with functions like get_cb_real_name from qq.c */ + member_name = (member->nickname != NULL && *(member->nickname) != '\0') ? + g_strdup_printf("%s (%u)", member->nickname, member->uid) : + g_strdup_printf("(%u)", member->uid); + member_uid = g_strdup_printf("(%u)", member->uid); + + flag = 0; + /* TYPING to put online above OP and FOUNDER */ + if (is_online(member->status)) flag |= (PURPLE_CBFLAGS_TYPING | PURPLE_CBFLAGS_VOICE); + if(1 == (member->role & 1)) flag |= PURPLE_CBFLAGS_OP; + if(member->uid == group->creator_uid) flag |= PURPLE_CBFLAGS_FOUNDER; + + is_find = TRUE; + if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_name)) + { + purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), + member_name, + flag); + } else if (purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), member_uid)) + { + purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(conv), + member_uid, + flag); + purple_conv_chat_rename_user(PURPLE_CONV_CHAT(conv), member_uid, member_name); + } else { + is_find = FALSE; + } + if (!is_find) { + /* always put it even offline */ + names = g_list_append(names, member_name); + flags = g_list_append(flags, GINT_TO_POINTER(flag)); + } else { + g_free(member_name); + } + g_free(member_uid); + list = list->next; + } + + if (names != NULL && flags != NULL) { + purple_conv_chat_add_users(PURPLE_CONV_CHAT(conv), names, NULL, flags, FALSE); + } + + /* clean up names */ + while (names != NULL) { + member_name = (gchar *) names->data; + names = g_list_remove(names, member_name); + g_free(member_name); + } + g_list_free(flags); +} + /* send IM to a group */ void qq_send_packet_group_im(PurpleConnection *gc, qq_group *group, const gchar *msg) { @@ -151,7 +262,7 @@ conv = purple_find_conversation_with_account( PURPLE_CONV_TYPE_CHAT, group->title_utf8, account); if (conv == NULL && purple_prefs_get_bool("/plugins/prpl/qq/show_room_when_newin")) { - conv = qq_room_conv_create(gc, group); + conv = qq_room_conv_new(gc, group); } if (conv == NULL) { diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_im.h --- a/libpurple/protocols/qq/group_im.h Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/group_im.h Wed Oct 22 14:58:32 2008 +0000 @@ -27,8 +27,12 @@ #include #include "connection.h" +#include "conversation.h" #include "group.h" +PurpleConversation *qq_room_conv_new(PurpleConnection *gc, qq_group *group); +void qq_room_conv_set_onlines(PurpleConnection *gc, qq_group *group); + void qq_room_got_chat_in(PurpleConnection *gc, qq_group *group, guint32 uid_from, const gchar *msg, time_t in_time); diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_info.c --- a/libpurple/protocols/qq/group_info.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/group_info.c Wed Oct 22 14:58:32 2008 +0000 @@ -247,8 +247,7 @@ conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group->title_utf8, purple_connection_get_account(gc)); if(NULL == conv) { - purple_debug_warning("QQ", - "Conversation \"%s\" is not open, do not set topic\n", group->title_utf8); + purple_debug_warning("QQ", "Conversation \"%s\" is not opened\n", group->title_utf8); return; } diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_internal.c --- a/libpurple/protocols/qq/group_internal.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/group_internal.c Wed Oct 22 14:58:32 2008 +0000 @@ -63,7 +63,7 @@ PurpleChat *chat; components = qq_group_to_hashtable(group); chat = purple_chat_new(purple_connection_get_account(gc), group->title_utf8, components); - g = qq_create_group(PURPLE_GROUP_QQ_QUN); + g = qq_group_find_or_new(PURPLE_GROUP_QQ_QUN); purple_blist_add_chat(chat, g, NULL); purple_debug_info("QQ", "Added room \"%s\" to blist locally\n", group->title_utf8); } diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/group_join.c --- a/libpurple/protocols/qq/group_join.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/group_join.c Wed Oct 22 14:58:32 2008 +0000 @@ -31,13 +31,11 @@ #include "char_conv.h" #include "im.h" -#include "group_conv.h" #include "group_find.h" #include "group_internal.h" #include "group_info.h" #include "group_join.h" #include "group_opt.h" -#include "group_conv.h" #include "group_search.h" #include "group_im.h" #include "qq_define.h" @@ -284,7 +282,7 @@ group->my_role = QQ_ROOM_ROLE_YES; qq_group_refresh(gc, group); /* this must be shown before getting online members */ - qq_room_conv_create(gc, group); + qq_room_conv_new(gc, group); break; case QQ_ROOM_JOIN_NEED_AUTH: purple_debug_info("QQ", diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/im.c --- a/libpurple/protocols/qq/im.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/im.c Wed Oct 22 14:58:32 2008 +0000 @@ -163,19 +163,16 @@ { qq_data *qd; gchar *from; - PurpleBuddy *buddy; time_t now = time(NULL); - qd = (qq_data *) gc->proto_data; + g_return_if_fail(gc != NULL && gc->proto_data != NULL); + qd = gc->proto_data; g_return_if_fail(qd->uid > 0); + qq_buddy_find_or_new(gc, qd->uid); + from = uid_to_purple_name(qd->uid); - buddy = purple_find_buddy(gc->account, from); - if (buddy == NULL) { - qq_create_buddy(gc, qd->uid, TRUE, TRUE); - } - serv_got_im(gc, from, msg, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY, now); g_free(from); } diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/qq.c --- a/libpurple/protocols/qq/qq.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/qq.c Wed Oct 22 14:58:32 2008 +0000 @@ -374,18 +374,25 @@ /* we can show tiny icons on the four corners of buddy icon, */ static const char *qq_list_emblem(PurpleBuddy *b) { - /* each char** are refering to a filename in pixmaps/purple/status/default/ */ - qq_buddy *q_bud; + PurpleAccount *account; + PurpleConnection *gc; + qq_data *qd; + qq_buddy *buddy; - if (!b || !(q_bud = b->proto_data)) { + if (!b || !(account = b->account) || + !(gc = purple_account_get_connection(account)) || !(qd = gc->proto_data)) return NULL; + + buddy = (qq_buddy *)b->proto_data; + if (!buddy) { + return "not-authorized"; } - if (q_bud->comm_flag & QQ_COMM_FLAG_MOBILE) + if (buddy->comm_flag & QQ_COMM_FLAG_MOBILE) return "mobile"; - if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) + if (buddy->comm_flag & QQ_COMM_FLAG_VIDEO) return "video"; - if (q_bud->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) + if (buddy->comm_flag & QQ_COMM_FLAG_QQ_MEMBER) return "qq_member"; return NULL; @@ -512,6 +519,8 @@ { PurpleConnection *gc = (PurpleConnection *) action->context; qq_data *qd; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; if ( !qd->is_login ) { @@ -526,6 +535,7 @@ PurpleConnection *gc = (PurpleConnection *) action->context; qq_data *qd; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_BASE); } @@ -535,6 +545,7 @@ PurpleConnection *gc = (PurpleConnection *) action->context; qq_data *qd; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_EXT); } @@ -544,6 +555,7 @@ PurpleConnection *gc = (PurpleConnection *) action->context; qq_data *qd; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_ADDR); } @@ -553,12 +565,16 @@ PurpleConnection *gc = (PurpleConnection *) action->context; qq_data *qd; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; qq_request_buddy_info(gc, qd->uid, 0, QQ_BUDDY_INFO_MODIFY_CONTACT); } static void action_change_password(PurplePluginAction *action) { + PurpleConnection *gc = (PurpleConnection *) action->context; + + g_return_if_fail(NULL != gc && NULL != gc->proto_data); purple_notify_uri(NULL, "https://password.qq.com"); } @@ -571,6 +587,7 @@ struct tm *tm_local; int index; + g_return_if_fail(NULL != gc && NULL != gc->proto_data); qd = (qq_data *) gc->proto_data; info = g_string_new(""); diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/qq.h --- a/libpurple/protocols/qq/qq.h Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/qq.h Wed Oct 22 14:58:32 2008 +0000 @@ -179,7 +179,6 @@ struct in_addr my_ip; /* my ip address detected by server */ guint16 my_port; /* my port detected by server */ guint16 my_icon; /* my icon index */ - guint16 my_level; /* my level */ guint32 online_total; /* the number of online QQ users */ time_t online_last_update; /* last time send get_friends_online packet */ @@ -189,7 +188,6 @@ GList *groups; GSList *joining_groups; GSList *adding_groups_from_server; /* internal ids of groups the server wants in my blist */ - GList *buddies; GList *group_info_window; gboolean is_show_notice; diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/qq_define.c --- a/libpurple/protocols/qq/qq_define.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/qq_define.c Wed Oct 22 14:58:32 2008 +0000 @@ -245,3 +245,18 @@ return "Unknown Room Command"; } } + +/* check if status means online or offline */ +gboolean is_online(guint8 status) +{ + switch(status) { + case QQ_BUDDY_ONLINE_NORMAL: + case QQ_BUDDY_ONLINE_AWAY: + case QQ_BUDDY_ONLINE_INVISIBLE: + case QQ_BUDDY_ONLINE_BUSY: + return TRUE; + case QQ_BUDDY_CHANGE_TO_OFFLINE: + return FALSE; + } + return FALSE; +} diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/qq_define.h --- a/libpurple/protocols/qq/qq_define.h Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/qq_define.h Wed Oct 22 14:58:32 2008 +0000 @@ -115,4 +115,16 @@ QQ_SERVER_NOTICE= 0x06, QQ_SERVER_NEW_CLIENT = 0x09 }; + +enum { + QQ_BUDDY_OFFLINE = 0x00, + QQ_BUDDY_ONLINE_NORMAL = 10, + QQ_BUDDY_CHANGE_TO_OFFLINE = 20, + QQ_BUDDY_ONLINE_AWAY = 30, + QQ_BUDDY_ONLINE_INVISIBLE = 40, + QQ_BUDDY_ONLINE_BUSY = 50, +}; + +gboolean is_online(guint8 status); + #endif diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/qq_network.c --- a/libpurple/protocols/qq/qq_network.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/qq_network.c Wed Oct 22 14:58:32 2008 +0000 @@ -1040,8 +1040,8 @@ qd->my_ip.s_addr = 0; qd->my_port = 0; - qq_group_free_all(qd); - qq_buddies_list_free(gc->account, qd); + qq_group_free_all(gc); + qq_buddy_data_free_all(gc); } static gint packet_encap(qq_data *qd, guint8 *buf, gint maxlen, guint16 cmd, guint16 seq, diff -r 0a92aa673a33 -r 1bdf7b602684 libpurple/protocols/qq/qq_process.c --- a/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:55:09 2008 +0000 +++ b/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:58:32 2008 +0000 @@ -34,7 +34,6 @@ #include "qq_crypt.h" #include "group_search.h" -#include "group_conv.h" #include "group_find.h" #include "group_internal.h" #include "group_im.h" @@ -630,7 +629,7 @@ 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); + qq_request_get_buddies(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); @@ -824,13 +823,13 @@ case QQ_ROOM_CMD_GET_ONLINES: qq_process_room_cmd_get_onlines(data + bytes, data_len - bytes, gc); if (group != NULL) - qq_group_conv_refresh_online_member(gc, group); + qq_room_conv_set_onlines(gc, group); break; case QQ_ROOM_CMD_GET_BUDDIES: qq_process_room_cmd_get_buddies(data + bytes, data_len - bytes, gc); if (group != NULL) { group->is_got_info = TRUE; - qq_group_conv_refresh_online_member(gc, group); + qq_room_conv_set_onlines(gc, group); } break; default: @@ -898,23 +897,16 @@ case QQ_CMD_LOGIN: default: if (qd->client_version >= 2007) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); if (data_len >= 0) { - purple_debug_warning("QQ", "Dpwd_twice_md5 *OK*\n"); - } - else { - purple_debug_warning("QQ", "Dpwd_twice_md5 *FAILED*, try login_key, last data_len=%d\n", data_len); + purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); + } else { data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.login_key); if (data_len >= 0) { - purple_debug_warning("QQ", "Dlogin_key *OK*\n"); - } - else { - purple_debug_warning("QQ", "Dlogin_key *FAILED*\n"); + purple_debug_warning("QQ", "Decrypt login packet by login_key\n"); } } - } - else { + } else { /* May use password_twice_md5 in the past version like QQ2005 */ data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.random_key); if (data_len >= 0) { @@ -999,7 +991,6 @@ qq_update_all(gc, 0); break; default: - purple_debug_warning("QQ", "UNKNOWN LOGIN CMD: %d\n", cmd); process_unknow_cmd(gc, _("Unknow LOGIN CMD"), data, data_len, cmd, seq); return QQ_LOGIN_REPLY_ERR; } @@ -1061,7 +1052,7 @@ qq_process_get_buddy_info(data, data_len, ship32, gc); break; case QQ_CMD_CHANGE_STATUS: - qq_process_change_status_reply(data, data_len, gc); + qq_process_change_status(data, data_len, gc); break; case QQ_CMD_SEND_IM: do_im_ack(data, data_len, gc); @@ -1076,23 +1067,23 @@ } break; case QQ_CMD_GET_BUDDIES_ONLINE: - ret_8 = qq_process_get_buddies_online_reply(data, data_len, gc); + ret_8 = qq_process_get_buddies_online(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_info("QQ", "All online buddies received\n"); - qq_refresh_all_buddy_status(gc); + qq_update_buddyies_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); + ret_16 = qq_process_get_buddies(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); + qq_request_get_buddies(gc, ret_16, update_class); return; } purple_debug_info("QQ", "All buddies received. Requesting buddies' levels\n");