📄 buddy_info.c
字号:
/** * @file buddy_info.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "internal.h"#include "debug.h"#include "notify.h"#include "request.h"#include "utils.h"#include "packet_parse.h"#include "buddy_info.h"#include "char_conv.h"#include "crypt.h"#include "header_info.h"#include "keep_alive.h"#include "send_core.h"#define QQ_PRIMARY_INFORMATION _("Primary Information")#define QQ_ADDITIONAL_INFORMATION _("Additional Information")#define QQ_INTRO _("Personal Introduction")#define QQ_NUMBER _("QQ Number")#define QQ_NICKNAME _("Nickname")#define QQ_NAME _("Name")#define QQ_AGE _("Age")#define QQ_GENDER _("Gender")#define QQ_COUNTRY _("Country/Region")#define QQ_PROVINCE _("Province/State")#define QQ_CITY _("City")#define QQ_HOROSCOPE _("Horoscope Symbol")#define QQ_OCCUPATION _("Occupation")#define QQ_ZODIAC _("Zodiac Sign")#define QQ_BLOOD _("Blood Type")#define QQ_COLLEGE _("College")#define QQ_EMAIL _("Email")#define QQ_ADDRESS _("Address")#define QQ_ZIPCODE _("Zipcode")#define QQ_CELL _("Cellphone Number")#define QQ_TELEPHONE _("Phone Number")#define QQ_HOMEPAGE _("Homepage")#define QQ_HOROSCOPE_SIZE 13static const gchar *horoscope_names[] = { "-", N_("Aquarius"), N_("Pisces"), N_("Aries"), N_("Taurus"), N_("Gemini"), N_("Cancer"), N_("Leo"), N_("Virgo"), N_("Libra"), N_("Scorpio"), N_("Sagittarius"), N_("Capricorn")};#define QQ_ZODIAC_SIZE 13static const gchar *zodiac_names[] = { "-", N_("Rat"), N_("Ox"), N_("Tiger"), N_("Rabbit"), N_("Dragon"), N_("Snake"), N_("Horse"), N_("Goat"), N_("Monkey"), N_("Rooster"), N_("Dog"), N_("Pig")};#define QQ_BLOOD_SIZE 6static const gchar *blood_types[] = { "-", "A", "B", "O", "AB", N_("Other")};#define QQ_GENDER_SIZE 2static const gchar *genders[] = { N_("Male"), N_("Female")};#define QQ_CONTACT_FIELDS 37/* 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; gboolean modify_info;} qq_info_query;/* We get an info packet on ourselves before we modify our information. * Even though not all of the information is modifiable, it still * all needs to be there when we send out the modify info packet */typedef struct _modify_info_data { PurpleConnection *gc; contact_info *info;} modify_info_data;/* return -1 as a sentinel */static gint choice_index(const gchar *value, const gchar **choice, gint choice_size){ gint len, i; len = strlen(value); if (len > 3 || len == 0) return -1; for (i = 0; i < len; i++) { if (!g_ascii_isdigit(value[i])) return -1; } i = strtol(value, NULL, 10); if (i >= choice_size) return -1; return i;}/* return should be freed */static gchar *field_value(const gchar *field, const gchar **choice, gint choice_size){ gint index, len; len = strlen(field); if (len == 0) { return NULL; } else if (choice != NULL) { /* some choice fields are also customizable */ index = choice_index(field, choice, choice_size); if (index == -1) { if (strcmp(field, "-") != 0) { return qq_to_utf8(field, QQ_CHARSET_DEFAULT); } else { return NULL; } /* else ASCIIized index */ } else { if (strcmp(choice[index], "-") != 0) return g_strdup(choice[index]); else return NULL; } } else { if (strcmp(field, "-") != 0) { return qq_to_utf8(field, QQ_CHARSET_DEFAULT); } else { return NULL; } }}static gboolean append_field_value(PurpleNotifyUserInfo *user_info, const gchar *field, const gchar *title, const gchar **choice, gint choice_size){ gchar *value = field_value(field, choice, choice_size); if (value != NULL) { purple_notify_user_info_add_pair(user_info, title, value); g_free(value); return TRUE; } return FALSE;}static PurpleNotifyUserInfo *info_to_notify_user_info(const contact_info *info){ PurpleNotifyUserInfo *user_info = purple_notify_user_info_new(); const gchar *intro; gboolean has_extra_info = FALSE; purple_notify_user_info_add_pair(user_info, QQ_NUMBER, info->uid); append_field_value(user_info, info->nick, QQ_NICKNAME, NULL, 0); append_field_value(user_info, info->name, QQ_NAME, NULL, 0); append_field_value(user_info, info->age, QQ_AGE, NULL, 0); append_field_value(user_info, info->gender, QQ_GENDER, genders, QQ_GENDER_SIZE); append_field_value(user_info, info->country, QQ_COUNTRY, NULL, 0); append_field_value(user_info, info->province, QQ_PROVINCE, NULL, 0); append_field_value(user_info, info->city, QQ_CITY, NULL, 0); purple_notify_user_info_add_section_header(user_info, QQ_ADDITIONAL_INFORMATION); has_extra_info |= append_field_value(user_info, info->horoscope, QQ_HOROSCOPE, horoscope_names, QQ_HOROSCOPE_SIZE); has_extra_info |= append_field_value(user_info, info->occupation, QQ_OCCUPATION, NULL, 0); has_extra_info |= append_field_value(user_info, info->zodiac, QQ_ZODIAC, zodiac_names, QQ_ZODIAC_SIZE); has_extra_info |= append_field_value(user_info, info->blood, QQ_BLOOD, blood_types, QQ_BLOOD_SIZE); has_extra_info |= append_field_value(user_info, info->college, QQ_COLLEGE, NULL, 0); has_extra_info |= append_field_value(user_info, info->email, QQ_EMAIL, NULL, 0); has_extra_info |= append_field_value(user_info, info->address, QQ_ADDRESS, NULL, 0); has_extra_info |= append_field_value(user_info, info->zipcode, QQ_ZIPCODE, NULL, 0); has_extra_info |= append_field_value(user_info, info->hp_num, QQ_CELL, NULL, 0); has_extra_info |= append_field_value(user_info, info->tel, QQ_TELEPHONE, NULL, 0); has_extra_info |= append_field_value(user_info, info->homepage, QQ_HOMEPAGE, NULL, 0); if (!has_extra_info) purple_notify_user_info_remove_last_item(user_info); intro = field_value(info->intro, NULL, 0); if (intro) { purple_notify_user_info_add_pair(user_info, QQ_INTRO, intro); } /* for debugging */ /* g_string_append_printf(info_text, "<br /><br /><b>%s</b><br />", "Miscellaneous"); append_field_value(info_text, info->pager_sn, "pager_sn", NULL, 0); append_field_value(info_text, info->pager_num, "pager_num", NULL, 0); append_field_value(info_text, info->pager_sp, "pager_sp", NULL, 0); append_field_value(info_text, info->pager_base_num, "pager_base_num", NULL, 0); append_field_value(info_text, info->pager_type, "pager_type", NULL, 0); append_field_value(info_text, info->auth_type, "auth_type", NULL, 0); append_field_value(info_text, info->unknown1, "unknown1", NULL, 0); append_field_value(info_text, info->unknown2, "unknown2", NULL, 0); append_field_value(info_text, info->face, "face", NULL, 0); append_field_value(info_text, info->hp_type, "hp_type", NULL, 0); append_field_value(info_text, info->unknown3, "unknown3", NULL, 0); append_field_value(info_text, info->unknown4, "unknown4", NULL, 0); append_field_value(info_text, info->unknown5, "unknown5", NULL, 0); append_field_value(info_text, info->is_open_hp, "is_open_hp", NULL, 0); append_field_value(info_text, info->is_open_contact, "is_open_contact", NULL, 0); append_field_value(info_text, info->qq_show, "qq_show", NULL, 0); append_field_value(info_text, info->unknown6, "unknown6", NULL, 0); */ return user_info;}/* send a packet to get detailed information of uid */void qq_send_packet_get_info(PurpleConnection *gc, guint32 uid, gboolean show_window){ qq_data *qd; gchar uid_str[11]; qq_info_query *query; g_return_if_fail(uid != 0); qd = (qq_data *) gc->proto_data; g_snprintf(uid_str, sizeof(uid_str), "%d", uid); 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);}/* set up the fields requesting personal information and send a get_info packet * for myself */void qq_prepare_modify_info(PurpleConnection *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 */static void qq_send_packet_modify_info(PurpleConnection *gc, gchar **segments){ gint i; guint8 *raw_data, *cursor, bar; g_return_if_fail(segments != NULL); bar = 0x1f; raw_data = g_newa(guint8, MAX_PACKET_SIZE - 128); cursor = raw_data; create_packet_b(raw_data, &cursor, bar); /* 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, (guint8 *) segments[i], strlen(segments[i])); } create_packet_b(raw_data, &cursor, bar); qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, TRUE, 0, TRUE, raw_data, cursor - raw_data);}static void modify_info_cancel_cb(modify_info_data *mid){ qq_data *qd; qd = (qq_data *) mid->gc->proto_data; qd->modifying_info = FALSE; g_strfreev((gchar **) mid->info); g_free(mid);}static gchar *parse_field(GList **list, gboolean choice){ gchar *value; PurpleRequestField *field; field = (PurpleRequestField *) (*list)->data; if (choice) { value = g_strdup_printf("%d", purple_request_field_choice_get_value(field)); } else { value = (gchar *) purple_request_field_string_get_value(field); if (value == NULL) value = g_strdup("-"); else value = utf8_to_qq(value, QQ_CHARSET_DEFAULT); } *list = g_list_remove_link(*list, *list); return value;}/* parse fields and send info packet */static void modify_info_ok_cb(modify_info_data *mid, PurpleRequestFields *fields){ PurpleConnection *gc; qq_data *qd; GList *list, *groups; contact_info *info; gc = mid->gc; qd = (qq_data *) gc->proto_data; qd->modifying_info = FALSE; info = mid->info; groups = purple_request_fields_get_groups(fields); list = purple_request_field_group_get_fields(groups->data); info->uid = parse_field(&list, FALSE); info->nick = parse_field(&list, FALSE); info->name = parse_field(&list, FALSE); info->age = parse_field(&list, FALSE); info->gender = parse_field(&list, TRUE); info->country = parse_field(&list, FALSE); info->province = parse_field(&list, FALSE); info->city = parse_field(&list, FALSE); groups = g_list_remove_link(groups, groups); list = purple_request_field_group_get_fields(groups->data); info->horoscope = parse_field(&list, TRUE); info->occupation = parse_field(&list, FALSE); info->zodiac = parse_field(&list, TRUE); info->blood = parse_field(&list, TRUE); info->college = parse_field(&list, FALSE); info->email = parse_field(&list, FALSE); info->address = parse_field(&list, FALSE); info->zipcode = parse_field(&list, FALSE); info->hp_num = parse_field(&list, FALSE); info->tel = parse_field(&list, FALSE); info->homepage = parse_field(&list, FALSE); groups = g_list_remove_link(groups, groups); list = purple_request_field_group_get_fields(groups->data); info->intro = parse_field(&list, FALSE); groups = g_list_remove_link(groups, groups); qq_send_packet_modify_info(gc, (gchar **) info); g_strfreev((gchar **) mid->info); g_free(mid);}static PurpleRequestFieldGroup *setup_field_group(PurpleRequestFields *fields, const gchar *title){ PurpleRequestFieldGroup *group; group = purple_request_field_group_new(title); purple_request_fields_add_group(fields, group); return group;}static void add_string_field_to_group(PurpleRequestFieldGroup *group, const gchar *id, const gchar *title, const gchar *value){ PurpleRequestField *field; gchar *utf8_value; utf8_value = qq_to_utf8(value, QQ_CHARSET_DEFAULT); field = purple_request_field_string_new(id, title, utf8_value, FALSE); purple_request_field_group_add_field(group, field); g_free(utf8_value);}static void add_choice_field_to_group(PurpleRequestFieldGroup *group, const gchar *id, const gchar *title, const gchar *value, const gchar **choice, gint choice_size){ PurpleRequestField *field; gint i, index; index = choice_index(value, choice, choice_size); field = purple_request_field_choice_new(id, title, index); for (i = 0; i < choice_size; i++) purple_request_field_choice_add(field, choice[i]); purple_request_field_group_add_field(group, field);}/* take the info returned by a get_info packet for myself and set up a request form */static void create_modify_info_dialogue(PurpleConnection *gc, const contact_info *info){ qq_data *qd; PurpleRequestFieldGroup *group; PurpleRequestFields *fields; PurpleRequestField *field; modify_info_data *mid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -