Mercurial > pidgin
view src/protocols/qq/buddy_status.c @ 13910:6c907830a45f
[gaim-migrate @ 16408]
Get rid of an assertion failure that I hit
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 03 Jul 2006 01:39:51 +0000 |
parents | 2be9dfa9569b |
children | 16102b9c5c4a |
line wrap: on
line source
/** * The QQ2003C protocol plugin * * for gaim * * Copyright (C) 2004 Puzzlebird * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // START OF FILE /*****************************************************************************/ #include <string.h> // g_memmove #include "debug.h" // gaim_debug #include "prefs.h" // gaim_prefs_get_bool #include "utils.h" // get_ip_str #include "packet_parse.h" // create_packet, #include "buddy_status.h" #include "crypt.h" // qq_crypt.h #include "header_info.h" // cmd alias #include "keep_alive.h" // qq_update_buddy_contact #include "send_core.h" // qq_send_cmd #define QQ_MISC_STATUS_HAVING_VIIDEO 0x00000001 #define QQ_ICON_SUFFIX_DEFAULT QQ_ICON_SUFFIX_OFFLINE #define QQ_CHANGE_ONLINE_STATUS_REPLY_OK 0x30 // ASCii value of "0" enum { QQ_ICON_SUFFIX_NORMAL = 1, QQ_ICON_SUFFIX_OFFLINE = 2, QQ_ICON_SUFFIX_AWAY = 3, }; /*****************************************************************************/ static void _qq_buddy_status_dump_unclear(qq_buddy_status * s) { GString *dump; g_return_if_fail(s != NULL); dump = g_string_new(""); g_string_append_printf(dump, "unclear fields for [%d]:\n", s->uid); g_string_append_printf(dump, "004: %02x (unknown)\n", s->unknown1); g_string_append_printf(dump, "011: %02x (unknown)\n", s->unknown2); gaim_debug(GAIM_DEBUG_INFO, "QQ", "Buddy status entry, %s", dump->str); g_string_free(dump, TRUE); } // _qq_buddy_status_dump_unclear /*****************************************************************************/ // parse the data into qq_buddy_status gint _qq_buddy_status_read(guint8 * data, guint8 ** cursor, gint len, qq_buddy_status * s) { gint bytes; g_return_val_if_fail(data != NULL && *cursor != NULL && s != NULL, -1); bytes = 0; // 000-003: uid bytes += read_packet_dw(data, cursor, len, &s->uid); // 004-004: 0x01 bytes += read_packet_b(data, cursor, len, &s->unknown1); // 005-008: ip s->ip = g_new0(guint8, 4); bytes += read_packet_data(data, cursor, len, s->ip, 4); // 009-010: port bytes += read_packet_w(data, cursor, len, &s->port); // 011-011: 0x00 bytes += read_packet_b(data, cursor, len, &s->unknown2); // 012-012: status bytes += read_packet_b(data, cursor, len, &s->status); // 013-014: client_version bytes += read_packet_w(data, cursor, len, &s->client_version); // 015-030: unknown key s->unknown_key = g_new0(guint8, QQ_KEY_LENGTH); bytes += read_packet_data(data, cursor, len, s->unknown_key, QQ_KEY_LENGTH); if (s->uid == 0 || bytes != 31) return -1; return bytes; } // _qq_buddy_status_read /*****************************************************************************/ // check if status means online or offline gboolean is_online(guint8 status) { // return (status == QQ_BUDDY_ONLINE_NORMAL ? TRUE : (status == QQ_BUDDY_ONLINE_AWAY ? TRUE : FALSE)); //rewritten by gfhuang switch(status) { case QQ_BUDDY_ONLINE_NORMAL: case QQ_BUDDY_ONLINE_AWAY: case QQ_BUDDY_ONLINE_INVISIBLE: return TRUE; case QQ_BUDDY_ONLINE_OFFLINE: return FALSE; } return FALSE; } // is_online /*****************************************************************************/ // the icon suffix is detemined by status // although QQ server may return the right icon, I set it here myself gchar get_suffix_from_status(guint8 status) { switch (status) { case QQ_BUDDY_ONLINE_NORMAL: return QQ_ICON_SUFFIX_NORMAL; case QQ_BUDDY_ONLINE_AWAY: return QQ_ICON_SUFFIX_AWAY; case QQ_BUDDY_ONLINE_INVISIBLE: case QQ_BUDDY_ONLINE_OFFLINE: return QQ_ICON_SUFFIX_OFFLINE; default: return QQ_ICON_SUFFIX_DEFAULT; } // switch } // get_suffix_from_status /*****************************************************************************/ // send a packet to change my online status void qq_send_packet_change_status(GaimConnection * gc) { qq_data *qd; guint8 *raw_data, *cursor, away_cmd; guint32 misc_status; gboolean fake_video; g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; if (!qd->logged_in) return; switch (qd->status) { case QQ_SELF_STATUS_AVAILABLE: away_cmd = QQ_BUDDY_ONLINE_NORMAL; break; case QQ_SELF_STATUS_INVISIBLE: away_cmd = QQ_BUDDY_ONLINE_INVISIBLE; break; case QQ_SELF_STATUS_AWAY: case QQ_SELF_STATUS_IDLE: case QQ_SELF_STATUS_CUSTOM: away_cmd = QQ_BUDDY_ONLINE_AWAY; break; default: away_cmd = QQ_BUDDY_ONLINE_NORMAL; } // switch raw_data = g_new0(guint8, 5); cursor = raw_data; misc_status = 0x00000000; fake_video = gaim_prefs_get_bool("/plugins/prpl/qq/show_fake_video"); if (fake_video) misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO; create_packet_b(raw_data, &cursor, away_cmd); create_packet_dw(raw_data, &cursor, misc_status); qq_send_cmd(gc, QQ_CMD_CHANGE_ONLINE_STATUS, TRUE, 0, TRUE, raw_data, 5); g_free(raw_data); } // qq_send_packet_change_status /*****************************************************************************/ // parse the reply packet for change_status void qq_process_change_status_reply(guint8 * buf, gint buf_len, GaimConnection * gc) { qq_data *qd; gint len; guint8 *data, *cursor, reply; g_return_if_fail(gc != NULL && gc->proto_data != NULL); g_return_if_fail(buf != NULL && buf_len != 0); qd = (qq_data *) gc->proto_data; len = buf_len; data = g_newa(guint8, len); if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { cursor = data; read_packet_b(data, &cursor, len, &reply); if (reply != QQ_CHANGE_ONLINE_STATUS_REPLY_OK) { gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Change status fail\n"); } else gaim_debug(GAIM_DEBUG_INFO, "QQ", "Change status OK\n"); } else gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt chg status reply\n"); } // qq_process_change_status_reply /*****************************************************************************/ // it is a server message // indicating that one of my buddies changes its status void qq_process_friend_change_status(guint8 * buf, gint buf_len, GaimConnection * gc) { qq_data *qd; gint len, bytes; guint32 my_uid; guint8 *data, *cursor; GaimBuddy *b; qq_buddy *q_bud; qq_buddy_status *s; gchar *name; g_return_if_fail(gc != NULL && gc->proto_data != NULL); g_return_if_fail(buf != NULL && buf_len != 0); qd = (qq_data *) gc->proto_data; len = buf_len; data = g_newa(guint8, len); cursor = data; if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { s = g_new0(qq_buddy_status, 1); bytes = 0; // 000-030: qq_buddy_status; bytes += _qq_buddy_status_read(data, &cursor, len, s); // 031-034: my uid bytes += read_packet_dw(data, &cursor, len, &my_uid); if (my_uid == 0 || bytes != 35) { gaim_debug(GAIM_DEBUG_ERROR, "QQ", "my_uid == 0 || bytes(%d) != 35\n", bytes); g_free(s->ip); g_free(s->unknown_key); g_free(s); return; } // if (QQ_DEBUG) gfhuang // _qq_buddy_status_dump_unclear(s); name = uid_to_gaim_name(s->uid); //by gfhuang b = gaim_find_buddy(gc->account, name); g_free(name); q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; if (q_bud) { gaim_debug(GAIM_DEBUG_INFO, "QQ", "s->uid = %d, q_bud->uid = %d\n", s->uid , q_bud->uid); if(0 != *((guint32 *)s->ip)) { //by gfhuang g_memmove(q_bud->ip, s->ip, 4); q_bud->port = s->port; } q_bud->status = s->status; if(0 != s->client_version) q_bud->client_version = s->client_version; //gfhuang qq_update_buddy_contact(gc, q_bud); } else gaim_debug(GAIM_DEBUG_ERROR, "QQ", "got information of unknown buddy by gfhuang %d\n", s->uid); g_free(s->ip); g_free(s->unknown_key); g_free(s); } else gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt buddy status change packet\n"); } // qq_process_friend_change_status /*****************************************************************************/ // END OF FILE