Mercurial > pidgin
diff src/protocols/qq/buddy_info.c @ 13989:16102b9c5c4a
[gaim-migrate @ 16562]
*Eliminated all Gtk-related code from the prpl. Notably, this included the group ("Qun") administrative dialog and a dialog for setting and viewing personal information. Code for the latter now uses the gaim UI, while the former is currently disabled.
*Disabled a few non-functional/non-essential menu actions. These included: IP lookup, system logging, about dialog, and qq_buddy_menu.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Huetsch <markhuetsch> |
---|---|
date | Mon, 24 Jul 2006 13:39:12 +0000 |
parents | 983fd420e86b |
children | e6977f9435a1 |
line wrap: on
line diff
--- a/src/protocols/qq/buddy_info.c Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/buddy_info.c Mon Jul 24 13:39:12 2006 +0000 @@ -20,11 +20,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// START OF FILE -/*****************************************************************************/ #include "internal.h" // strlen, _("get_text) #include "debug.h" // gaim_debug #include "notify.h" // gaim_notify +#include "request.h" // gaim_request_fields_new #include "utils.h" // uid_to_gaim_name #include "packet_parse.h" // MAX_PACKET_SIZE @@ -32,68 +31,295 @@ #include "char_conv.h" // qq_to_utf8 #include "crypt.h" // qq_crypt #include "header_info.h" // cmd alias -#include "infodlg.h" // info_window #include "keep_alive.h" // qq_update_buddy_contact #include "send_core.h" // qq_send_cmd -// amount of fiedls in user info -#define QQ_CONTACT_FIELDS 37 +// Below is all of the information necessary to reconstruct the various +// information fields that one can set in the official client. When we need +// to know about a specific field (e.g., should "city" be a choice +// or text field?), we can simply look it up from the template. Note that +// there are a number of unidentified fields. + +typedef struct _info_field { + gchar *title; + gchar *id; // used by gaim_request fields + gint pos; + gchar *group; + gint group_pos; // for display order in the UI + gint choice; // indicates which character array contains the choices + gboolean customizable; // whether a user can enter any text as a value, regardless of choice arrays + gchar *value; +} info_field; + +static const info_field info_template_data[] = { + { N_("User ID"), "uid", 0, QQ_MAIN_INFO, 0, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Nickname"), "nick", 1, QQ_MAIN_INFO, 1, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Country/Region"), "country", 2, QQ_MAIN_INFO, 5, QQ_COUNTRY, TRUE, NULL }, + { N_("Province/State"), "province", 3, QQ_MAIN_INFO, 6, QQ_PROVINCE, TRUE, NULL }, + { N_("Zipcode"), "zipcode", 4, QQ_EXTRA_INFO, 7, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Address"), "address", 5, QQ_EXTRA_INFO, 6, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Phone Number"), "tel", 6, QQ_EXTRA_INFO, 9, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Age"), "age", 7, QQ_MAIN_INFO, 3, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Gender"), "gender", 8, QQ_MAIN_INFO, 4, QQ_GENDER, FALSE, NULL }, + { N_("Name"), "name", 9, QQ_MAIN_INFO, 2, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Email"), "email", 10, QQ_EXTRA_INFO, 5, QQ_NO_CHOICE, TRUE, NULL }, + { "pager_sn", "pager_sn", 11, QQ_MISC, 0, QQ_NO_CHOICE, TRUE, NULL }, + { "pager_num", "pager_num", 12, QQ_MISC, 1, QQ_NO_CHOICE, TRUE, NULL }, + { "pager_sp", "pager_sp", 13, QQ_MISC, 2, QQ_NO_CHOICE, TRUE, NULL }, + { "pager_base_num", "pager_base_num", 14, QQ_MISC, 3, QQ_NO_CHOICE, TRUE, NULL }, + { "pager_type", "pager_type", 15, QQ_MISC, 4, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Occupation"), "occupation", 16, QQ_EXTRA_INFO, 1, QQ_OCCUPATION, TRUE, NULL }, + { N_("Homepage"), "homepage", 17, QQ_EXTRA_INFO, 10, QQ_NO_CHOICE, TRUE, NULL }, + { "auth_type", "auth_type", 18, QQ_MISC, 5, QQ_NO_CHOICE, TRUE, NULL }, + { "unknown1", "unknown1", 19, QQ_MISC, 6, QQ_NO_CHOICE, TRUE, NULL }, + { "unknown2", "unknown2", 20, QQ_MISC, 7, QQ_NO_CHOICE, TRUE, NULL }, + { "face", "face", 21, QQ_MISC, 8, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Cellphone Number"), "hp_num", 22, QQ_EXTRA_INFO, 8, QQ_NO_CHOICE, TRUE, NULL }, + { "hp_type", "hp_type", 23, QQ_MISC, 9, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Personal Introduction"), "intro", 24, QQ_PERSONAL_INTRO, 0, QQ_NO_CHOICE, TRUE, NULL }, + { N_("City"), "city", 25, QQ_MAIN_INFO, 7, QQ_NO_CHOICE, TRUE, NULL }, + { "unknown3", "unknown3", 26, QQ_MISC, 10, QQ_NO_CHOICE, TRUE, NULL }, + { "unknown4", "unknown4", 27, QQ_MISC, 11, QQ_NO_CHOICE, TRUE, NULL }, + { "unknown5", "unknown5", 28, QQ_MISC, 12, QQ_NO_CHOICE, TRUE, NULL }, + { "is_open_hp", "is_open_hp", 29, QQ_MISC, 13, QQ_NO_CHOICE, TRUE, NULL }, + { "is_open_contact", "is_open_contact", 30, QQ_MISC, 14, QQ_NO_CHOICE, TRUE, NULL }, + { N_("College"), "college", 31, QQ_EXTRA_INFO, 4, QQ_NO_CHOICE, TRUE, NULL }, + { N_("Horoscope Symbol"), "horoscope", 32, QQ_EXTRA_INFO, 0, QQ_HOROSCOPE, FALSE, NULL }, + { N_("Zodiac Symbol"), "zodiac", 33, QQ_EXTRA_INFO, 2, QQ_ZODIAC, FALSE, NULL }, + { N_("Blood Type"), "blood", 34, QQ_EXTRA_INFO, 3, QQ_BLOOD, FALSE, NULL }, + { "qq_show", "qq_show", 35, QQ_MISC, 15, QQ_NO_CHOICE, TRUE, NULL }, + { "unknown6", "unknown6", 36, QQ_MISC, 16, QQ_NO_CHOICE, TRUE, NULL }, + { NULL, NULL, 0, NULL, 0, 0, 0, NULL } //NULL termination +}; + +//TODO: translate these arrays to their English equivalents +// and move these characters to the zh_CN po file +static const gchar *horoscope_names[] = { + "-", "水瓶座", "双鱼座", "牡羊座", "金牛座", + "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", + "天蝎座", "射手座", "魔羯座", NULL +}; + +static const gchar *zodiac_names[] = { + "-", "鼠", "牛", "虎", "兔", + "龙", "蛇", "马", "羊", "猴", + "鸡", "狗", "猪", NULL +}; + +static const gchar *blood_types[] = { + "其它", "A型", "B型", "O型", "AB型", NULL +}; + +static const gchar *genders[] = { + N_("Male"), + N_("Female"), + NULL +}; + +static const gchar *country_names[] = { + "中国", "中国香港", "中国澳门", "中国台湾", + "新加坡", "马来西亚", "美国", NULL +}; + +static const gchar *province_names[] = { + "北京", "天津", "上海", "重庆", "香港", + "河北", "山西", "内蒙古", "辽宁", "吉林", + "黑龙江", "江西", "浙江", "江苏", "安徽", + "福建", "山东", "河南", "湖北", "湖南", + "广东", "广西", "海南", "四川", "贵州", + "云南", "西藏", "陕西", "甘肃", "宁夏", + "青海", "新疆", "台湾", "澳门", NULL +}; + +static const gchar *occupation_names[] = { + "全职", "兼职", "制造业", "商业", "失业中", + "学生", "工程师", "政府部门", "教育业", "服务行业", + "老板", "计算机业", "退休", "金融业", + "销售/广告/市场", NULL +}; + +static const gint choice_sizes[] = { 0, 13, 13, 5, 2, 7, 34, 15 }; + + +static const gchar *info_group_headers[] = { + QQ_MAIN_INFO, + QQ_EXTRA_INFO, + QQ_PERSONAL_INTRO, + QQ_MISC +}; -// There is no user id stored in the reply packet for information query -// we have to manually store the query, so that we know the query source -typedef struct _qq_info_query { - guint32 uid; - gboolean show_window; - contact_info *ret_info; -} qq_info_query; +static const gchar **choices[] = { + NULL, + horoscope_names, + zodiac_names, + blood_types, + genders, + country_names, + province_names, + occupation_names +}; + +/*************** info and info_field methods *****************/ + +// Given an id, return the template for that field. +// Returns NULL if the id is not found. +static const info_field *info_field_get_template(const gchar *id) +{ + const info_field *cur_field; + const gchar *cur_id; + + cur_field = info_template_data; + cur_id = cur_field->id; + while(cur_id != NULL) { + if (g_ascii_strcasecmp(cur_id, id) == 0) return cur_field; + cur_field++; + cur_id = cur_field->id; + } + gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Info field with id %s not found!", id); + return NULL; +} + +// info_fields are compared by their group positions +static gint info_field_compare(gconstpointer a, gconstpointer b, gpointer unused) +{ + return ((info_field *) a)->group_pos - ((info_field *) b)->group_pos; +} + +static void info_field_free(info_field *i) +{ + g_free(i->value); + g_free(i); +} + +// Parses the info_template_data above and returns a newly-allocated list +// containing the desired fields from segments. This list is ordered by +// group_pos. +static GList *info_get_group(const gchar **info, const gchar *group_name) +{ + const info_field *cur; + info_field *entry; + GList *group = NULL; + + cur = info_template_data; + while (cur->id != NULL) { + if (g_ascii_strcasecmp(group_name, cur->group) == 0) { + entry = g_memdup(cur, sizeof(info_field)); + entry->value = g_strdup(info[entry->pos]); + group = g_list_insert_sorted_with_data(group, entry, info_field_compare, NULL); + } + cur++; + } + + return group; +} -/*****************************************************************************/ -// send a packet to get detailed information of uid, -// if show_window, a info window will be display upon receiving a reply +// determines if the given text value and choice group require +// a lookup from the choice arrays +static gboolean is_valid_index(gchar *value, gint choice) +{ + gint len, i; + + if (choice == 0) return FALSE; + len = strlen(value); + // the server sends us an ascii index and none of arrays has more than 99 + // elements + if (len > 3 || len == 0) return FALSE; + for (i = 0; i < len; i++) + if (!g_ascii_isdigit(value[i])) return FALSE; + i = atoi(value); + if (i < 0 || i >= choice_sizes[choice]) return FALSE; + return TRUE; +} + +// formats a field for printing +static void append_field_to_str(gpointer field, gpointer str) +{ + info_field *f; + gint choice; + gboolean valid_index; + gchar *value; + + f = (info_field *) field; + choice = f->choice; + valid_index = is_valid_index(f->value, choice); + if (choice && valid_index) value = g_strdup(choices[choice][atoi(f->value)]); + else value = qq_to_utf8(f->value, QQ_CHARSET_DEFAULT); + g_string_append_printf((GString *) str, "<b>%s:</b> %s<br />", + f->title, value); + g_free(value); + info_field_free(f); +} + +// formats a group of information for printing +static void append_group_to_str(GString *str, const gchar *group_name, const gchar **info) +{ + GList *group; + + group = info_get_group(info, group_name); + g_string_append_printf(str, "<b>%s</b><br /><br />", (*(info_field *) group->data).group); + g_list_foreach(group, append_field_to_str, str); + g_list_free(group); + g_string_append_printf(str, "<br />"); +} + +// takes a contact_info struct and outputs the appropriate fields in +// a printable format for our upcoming call to gaim_notify_userinfo +static GString *info_to_str(const gchar **info) +{ + GString *info_text; + + info_text = g_string_new(""); + append_group_to_str(info_text, QQ_MAIN_INFO, info); + append_group_to_str(info_text, QQ_EXTRA_INFO, info); + append_group_to_str(info_text, QQ_PERSONAL_INTRO, info); + //if (QQ_DEBUG) append_group_to_str(info_text, QQ_MISC, info); + + return info_text; +} + +/*************** packets and UI management *****************/ + +// send a packet to get detailed information of uid void qq_send_packet_get_info(GaimConnection * gc, guint32 uid, gboolean show_window) { qq_data *qd; gchar *uid_str; - GList *list; qq_info_query *query; - gboolean is_exist; - contact_info_window *info_window; g_return_if_fail(gc != NULL && gc->proto_data != NULL && uid != 0); qd = (qq_data *) gc->proto_data; uid_str = g_strdup_printf("%d", uid); - qq_send_cmd(gc, QQ_CMD_GET_USER_INFO, TRUE, 0, TRUE, uid_str, strlen(uid_str)); - - if (show_window) { // prepare the window - is_exist = FALSE; // see if there is already a window for this uid - list = qd->contact_info_window; - while (list != NULL) { - info_window = (contact_info_window *) list->data; - if (uid == info_window->uid) { - is_exist = TRUE; - break; - } else - list = list->next; - } // while list - if (!is_exist) { // create a new one - info_window = g_new0(contact_info_window, 1); - info_window->uid = uid; - qd->contact_info_window = g_list_append(qd->contact_info_window, info_window); - } // if !is_exist - } // if show_window + qq_send_cmd(gc, QQ_CMD_GET_USER_INFO, TRUE, 0, TRUE, (guint8 *) uid_str, strlen(uid_str)); query = g_new0(qq_info_query, 1); query->uid = uid; query->show_window = show_window; + query->modify_info = FALSE; qd->info_query = g_list_append(qd->info_query, query); g_free(uid_str); -} // qq_send_packet_get_info +} + +// set up the fields requesting personal information and send a get_info packet +// for myself +void qq_prepare_modify_info(GaimConnection *gc) +{ + qq_data *qd; + GList *ql; + qq_info_query *query; -/*****************************************************************************/ + qd = (qq_data *) gc->proto_data; + qq_send_packet_get_info(gc, qd->uid, FALSE); + // traverse backwards so we get the most recent info_query + for (ql = g_list_last(qd->info_query); ql != NULL; ql = g_list_previous(ql)) { + query = ql->data; + if (query->uid == qd->uid) query->modify_info = TRUE; + } +} + // send packet to modify personal information, and/or change password -void qq_send_packet_modify_info(GaimConnection * gc, contact_info * info, gchar * new_passwd) +void qq_send_packet_modify_info(GaimConnection *gc, contact_info *info, gchar *new_passwd) { GaimAccount *a; gchar *old_passwd, *info_field[QQ_CONTACT_FIELDS]; @@ -112,26 +338,174 @@ if (new_passwd == NULL || strlen(new_passwd) == 0) create_packet_b(raw_data, &cursor, bar); - else { // we gonna change passwd - create_packet_data(raw_data, &cursor, old_passwd, strlen(old_passwd)); + else { // we're gonna change passwd + create_packet_data(raw_data, &cursor, (guint8 *) old_passwd, strlen(old_passwd)); create_packet_b(raw_data, &cursor, bar); - create_packet_data(raw_data, &cursor, new_passwd, strlen(new_passwd)); + create_packet_data(raw_data, &cursor, (guint8 *) new_passwd, strlen(new_passwd)); } // important!, skip the first uid entry for (i = 1; i < QQ_CONTACT_FIELDS; i++) { create_packet_b(raw_data, &cursor, bar); - create_packet_data(raw_data, &cursor, info_field[i], strlen(info_field[i])); + create_packet_data(raw_data, &cursor, (guint8 *) info_field[i], strlen(info_field[i])); } create_packet_b(raw_data, &cursor, bar); qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, TRUE, 0, TRUE, raw_data, cursor - raw_data); -} // qq_send_packet_modify_info +} + +static void modify_info_cancel_cb(modify_info_data *mid) +{ + g_list_free(mid->misc); + g_free(mid); +} + +// runs through all of the fields in the modify info UI and put +// their values into the outgoing packet +static void parse_field(gpointer field, gpointer outgoing_info) +{ + GaimRequestField *f; + gchar **segments, *value; + const info_field *ft; + const gchar *id; + + f = (GaimRequestField *) field; + segments = (gchar **) outgoing_info; + id = gaim_request_field_get_id(f); + ft = info_field_get_template(id); + if (ft->choice && !ft->customizable) + value = g_strdup_printf("%d", gaim_request_field_choice_get_value(f)); + else { + value = (gchar *) gaim_request_field_string_get_value(f); + if (value == NULL) value = g_strdup(""); + else value = utf8_to_qq(value, QQ_CHARSET_DEFAULT); + } + segments[ft->pos] = value; +} + +// dumps the uneditable information straight into the outgoing packet +static void parse_misc_field(gpointer field, gpointer outgoing_info) +{ + info_field *f; + gchar **segments; + + f = (info_field *) field; + segments = (gchar **) outgoing_info; + segments[f->pos] = g_strdup(f->value); + info_field_free(f); +} + +// runs through all of the information fields and copies them into an +// outgoing packet, then sends that packet +static void modify_info_ok_cb(modify_info_data *mid, GaimRequestFields *fields) +{ + GaimConnection *gc; + GList *list, *groups, *group_node; + gchar *info_field[QQ_CONTACT_FIELDS]; + contact_info *info; + gint i; + + gc = mid->gc; + list = mid->misc; + g_list_foreach(list, parse_misc_field, info_field); + g_list_free(list); + groups = gaim_request_fields_get_groups(fields); + while(groups) { + group_node = groups; + list = gaim_request_field_group_get_fields(group_node->data); + g_list_foreach(list, parse_field, info_field); + groups = g_list_remove_link(groups, group_node); + } + info = (contact_info *) info_field; + + qq_send_packet_modify_info(gc, info, NULL); + g_free(mid); + for (i = 0; i < QQ_CONTACT_FIELDS; i++) + g_free(info_field[i]); +} -/*****************************************************************************/ -// process the reply of modidy_info packet -void qq_process_modify_info_reply(guint8 * buf, gint buf_len, GaimConnection * gc) +// Sets up the display for one group of information. This includes +// managing which fields in the UI should be textfields and +// which choices, and also mapping ints to choice values when appropriate. +static void setup_group(gpointer field, gpointer group) +{ + info_field *f; + GaimRequestFieldGroup *g; + GaimRequestField *rf; + gint choice, index, j; + gboolean customizable, valid_index, multiline; + gchar *id, *value; + + f = (info_field *) field; + g = (GaimRequestFieldGroup *) group; + choice = f->choice; + customizable = f->customizable; + id = f->id; + valid_index = TRUE; + + if (!choice || customizable) { + valid_index = is_valid_index(f->value, choice); + multiline = id == "intro"; + if (valid_index) { + index = atoi(f->value); + value = (gchar *) choices[choice][index]; + } else value = qq_to_utf8(f->value, QQ_CHARSET_DEFAULT); + rf = gaim_request_field_string_new(id, f->title, value, multiline); + } else { + index = atoi(f->value); + value = (gchar *) choices[choice][index]; + rf = gaim_request_field_choice_new(id, f->title, index); + j = 0; + while(choices[choice][j] != NULL) + gaim_request_field_choice_add(rf, choices[choice][j++]); + } + gaim_request_field_group_add_field(g, rf); + if (!valid_index) g_free(value); + info_field_free(f); +} + +// Takes the info returned by a get_info packet for the user and sets up +// a form using those values and the info_template. +static void create_modify_info_dialogue(GaimConnection *gc, const gchar **info) +{ + GaimRequestFields *fields; + GaimRequestFieldGroup *group; + GaimRequestField *field; + GList *group_list; + modify_info_data *mid; + gint i; + + fields = gaim_request_fields_new(); + + // we only care about the first 3 groups, not the miscellaneous stuff + for (i = 0; i < 3; i++) { + group = gaim_request_field_group_new(info_group_headers[i]); + gaim_request_fields_add_group(fields, group); + group_list = info_get_group(info, info_group_headers[i]); + g_list_foreach(group_list, setup_group, group); + g_list_free(group_list); + } + + //set this manually here instead of generating a new template column + field = gaim_request_fields_get_field(fields, "uid"); + gaim_request_field_string_set_editable(field, FALSE); + + //we need to pass the info that doesn't get modified as aux data + //because we'll still need it when we send the modify_info packet + mid = g_new0(modify_info_data, 1); + mid->gc = gc; + mid->misc = info_get_group(info, info_group_headers[3]); + + gaim_request_fields(gc, _("Modify my information"), + _("Modify my information"), NULL, fields, + _("Update my information"), G_CALLBACK(modify_info_ok_cb), + _("Cancel"), G_CALLBACK(modify_info_cancel_cb), + mid); +} + +// process the reply of modify_info packet +void qq_process_modify_info_reply(guint8 *buf, gint buf_len, GaimConnection *gc) { qq_data *qd; gint len; @@ -145,18 +519,17 @@ data = g_newa(guint8, len); if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { - if (qd->uid == atoi(data)) { // return should be my uid + if (qd->uid == atoi((gchar *) data)) { // return should be my uid gaim_debug(GAIM_DEBUG_INFO, "QQ", "Update info ACK OK\n"); - gaim_notify_info(gc, NULL, _("You information have been updated"), NULL); + gaim_notify_info(gc, NULL, _("Your information has been updated"), NULL); } } else gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt modify info reply\n"); -} // qq_process_modify_info_reply +} -/*****************************************************************************/ // after getting info or modify myself, refresh the buddy list accordingly -void qq_refresh_buddy_and_myself(contact_info * info, GaimConnection * gc) +void qq_refresh_buddy_and_myself(contact_info *info, GaimConnection *gc) { GaimBuddy *b; qq_data *qd; @@ -182,13 +555,16 @@ if (alias_utf8 != NULL) q_bud->nickname = g_strdup(alias_utf8); qq_update_buddy_contact(gc, q_bud); - } // if q_bud + } g_free(alias_utf8); -} // qq_refresh_buddy_and_myself +} -/*****************************************************************************/ +// XXX When we don't have any immediate response, we send duplicate get info packets +// to the server. If the server ends up responding to multiple packets, we get multiple +// modify info dialogues, which is annoying. Fix this. + // process reply to get_info packet -void qq_process_get_info_reply(guint8 * buf, gint buf_len, GaimConnection * gc) +void qq_process_get_info_reply(guint8 *buf, gint buf_len, GaimConnection *gc) { gint len; guint8 *data; @@ -196,9 +572,8 @@ qq_info_query *query; qq_data *qd; contact_info *info; - contact_info_window *info_window; - gboolean show_window; GList *list, *query_list; + GString *info_text; g_return_if_fail(gc != NULL && gc->proto_data != NULL); g_return_if_fail(buf != NULL && buf_len != 0); @@ -217,42 +592,30 @@ qq_refresh_buddy_and_myself(info, gc); query_list = qd->info_query; - show_window = FALSE; - while (query_list != NULL) { + // ensure we're processing the right query + while (query_list) { query = (qq_info_query *) query_list->data; if (query->uid == atoi(info->uid)) { - show_window = query->show_window; + if (query->show_window) { + info_text = info_to_str((const gchar **) segments); + gaim_notify_userinfo(gc, info->uid, info_text->str, NULL, NULL); + g_string_free(info_text, TRUE); + } else if (query->modify_info) { + create_modify_info_dialogue(gc, (const gchar **) segments); + } qd->info_query = g_list_remove(qd->info_query, qd->info_query->data); g_free(query); break; } query_list = query_list->next; - } // while query_list + } - if (!show_window) { - g_strfreev(segments); - return; - } - // if not show_window, we can not find the window here either - list = qd->contact_info_window; - while (list != NULL) { - info_window = (contact_info_window *) (list->data); - if (info_window->uid == atoi(info->uid)) { - if (info_window->window) - qq_refresh_contact_info_dialog(info, gc, info_window); - else - qq_show_contact_info_dialog(info, gc, info_window); - break; - } else - list = list->next; - } // while list g_strfreev(segments); } else gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt get info reply\n"); -} // qq_process_get_info_reply +} -/*****************************************************************************/ void qq_info_query_free(qq_data * qd) { gint i; @@ -268,7 +631,4 @@ i++; } gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d info queries are freed!\n", i); -} // qq_add_buddy_request_free - -/*****************************************************************************/ -// END OF FILE +}