首页 | 数据结构 | 文件列表 | 数据字段 | 全局定义

buddy_list.c

浏览该文件的文档。
00001 
00023 // START OF FILE
00024 /*****************************************************************************/
00025 #include <string.h>             // g_memmove, memmove
00026 #include "debug.h"              // gaim_debug
00027 
00028 #include "utils.h"              // get_ip_str
00029 #include "packet_parse.h"       // create_packet, read_packet
00030 #include "buddy_list.h"
00031 #include "buddy_status.h"       // qq_buddy_status
00032 #include "buddy_opt.h"          // qq_add_buddy_by_recv_packet
00033 #include "char_conv.h"          // qq_to_utf8
00034 #include "crypt.h"              // qq_crypt
00035 #include "header_info.h"        // cmd alias
00036 #include "keep_alive.h"         // qq_refresh_all_buddy_status
00037 #include "send_core.h"          // qq_send_cmd
00038 #include "qq.h"                 // qq_data
00039 
00040 #define QQ_GET_ONLINE_BUDDY_02          0x02
00041 #define QQ_GET_ONLINE_BUDDY_03          0x03    // unknown function
00042 
00043 #define QQ_ONLINE_BUDDY_ENTRY_LEN       38
00044 
00045 typedef struct _qq_friends_online_entry {
00046         qq_buddy_status *s;
00047         guint16 unknown1;
00048         guint8 flag1;
00049         guint8 comm_flag;
00050         guint16 unknown2;
00051         guint8 ending;          //0x00
00052 } qq_friends_online_entry;
00053 
00054 extern void                     // defined in qq_buddy_status.c
00055  _qq_buddy_status_dump_unclear(qq_buddy_status * s);
00056 
00057 extern gint                     // defined in qq_buddy_status.c
00058  _qq_buddy_status_read(guint8 * data, guint8 ** cursor, gint len, qq_buddy_status * s);
00059 
00060 /*****************************************************************************/
00061 // get a list of online_buddies
00062 void qq_send_packet_get_buddies_online(GaimConnection * gc, guint8 position)
00063 {
00064         qq_data *qd;
00065         guint8 *raw_data, *cursor;
00066 
00067         g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00068 
00069         qd = (qq_data *) gc->proto_data;
00070         raw_data = g_newa(guint8, 5);
00071         cursor = raw_data;
00072 
00073         // 000-000 get online friends cmd
00074         // only 0x02 and 0x03 returns info from server, other valuse all return 0xff
00075         // I can also only send the first byte (0x02, or 0x03)
00076         // and the result is the same
00077         create_packet_b(raw_data, &cursor, QQ_GET_ONLINE_BUDDY_02);
00078         // 001-001 seems it supports 255 online buddies at most
00079         create_packet_b(raw_data, &cursor, position);
00080         // 002-002
00081         create_packet_b(raw_data, &cursor, 0x00);
00082         // 003-004
00083         create_packet_w(raw_data, &cursor, 0x0000);
00084 
00085         qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_ONLINE, TRUE, 0, TRUE, raw_data, 5);
00086         qd->last_get_online = time(NULL);
00087 
00088 }                               // qq_send_packet_get_buddies_online
00089 
00090 /*****************************************************************************/
00091 // position starts with 0x0000, 
00092 // server may return a position tag if list is too long for one packet
00093 void qq_send_packet_get_buddies_list(GaimConnection * gc, guint16 position)
00094 {
00095         guint8 *raw_data, *cursor;
00096         gint data_len;
00097 
00098         g_return_if_fail(gc != NULL);
00099 
00100         data_len = 3;
00101         raw_data = g_newa(guint8, data_len);
00102         cursor = raw_data;
00103         // 000-001 starting position, can manually specify
00104         create_packet_w(raw_data, &cursor, position);
00105         // before Mar 18, 2004, any value can work, and we sent 00
00106         // I do not know what data QQ server is expecting, as QQ2003iii 0304 itself
00107         // even can sending packets 00 and get no response.
00108         // Now I tested that 00,00,00,00,00,01 work perfectly
00109         // March 22, fount the 00,00,00 starts to work as well
00110         create_packet_b(raw_data, &cursor, 0x00);
00111 
00112         qq_send_cmd(gc, QQ_CMD_GET_FRIENDS_LIST, TRUE, 0, TRUE, raw_data, data_len);
00113 
00114 }                               // qq_send_packet_get_buddies_list
00115 
00116 /*****************************************************************************/
00117 void _qq_buddies_online_reply_dump_unclear(qq_friends_online_entry * fe)
00118 {
00119         GString *dump;
00120 
00121         g_return_if_fail(fe != NULL);
00122 
00123         _qq_buddy_status_dump_unclear(fe->s);
00124 
00125         dump = g_string_new("");
00126         g_string_append_printf(dump, "Unclear fields for [%d]:\n", fe->s->uid);
00127         g_string_append_printf(dump, "031-032: %04x (unknown)\n", fe->unknown1);
00128         g_string_append_printf(dump, "033:     %02x   (flag1)\n", fe->flag1);
00129         g_string_append_printf(dump, "034:     %02x   (comm_flag)\n", fe->comm_flag);
00130         g_string_append_printf(dump, "035-036: %04x (unknown)\n", fe->unknown2);
00131 
00132         gaim_debug(GAIM_DEBUG_INFO, "QQ", "Online buddy entry, %s", dump->str);
00133         g_string_free(dump, TRUE);
00134 }                               // _qq_buddies_online_reply_dump_unknown
00135 
00136 /*****************************************************************************/
00137 // process the reply packet for get_buddies_online packet
00138 void qq_process_get_buddies_online_reply(guint8 * buf, gint buf_len, GaimConnection * gc) {
00139 
00140         qq_data *qd;
00141         gint len, bytes;
00142         guint8 *data, *cursor, position;
00143         GaimBuddy *b;
00144         qq_buddy *q_bud;
00145         qq_friends_online_entry *fe;
00146 
00147         g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00148         g_return_if_fail(buf != NULL && buf_len != 0);
00149 
00150         qd = (qq_data *) gc->proto_data;
00151         len = buf_len;
00152         data = g_newa(guint8, len);
00153         cursor = data;
00154 
00155         if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
00156 
00157                 read_packet_b(data, &cursor, len, &position);
00158                 fe = g_newa(qq_friends_online_entry, 1);
00159                 fe->s = g_newa(qq_buddy_status, 1);
00160 
00161                 while (cursor < (data + len)) {
00162                         // based on one online buddy entry
00163                         bytes = 0;
00164                         // 000-030 qq_buddy_status
00165                         bytes += _qq_buddy_status_read(data, &cursor, len, fe->s);
00166                         // 031-032: unknown4
00167                         bytes += read_packet_w(data, &cursor, len, &fe->unknown1);
00168                         // 033-033: flag1
00169                         bytes += read_packet_b(data, &cursor, len, &fe->flag1);
00170                         // 034-034: comm_flag
00171                         bytes += read_packet_b(data, &cursor, len, &fe->comm_flag);
00172                         // 035-036:
00173                         bytes += read_packet_w(data, &cursor, len, &fe->unknown2);
00174                         // 037-037:
00175                         bytes += read_packet_b(data, &cursor, len, &fe->ending);        // 0x00
00176 
00177                         if (fe->s->uid == 0 || bytes != QQ_ONLINE_BUDDY_ENTRY_LEN) {
00178                                 g_free(fe->s->ip);
00179                                 g_free(fe->s->unknown_key);
00180                                 continue;
00181                         }       // check if it is a valid entry
00182 
00183                         if (QQ_DEBUG)
00184                                 _qq_buddies_online_reply_dump_unclear(fe);
00185 
00186                         // update buddy information
00187                         b = gaim_find_buddy(gaim_connection_get_account(gc), uid_to_gaim_name(fe->s->uid));
00188                         q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
00189 
00190                         if (q_bud != NULL) {    // we find one and update qq_buddy
00191                                 g_memmove(q_bud->ip, fe->s->ip, 4);
00192                                 q_bud->port = fe->s->port;
00193                                 q_bud->status = fe->s->status;
00194                                 q_bud->flag1 = fe->flag1;
00195                                 q_bud->comm_flag = fe->comm_flag;
00196                                 qq_update_buddy_contact(gc, q_bud);
00197                         }       // if q_bud
00198 
00199                         g_free(fe->s->ip);
00200                         g_free(fe->s->unknown_key);
00201                 }               // while cursor
00202 
00203                 if (position != QQ_FRIENDS_ONLINE_POSITION_END)
00204                         qq_send_packet_get_buddies_online(gc, position);
00205                 else
00206                         qq_refresh_all_buddy_status(gc);
00207 
00208         } else
00209                 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt buddies online");
00210 
00211 }                               // qq_process_get_buddies_online_reply
00212 
00213 /*****************************************************************************/
00214 // process reply for get_buddies_list
00215 void qq_process_get_buddies_list_reply(guint8 * buf, gint buf_len, GaimConnection * gc) {
00216         qq_data *qd;
00217         qq_buddy *q_bud;
00218         gint len, bytes, bytes_expected, i;
00219         guint16 position, unknown;
00220         guint8 *data, *cursor, bar, pascal_len;
00221         gchar *name;
00222         GaimBuddy *b;
00223 
00224         g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00225         g_return_if_fail(buf != NULL && buf_len != 0);
00226 
00227         qd = (qq_data *) gc->proto_data;
00228         len = buf_len;
00229         data = g_newa(guint8, len);
00230         cursor = data;
00231 
00232         if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
00233                 read_packet_w(data, &cursor, len, &position);
00234                 // the following data is buddy list in this packet
00235                 i = 0;
00236                 while (cursor < (data + len)) {
00237                         q_bud = g_new0(qq_buddy, 1);
00238                         bytes = 0;
00239                         // 000-003: uid
00240                         bytes += read_packet_dw(data, &cursor, len, &q_bud->uid);
00241                         // 004-004: 0xff if buddy is self, 0x00 otherwise
00242                         bytes += read_packet_b(data, &cursor, len, &bar);
00243                         // 005-005: icon index (1-255)
00244                         bytes += read_packet_b(data, &cursor, len, &q_bud->icon);
00245                         // 006-006: age
00246                         bytes += read_packet_b(data, &cursor, len, &q_bud->age);
00247                         // 007-007: gender
00248                         bytes += read_packet_b(data, &cursor, len, &q_bud->gender);
00249                         pascal_len = convert_as_pascal_string(cursor, &q_bud->nickname, QQ_CHARSET_DEFAULT);
00250                         cursor += pascal_len;
00251                         bytes += pascal_len;
00252                         bytes += read_packet_w(data, &cursor, len, &unknown);
00253                         /* flag1: (0-7)
00254                          *        bit1 => qq show
00255                          * comm_flag: (0-7)
00256                          *        bit1 => member
00257                          *        bit4 => TCP mode
00258                          *        bit5 => open mobile QQ
00259                          *        bit6 => bind to mobile
00260                          *        bit7 => whether having a video
00261                          */
00262                         bytes += read_packet_b(data, &cursor, len, &q_bud->flag1);
00263                         bytes += read_packet_b(data, &cursor, len, &q_bud->comm_flag);
00264 
00265                         bytes_expected = 12 + pascal_len;
00266 
00267                         if (q_bud->uid == 0 || bytes != bytes_expected) {
00268                                 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00269                                            "Buddy entry, expect %d bytes, read %d bytes\n", bytes_expected, bytes);
00270                                 g_free(q_bud->nickname);
00271                                 g_free(q_bud);
00272                                 continue;
00273                         } else
00274                                 i++;
00275 
00276                         if (QQ_DEBUG)
00277                                 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00278                                            "buddy [%09d]: flag1=0x%02x, comm_flag=0x%02x\n",
00279                                            q_bud->uid, q_bud->flag1, q_bud->comm_flag);
00280 
00281                         name = uid_to_gaim_name(q_bud->uid);
00282                         b = gaim_find_buddy(gc->account, name);
00283                         g_free(name);
00284 
00285                         if (b == NULL)
00286                                 b = qq_add_buddy_by_recv_packet(gc, q_bud->uid, TRUE, FALSE);
00287 
00288                         b->proto_data = q_bud;
00289                         qd->buddies = g_list_append(qd->buddies, q_bud);
00290                         qq_update_buddy_contact(gc, q_bud);
00291                 }               // while cursor
00292 
00293                 if (position == QQ_FRIENDS_LIST_POSITION_END) {
00294                         gaim_debug(GAIM_DEBUG_INFO, "QQ", "Get friends list done, %d buddies\n", i);
00295                         qq_send_packet_get_buddies_online(gc, QQ_FRIENDS_ONLINE_POSITION_START);
00296                 } else
00297                         qq_send_packet_get_buddies_list(gc, position);
00298 
00299         } else
00300                 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt buddies list");
00301 
00302 }                               // qq_process_get_buddies_list_reply
00303 
00304 /*****************************************************************************/
00305 // END OF FILE

Generated at Mon May 8 15:41:23 2006 for OpenQ by  doxygen 1.4.4