Mercurial > pidgin.yaz
changeset 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 | 4d5cc9e4cb12 |
children | ff4ee4ac4408 |
files | src/protocols/qq/Makefile.am src/protocols/qq/Makefile.mingw src/protocols/qq/TODO src/protocols/qq/buddy_info.c src/protocols/qq/buddy_info.h src/protocols/qq/buddy_list.c src/protocols/qq/buddy_status.c src/protocols/qq/buddy_status.h src/protocols/qq/group_admindlg.c src/protocols/qq/group_admindlg.h src/protocols/qq/group_opt.c src/protocols/qq/infodlg.c src/protocols/qq/infodlg.h src/protocols/qq/qq.c src/protocols/qq/qq_proxy.c src/protocols/qq/qq_proxy.h src/protocols/qq/show.c src/protocols/qq/show.h src/protocols/qq/utils.c src/protocols/qq/utils.h |
diffstat | 20 files changed, 625 insertions(+), 2694 deletions(-) [+] |
line wrap: on
line diff
--- a/src/protocols/qq/Makefile.am Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/Makefile.am Mon Jul 24 13:39:12 2006 +0000 @@ -21,8 +21,6 @@ char_conv.h \ crypt.c \ crypt.h \ - group_admindlg.c \ - group_admindlg.h \ group.c \ group_conv.c \ group_conv.h \ @@ -52,8 +50,6 @@ header_info.h \ im.c \ im.h \ - infodlg.c \ - infodlg.h \ ip_location.c \ ip_location.h \ keep_alive.c \ @@ -68,8 +64,6 @@ send_core.h \ sendqueue.c \ sendqueue.h \ - show.c \ - show.h \ sys_msg.c \ sys_msg.h \ udp_proxy_s5.c \ @@ -104,6 +98,5 @@ -DLOCALEDIR=\"${datadir}/locale\" \ -DVERSION=\"$(VERSION)\" \ $(DEBUG_CFLAGS) \ - $(GTK_CFLAGS) \ $(GLIB_CFLAGS) \ $(GAIM_CFLAGS)
--- a/src/protocols/qq/Makefile.mingw Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/Makefile.mingw Mon Jul 24 13:39:12 2006 +0000 @@ -82,7 +82,6 @@ crypt.c \ file_trans.c \ group.c \ - group_admindlg.c \ group_conv.c \ group_find.c \ group_free.c \ @@ -96,7 +95,6 @@ group_search.c \ header_info.c \ im.c \ - infodlg.c \ ip_location.c \ keep_alive.c \ login_logout.c \
--- a/src/protocols/qq/TODO Mon Jul 24 09:25:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -* Decide how to handle QQ status icons, which are customizable and legion. -* Give "Online Offline" and "My Offline" statuses appropriate titles. -* Handle emoticon at beginning of message via passthrough_unknown_commands. -* Fix file transfer. -* QQ protocol currently breaks Chinese localization of Gaim. Fix this. -* Fix ability to insert images into a conversation via the menubar. -* Fix _qq_menu_block_buddy in qq.c -* Eliminate all references to QQWry.dat and the geolocation lookup feature previously present OpenQ. -* Give smileys verbal instead of numerical titles. -* Clean up signedness warnings. -* Clean up mixed declaration and code warnings. -* Better decomposition: -** some of these functions are _really_ long -** buddy_status.c has a helper function which seems to belong in buddy_status.c -** consider cleaning up qq_encrypt (nested function declarations) -** eliminate group_misc.c -** investigate whether all of these externs are appropriate -* Check for memory leaks.
--- 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 +}
--- a/src/protocols/qq/buddy_info.h Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/buddy_info.h Mon Jul 24 13:39:12 2006 +0000 @@ -40,9 +40,7 @@ #define QQ_BUDDY_GENDER_MM 0x01 #define QQ_BUDDY_GENDER_UNKNOWN 0xff -typedef struct _contact_info contact_info; - -struct _contact_info { +typedef struct _contact_info { gchar *uid; //0 gchar *nick; //1 gchar *country; //2 @@ -80,15 +78,46 @@ gchar *blood; //34 gchar *qq_show; //35 gchar *unknown6; //36, always 0x2D -}; +} contact_info; + +// 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 currently modifiable, it still +// all needs to be there when we send out the modify info packet +typedef struct _modify_info_data { + GaimConnection *gc; + GList *misc, *node; +} modify_info_data; + +#define QQ_CONTACT_FIELDS 37 -void qq_refresh_buddy_and_myself(contact_info * info, GaimConnection * gc); -void qq_send_packet_get_info(GaimConnection * gc, guint32 uid, gboolean show_window); -void qq_send_packet_modify_info(GaimConnection * gc, contact_info * info, gchar * new_passwd); -void qq_process_modify_info_reply(guint8 * buf, gint buf_len, GaimConnection * gc); -void qq_process_get_info_reply(guint8 * buf, gint buf_len, GaimConnection * gc); -void qq_info_query_free(qq_data * qd); +#define QQ_MAIN_INFO "Primary Information" +#define QQ_EXTRA_INFO "Detailed Information" +#define QQ_PERSONAL_INTRO "Personal Introduction" +#define QQ_MISC "Miscellaneous" + +#define QQ_NO_CHOICE 0 +#define QQ_HOROSCOPE 1 +#define QQ_ZODIAC 2 +#define QQ_BLOOD 3 +#define QQ_GENDER 4 +#define QQ_COUNTRY 5 +#define QQ_PROVINCE 6 +#define QQ_OCCUPATION 7 + +void qq_refresh_buddy_and_myself(contact_info *info, GaimConnection *gc); +void qq_send_packet_get_info(GaimConnection *gc, guint32 uid, gboolean show_window); +void qq_send_packet_modify_info(GaimConnection *gc, contact_info *info, gchar *new_passwd); +void qq_prepare_modify_info(GaimConnection *gc); +void qq_process_modify_info_reply(guint8 *buf, gint buf_len, GaimConnection *gc); +void qq_process_get_info_reply(guint8 *buf, gint buf_len, GaimConnection *gc); +void qq_info_query_free(qq_data *qd); #endif -/*****************************************************************************/ -// END OF FILE
--- a/src/protocols/qq/buddy_list.c Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/buddy_list.c Mon Jul 24 13:39:12 2006 +0000 @@ -42,6 +42,8 @@ #include "group_hash.h" //qq_group_create_by_id #include "group_info.h" //qq_send_cmd_group_get_group_info +#include "qq_proxy.h" + #define QQ_GET_ONLINE_BUDDY_02 0x02 #define QQ_GET_ONLINE_BUDDY_03 0x03 // unknown function @@ -56,13 +58,6 @@ guint8 ending; //0x00 } qq_friends_online_entry; -//TODO: defined in qq_buddy_status.c, but only used here. Check decomposition. -extern void // defined in qq_buddy_status.c - _qq_buddy_status_dump_unclear(qq_buddy_status * s); - -extern gint // defined in qq_buddy_status.c - _qq_buddy_status_read(guint8 * data, guint8 ** cursor, gint len, qq_buddy_status * s); - /*****************************************************************************/ // get a list of online_buddies void qq_send_packet_get_buddies_online(GaimConnection * gc, guint8 position) @@ -148,7 +143,7 @@ g_return_if_fail(fe != NULL); - _qq_buddy_status_dump_unclear(fe->s); + qq_buddy_status_dump_unclear(fe->s); dump = g_string_new(""); g_string_append_printf(dump, "unclear fields for [%d]:\n", fe->s->uid); @@ -180,9 +175,14 @@ data = g_newa(guint8, len); cursor = data; + gaim_debug(GAIM_DEBUG_INFO, "QQ", "processing get_buddies_online_reply\n"); + if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { + _qq_show_packet("Get buddies online reply packet", data, len); + read_packet_b(data, &cursor, len, &position); + fe = g_newa(qq_friends_online_entry, 1); fe->s = g_newa(qq_buddy_status, 1); @@ -190,7 +190,7 @@ // based on one online buddy entry bytes = 0; // 000-030 qq_buddy_status - bytes += _qq_buddy_status_read(data, &cursor, len, fe->s); + bytes += qq_buddy_status_read(data, &cursor, len, fe->s); // 031-032: unknown4 bytes += read_packet_w(data, &cursor, len, &fe->unknown1); // 033-033: flag1 @@ -209,8 +209,8 @@ continue; } // check if it is a valid entry -// if (QQ_DEBUG) -// _qq_buddies_online_reply_dump_unclear(fe); + if (QQ_DEBUG) + _qq_buddies_online_reply_dump_unclear(fe); // update buddy information b = gaim_find_buddy(gaim_connection_get_account(gc), uid_to_gaim_name(fe->s->uid)); @@ -219,10 +219,10 @@ if (q_bud != NULL) { // we find one and update qq_buddy if(0 != fe->s->client_version) q_bud->client_version = fe->s->client_version; //by gfhuang - if(0 != *((guint32 *)fe->s->ip)) { // by gfhuang + // if(0 != *((guint32 *)fe->s->ip)) { // by gfhuang g_memmove(q_bud->ip, fe->s->ip, 4); q_bud->port = fe->s->port; - } + // } q_bud->status = fe->s->status; q_bud->flag1 = fe->flag1; q_bud->comm_flag = fe->comm_flag;
--- a/src/protocols/qq/buddy_status.c Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/buddy_status.c Mon Jul 24 13:39:12 2006 +0000 @@ -34,6 +34,8 @@ #include "keep_alive.h" // qq_update_buddy_contact #include "send_core.h" // qq_send_cmd +#include "qq_proxy.h" + #define QQ_MISC_STATUS_HAVING_VIIDEO 0x00000001 #define QQ_ICON_SUFFIX_DEFAULT QQ_ICON_SUFFIX_OFFLINE @@ -46,7 +48,7 @@ }; /*****************************************************************************/ -static void _qq_buddy_status_dump_unclear(qq_buddy_status * s) +void qq_buddy_status_dump_unclear(qq_buddy_status * s) { GString *dump; @@ -55,14 +57,23 @@ 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, "005-008: %09x (ip)\n", *(s->ip)); + g_string_append_printf(dump, "009-010: %04x (port)\n", s->port); g_string_append_printf(dump, "011: %02x (unknown)\n", s->unknown2); + g_string_append_printf(dump, "012: %02x (status)\n", s->status); + g_string_append_printf(dump, "013-014: %04x (client_version)\n", s->client_version); + //g_string_append_printf(dump, "015-030: %s (unknown key)\n", s->unknown_key); gaim_debug(GAIM_DEBUG_INFO, "QQ", "Buddy status entry, %s", dump->str); + _qq_show_packet("Unknown key", s->unknown_key, QQ_KEY_LENGTH); g_string_free(dump, TRUE); -} // _qq_buddy_status_dump_unclear +} /*****************************************************************************/ +// TODO: figure out what's going on with the IP region. Sometimes I get things which +// may be valid IP addresses, but the port number's weird, other times I get 0s. +// Note: I get these simultaneously on the same buddy, using different accounts to get info. // parse the data into qq_buddy_status -gint _qq_buddy_status_read(guint8 * data, guint8 ** cursor, gint len, qq_buddy_status * s) { +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); @@ -73,9 +84,12 @@ bytes += read_packet_dw(data, cursor, len, &s->uid); // 004-004: 0x01 bytes += read_packet_b(data, cursor, len, &s->unknown1); + // this is no longer the IP, it seems QQ (as of 2006) no longer sends + // the buddy's IP in this packet. all 0s // 005-008: ip s->ip = g_new0(guint8, 4); bytes += read_packet_data(data, cursor, len, s->ip, 4); + // port info is no longer here either // 009-010: port bytes += read_packet_w(data, cursor, len, &s->port); // 011-011: 0x00 @@ -93,7 +107,7 @@ return bytes; -} // _qq_buddy_status_read +} /*****************************************************************************/ // check if status means online or offline @@ -159,7 +173,7 @@ break; default: away_cmd = QQ_BUDDY_ONLINE_NORMAL; - } // switch + } raw_data = g_new0(guint8, 5); cursor = raw_data; @@ -175,7 +189,7 @@ 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 @@ -201,7 +215,7 @@ } else gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt chg status reply\n"); -} // qq_process_change_status_reply +} /*****************************************************************************/ // it is a server message @@ -228,7 +242,7 @@ s = g_new0(qq_buddy_status, 1); bytes = 0; // 000-030: qq_buddy_status; - bytes += _qq_buddy_status_read(data, &cursor, len, s); + bytes += qq_buddy_status_read(data, &cursor, len, s); // 031-034: my uid bytes += read_packet_dw(data, &cursor, len, &my_uid); @@ -242,19 +256,19 @@ // if (QQ_DEBUG) gfhuang // _qq_buddy_status_dump_unclear(s); - name = uid_to_gaim_name(s->uid); //by gfhuang + name = uid_to_gaim_name(s->uid); 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 + if(0 != *((guint32 *)s->ip)) { 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 + q_bud->client_version = s->client_version; qq_update_buddy_contact(gc, q_bud); } else @@ -265,8 +279,7 @@ 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
--- a/src/protocols/qq/buddy_status.h Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/buddy_status.h Mon Jul 24 13:39:12 2006 +0000 @@ -56,9 +56,11 @@ QQ_SELF_STATUS_CUSTOM = 0x14, QQ_SELF_STATUS_IDLE = 0x15, }; - + +void qq_buddy_status_dump_unclear(qq_buddy_status * s); gboolean is_online(guint8 status); +gint qq_buddy_status_read(guint8 * data, guint8 ** cursor, gint len, qq_buddy_status * s); gchar get_suffix_from_status(guint8 status); void qq_send_packet_change_status(GaimConnection * gc);
--- a/src/protocols/qq/group_admindlg.c Mon Jul 24 09:25:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,659 +0,0 @@ -/** -* 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 "debug.h" // gaim_debug -#include "blist.h" // GAIM_BLIST_NODE_IS_BUDDY -#include "notify.h" // gaim_notify_warning - -#include "utils.h" // gaim_name_to_uid -#include "group_admindlg.h" -#include "group_find.h" // qq_group_find_by_internal_group_id -#include "group_join.h" // auth_type -#include "group_opt.h" // QQ_GROUP_TYPE_PERMANENT - -enum { - COLUMN_SELECTED = 0, - COLUMN_UID, - COLUMN_NICKNAME, - NUM_COLUMNS -}; - -enum { - PAGE_INFO = 0, - PAGE_MEMBER, -}; - -typedef struct _qun_info_window { - guint32 internal_group_id; - GaimConnection *gc; - GtkWidget *window; - GtkWidget *notebook; - GtkWidget *lbl_external_group_id; - GtkWidget *lbl_admin_uid; - GtkWidget *ent_group_name; - GtkWidget *cmb_group_category; - GtkWidget *txt_group_desc; - GtkWidget *txt_group_notice; - GtkWidget *rad_auth[3]; - GtkWidget *btn_mod; - GtkWidget *btn_close; - GtkWidget *tre_members; -} qun_info_window; - -const gchar *qq_group_category[] = { - "同学", "朋友", "同事", "其他", -}; // qq_group_category - -const gchar *qq_group_auth_type_desc[] = { - "无须认证", "需要认证", "不可添加", -}; // qq_group_auth_type_desc - -/*****************************************************************************/ -static void _qq_group_info_window_deleteevent(GtkWidget * widget, GdkEvent * event, gpointer data) { - gtk_widget_destroy(widget); // this will call _window_destroy -} // _window_deleteevent - -/*****************************************************************************/ -static void _qq_group_info_window_close(GtkWidget * widget, gpointer data) -{ - // this will call _info_window_destroy if it is info-window - gtk_widget_destroy(GTK_WIDGET(data)); -} // _window_close - -/*****************************************************************************/ -static void _qq_group_info_window_destroy(GtkWidget * widget, gpointer data) -{ - GaimConnection *gc; - GList *list; - qq_data *qd; - qun_info_window *info_window; - - gc = (GaimConnection *) data; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group info is destoryed\n"); - - qd = (qq_data *) gc->proto_data; - list = qd->qun_info_window; - - while (list) { - info_window = (qun_info_window *) (list->data); - if (info_window->window != widget) - list = list->next; - else { - qd->qun_info_window = g_list_remove(qd->qun_info_window, info_window); - g_free(info_window); - break; - } // if info_window - } // while -} // _window_destroy - -/*****************************************************************************/ -void qq_qun_info_window_free(qq_data * qd) -{ - gint i; - qun_info_window *info_window; - - i = 0; - while (qd->qun_info_window) { - info_window = (qun_info_window *) qd->qun_info_window->data; - qd->qun_info_window = g_list_remove(qd->qun_info_window, info_window); - if (info_window->window) - gtk_widget_destroy(info_window->window); - g_free(info_window); - i++; - } // while - - gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d Qun info windows are freed\n", i); -} // qq_qun_info_window_free - -/*****************************************************************************/ -static void _qq_group_info_window_modify(GtkWidget * widget, gpointer data) -{ - GaimConnection *gc; - qun_info_window *info_window; - - g_return_if_fail(data != NULL); - info_window = (qun_info_window *) data; - - gc = info_window->gc; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - //henry: This function contains some codes only supported by gtk-2.4 or later -//#if !GTK_CHECK_VERSION(2,4,0) -// gaim_notify_info(gc, _("QQ Qun Operation"), -// _("This version of GTK-2 does not support this function"), NULL); -// return; -//#else - gint page, group_category, i = 0; - qq_group *group; - qq_data *qd; - GtkTextIter start, end; - GtkTreeModel *model; - GtkTreeIter iter; - GValue value = { 0, }; - guint32 *new_members; - guint32 uid; - gboolean selected; - - qd = (qq_data *) gc->proto_data; - - // we assume the modification can succeed - // maybe it needs some tweak here - group = qq_group_find_by_internal_group_id(gc, info_window->internal_group_id); - g_return_if_fail(group != NULL); - - new_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); - - page = gtk_notebook_get_current_page(GTK_NOTEBOOK(info_window->notebook)); - switch (page) { - case PAGE_INFO: - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Gonna change Qun detailed information\n"); - // get the group_category -#if GTK_CHECK_VERSION(2,4,0) - group_category = gtk_combo_box_get_active(GTK_COMBO_BOX(info_window->cmb_group_category)); -#else - group_category = gtk_option_menu_get_history(GTK_OPTION_MENU(info_window->cmb_group_category)); -#endif - - if (group_category >= 0) - group->group_category = group_category; - else { - g_free(group); - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid group_category: %d\n", group_category); - return; - } // if group_category - // get auth_type - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[0]))) - group->auth_type = QQ_GROUP_AUTH_TYPE_NO_AUTH; - else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[1]))) - group->auth_type = QQ_GROUP_AUTH_TYPE_NEED_AUTH; - else - group->auth_type = QQ_GROUP_AUTH_TYPE_NO_ADD; - // MUST use g_strdup, otherwise core dump after info_window is closed - group->group_name_utf8 = g_strdup(gtk_entry_get_text(GTK_ENTRY(info_window->ent_group_name))); - gtk_text_buffer_get_bounds(gtk_text_view_get_buffer - (GTK_TEXT_VIEW(info_window->txt_group_desc)), &start, &end); - group->group_desc_utf8 = - g_strdup(gtk_text_buffer_get_text - (gtk_text_view_get_buffer - (GTK_TEXT_VIEW(info_window->txt_group_desc)), &start, &end, FALSE)); - gtk_text_buffer_get_bounds(gtk_text_view_get_buffer - (GTK_TEXT_VIEW(info_window->txt_group_notice)), &start, &end); - group->notice_utf8 = - g_strdup(gtk_text_buffer_get_text - (gtk_text_view_get_buffer - (GTK_TEXT_VIEW(info_window->txt_group_notice)), &start, &end, FALSE)); - // finally we can modify it with new information - qq_group_modify_info(gc, group); - break; - case PAGE_MEMBER: - if (info_window->tre_members == NULL) { - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Member list is not ready, cannot modify!\n"); - } else { - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Gonna change Qun member list\n"); - model = gtk_tree_view_get_model(GTK_TREE_VIEW(info_window->tre_members)); - if (gtk_tree_model_get_iter_first(model, &iter)) { - gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); - uid = g_value_get_uint(&value); - g_value_unset(&value); - gtk_tree_model_get_value(model, &iter, COLUMN_SELECTED, &value); - selected = g_value_get_boolean(&value); - g_value_unset(&value); - if (!selected) - new_members[i++] = uid; - while (gtk_tree_model_iter_next(model, &iter)) { - gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); - uid = g_value_get_uint(&value); - g_value_unset(&value); - gtk_tree_model_get_value(model, &iter, COLUMN_SELECTED, &value); - selected = g_value_get_boolean(&value); - g_value_unset(&value); - if (!selected) - new_members[i++] = uid; - } // while - new_members[i] = 0xffffffff; // this labels the end - } else - new_members[0] = 0xffffffff; - qq_group_modify_members(gc, group, new_members); - } // if info_window->tre_members - break; - default: - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Invalid page number: %d\n", page); - } // switch - - _qq_group_info_window_close(NULL, info_window->window); - -//#endif /* GTK_CHECK_VERSION */ -} // _qq_group_info_window_modify - -/*****************************************************************************/ -static void _qq_group_member_list_deleted_toggled(GtkCellRendererToggle * cell, gchar * path_str, gpointer data) { - qun_info_window *info_window; - GaimConnection *gc; - qq_group *group; - - info_window = (qun_info_window *) data; - g_return_if_fail(info_window != NULL); - - gc = info_window->gc; - g_return_if_fail(gc != NULL); - - group = qq_group_find_by_internal_group_id(gc, info_window->internal_group_id); - g_return_if_fail(group != NULL); - - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(info_window->tre_members)); - GtkTreeIter iter; - GtkTreePath *path = gtk_tree_path_new_from_string(path_str); - gboolean selected; - guint32 uid; - - gtk_tree_model_get_iter(model, &iter, path); - gtk_tree_model_get(model, &iter, COLUMN_SELECTED, &selected, -1); - gtk_tree_model_get(model, &iter, COLUMN_UID, &uid, -1); - - if (uid != group->creator_uid) { // do not allow delete admin - selected ^= 1; - gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_SELECTED, selected, -1); - gtk_tree_path_free(path); - } else - gaim_notify_error(gc, NULL, _("Qun creator cannot be removed"), NULL); -} // _qq_group_member_list_deleted_toggled - -/*****************************************************************************/ -static void _qq_group_member_list_drag_data_rcv_cb - (GtkWidget * widget, GdkDragContext * dc, guint x, guint y, - GtkSelectionData * sd, guint info, guint t, gpointer data) { - - GaimConnection *gc; - GaimAccount *account; - GaimBlistNode *n = NULL; - GaimContact *c = NULL; - GaimBuddy *b = NULL; - GtkWidget *treeview; - GtkTreeModel *model; - GtkListStore *store; - GtkTreeIter iter; - GValue value = { 0, }; - guint32 uid, input_uid; - - treeview = widget; - gc = (GaimConnection *) data; - g_return_if_fail(gc != NULL); - account = gaim_connection_get_account(gc); - - if (sd->target != gdk_atom_intern("GAIM_BLIST_NODE", FALSE) || sd->data == NULL) { - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid drag data received, discard...\n"); - return; - } // if (sd->target - - memcpy(&n, sd->data, sizeof(n)); - - // we expect GAIM_BLIST_CONTACT_NODE and GAIM_BLIST_BUDDY_NODE - if (GAIM_BLIST_NODE_IS_CONTACT(n)) { - c = (GaimContact *) n; - b = c->priority; // we get the first buddy only - } else if (GAIM_BLIST_NODE_IS_BUDDY(n)) - b = (GaimBuddy *) n; - - if (b == NULL) { - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "No valid GaimBuddy is passed from DnD\n"); - return; - } // if b == NULL - - gaim_debug(GAIM_DEBUG_INFO, "QQ", "We get a GaimBuddy: %s\n", b->name); - input_uid = gaim_name_to_uid(b->name); - g_return_if_fail(input_uid > 0); - - model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); - // we need to check if the user id in the member list is unique - // possibly a tree transverse is necessary to achieve this - if (gtk_tree_model_get_iter_first(model, &iter)) { - gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); - uid = g_value_get_uint(&value); - g_value_unset(&value); - while (uid != input_uid && gtk_tree_model_iter_next(model, &iter)) { - gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); - uid = g_value_get_uint(&value); - g_value_unset(&value); - } // while - } else - uid = 0; // if gtk_tree_model_get_iter_first - - if (uid == input_uid) { - gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Qun already has this buddy %s\n", b->name); - return; - } else { // we add it to list - store = GTK_LIST_STORE(model); - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - COLUMN_SELECTED, FALSE, COLUMN_UID, input_uid, COLUMN_NICKNAME, b->alias, -1); - // re-sort the list - gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COLUMN_UID, GTK_SORT_ASCENDING); - } // if uid - -} // _qq_group_member_list_drag_data_rcv_cb - -/*****************************************************************************/ -static GtkWidget *_create_page_info(GaimConnection * gc, qq_group * group, gboolean do_manage, qun_info_window * info_window) { - GtkWidget *vbox, *hbox; - GtkWidget *frame_info, *frame_auth; - GtkWidget *tbl_info; - GtkWidget *label, *entry, *combo, *text, *scrolled_window; - gint i; - - g_return_val_if_fail(gc != NULL && group != NULL, NULL); - - vbox = gtk_vbox_new(FALSE, 5); - - frame_info = gtk_frame_new(NULL); - gtk_box_pack_start(GTK_BOX(vbox), frame_info, TRUE, TRUE, 0); - - tbl_info = gtk_table_new(6, 4, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(tbl_info), 4); - gtk_table_set_col_spacing(GTK_TABLE(tbl_info), 1, 10); - gtk_container_add(GTK_CONTAINER(frame_info), tbl_info); - - label = gtk_label_new(_("Group ID: ")); - gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); - label = gtk_label_new(g_strdup_printf("%d", group->external_group_id)); - gtk_table_attach(GTK_TABLE(tbl_info), label, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); - info_window->lbl_external_group_id = label; - - label = gtk_label_new(_("Group Name")); - gtk_table_attach(GTK_TABLE(tbl_info), label, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0); - entry = gtk_entry_new(); - gtk_widget_set_size_request(entry, 100, -1); - if (group->group_name_utf8 != NULL) - gtk_entry_set_text(GTK_ENTRY(entry), group->group_name_utf8); - gtk_table_attach(GTK_TABLE(tbl_info), entry, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0); - info_window->ent_group_name = entry; - - label = gtk_label_new(_("Admin: ")); - gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); - label = gtk_label_new(g_strdup_printf("%d", group->creator_uid)); - gtk_table_attach(GTK_TABLE(tbl_info), label, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); - info_window->lbl_admin_uid = label; - - label = gtk_label_new(_("Category")); - gtk_table_attach(GTK_TABLE(tbl_info), label, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0); - - //henry: these codes are supported only in GTK-2.4 or later -#if GTK_CHECK_VERSION(2, 4, 0) - combo = gtk_combo_box_new_text(); - for (i = 0; i < 4; i++) - gtk_combo_box_append_text(GTK_COMBO_BOX(combo), qq_group_category[i]); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), group->group_category); -#else - GtkWidget *menu; - GtkWidget *item; - - combo = gtk_option_menu_new(); - menu = gtk_menu_new(); - for (i = 0; i < 4; i++) { - item = gtk_menu_item_new_with_label(qq_group_category[i]); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - gtk_widget_show(item); - } - gtk_option_menu_set_menu(GTK_OPTION_MENU(combo), menu); - gtk_option_menu_set_history(GTK_OPTION_MENU(combo), group->group_category); -#endif /* GTK_CHECK_VERSION */ - - gtk_table_attach(GTK_TABLE(tbl_info), combo, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0); - info_window->cmb_group_category = combo; - - label = gtk_label_new(_("Description")); - gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); - text = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); - gtk_widget_set_size_request(text, -1, 50); - if (group->group_desc_utf8 != NULL) - gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), group->group_desc_utf8, -1); - info_window->txt_group_desc = text; - - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(scrolled_window), text); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2); - gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2); - gtk_table_attach(GTK_TABLE(tbl_info), scrolled_window, 0, 4, 3, 4, GTK_FILL, GTK_FILL, 0, 0); - - label = gtk_label_new(_("Group Notice")); - gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0); - text = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); - gtk_widget_set_size_request(text, -1, 50); - if (group->notice_utf8 != NULL) - gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), group->notice_utf8, -1); - info_window->txt_group_notice = text; - - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(scrolled_window), text); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2); - gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2); - gtk_table_attach(GTK_TABLE(tbl_info), scrolled_window, 0, 4, 5, 6, GTK_FILL, GTK_FILL, 0, 0); - - frame_auth = gtk_frame_new(_("Authentication")); - hbox = gtk_hbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(frame_auth), hbox); - info_window->rad_auth[0] = gtk_radio_button_new_with_label(NULL, qq_group_auth_type_desc[0]); - info_window->rad_auth[1] = - gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON - (info_window->rad_auth[0]), qq_group_auth_type_desc[1]); - info_window->rad_auth[2] = - gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON - (info_window->rad_auth[0]), qq_group_auth_type_desc[2]); - for (i = 0; i < 3; i++) - gtk_box_pack_start(GTK_BOX(hbox), info_window->rad_auth[i], FALSE, FALSE, 0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[group->auth_type - 1]), TRUE); - gtk_box_pack_start(GTK_BOX(vbox), frame_auth, FALSE, FALSE, 0); - - if (!do_manage) { - gtk_widget_set_sensitive(frame_info, FALSE); - gtk_widget_set_sensitive(frame_auth, FALSE); - } // if ! do_manage - - return vbox; -} // _create_info_page - -/*****************************************************************************/ -static GtkWidget *_create_page_members - (GaimConnection * gc, qq_group * group, gboolean do_manage, qun_info_window * info_window) { - GtkWidget *vbox, *sw, *treeview; - GtkTreeModel *model; - GtkListStore *store; - GtkTreeIter iter; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GList *list; - qq_buddy *q_bud; - GtkTargetEntry gte = { "GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, 0 }; - - g_return_val_if_fail(gc != NULL && group != NULL, NULL); - - vbox = gtk_vbox_new(FALSE, 0); - - if (group->members == NULL) { // if NULL, not ready - sw = gtk_label_new(_ - ("OpenQ is collecting member information.\nPlease close this window and open again")); - gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); - return vbox; - } // if group->members - - sw = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); - - store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING); - - list = group->members; - while (list != NULL) { - q_bud = (qq_buddy *) list->data; - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - COLUMN_SELECTED, FALSE, - COLUMN_UID, q_bud->uid, COLUMN_NICKNAME, q_bud->nickname, -1); - list = list->next; - } // for - - model = GTK_TREE_MODEL(store); - treeview = gtk_tree_view_new_with_model(model); - info_window->tre_members = treeview; - - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); - gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), COLUMN_UID); - g_object_unref(model); - - // set up drag & drop ONLY for managable Qun - if (do_manage) { - gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(treeview), >e, 1, GDK_ACTION_COPY); - g_signal_connect(G_OBJECT(treeview), "drag-data-received", - G_CALLBACK(_qq_group_member_list_drag_data_rcv_cb), gc); - } // if do manage - - gtk_container_add(GTK_CONTAINER(sw), treeview); - - model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); - renderer = gtk_cell_renderer_toggle_new(); - - // it seems this signal has to be handled - // otherwise, the checkbox in the column does not reponse to user action - if (do_manage) - g_signal_connect(renderer, "toggled", G_CALLBACK(_qq_group_member_list_deleted_toggled), info_window); - - column = gtk_tree_view_column_new_with_attributes(_("Del"), renderer, "active", COLUMN_SELECTED, NULL); - - gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(GTK_TREE_VIEW_COLUMN(column), 30); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("UID"), renderer, "text", COLUMN_UID, NULL); - gtk_tree_view_column_set_sort_column_id(column, COLUMN_UID); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - // default sort by UID - gtk_tree_view_column_set_sort_order(column, GTK_SORT_ASCENDING); - gtk_tree_view_column_set_sort_indicator(column, TRUE); - - renderer = gtk_cell_renderer_text_new(); - column = gtk_tree_view_column_new_with_attributes(_("Nickname"), renderer, "text", COLUMN_NICKNAME, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - - return vbox; -} // _create_page_members - -/*****************************************************************************/ -void qq_group_detail_window_show(GaimConnection * gc, qq_group * group) -{ - GtkWidget *vbox, *notebook; - GtkWidget *label, *bbox; - GList *list; - qq_data *qd; - qun_info_window *info_window = NULL; - gboolean do_manage, do_show, do_exist; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL && group != NULL); - qd = (qq_data *) gc->proto_data; - - do_manage = group->my_status == QQ_GROUP_MEMBER_STATUS_IS_ADMIN; - do_show = do_manage || (group->my_status == QQ_GROUP_MEMBER_STATUS_IS_MEMBER); - - if (!do_show) { - gaim_notify_error(gc, _("QQ Qun Operation"), - _("You can not view Qun details"), - _("Only Qun admin or Qun member can view details")); - return; - } // if ! do_show - - list = qd->qun_info_window; - do_exist = FALSE; - while (list != NULL) { - info_window = (qun_info_window *) list->data; - if (info_window->internal_group_id == group->internal_group_id) { - break; - do_exist = TRUE; - } else - list = list->next; - } // while list - - if (!do_exist) { - info_window = g_new0(qun_info_window, 1); - info_window->gc = gc; - info_window->internal_group_id = group->internal_group_id; - g_list_append(qd->qun_info_window, info_window); - - info_window->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - g_signal_connect(GTK_WINDOW(info_window->window), - "delete_event", G_CALLBACK(_qq_group_info_window_deleteevent), NULL); - g_signal_connect(G_OBJECT(info_window->window), "destroy", - G_CALLBACK(_qq_group_info_window_destroy), gc); - - gtk_window_set_title(GTK_WINDOW(info_window->window), _("Manage Qun")); - gtk_window_set_resizable(GTK_WINDOW(info_window->window), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(info_window->window), 5); - - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(info_window->window), vbox); - - notebook = gtk_notebook_new(); - info_window->notebook = notebook; - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); - - label = gtk_label_new(_("Qun Information")); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), - _create_page_info(gc, group, do_manage, info_window), label); - label = gtk_label_new(_("Members")); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), - _create_page_members(gc, group, do_manage, info_window), label); - - bbox = gtk_hbutton_box_new(); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD); - gtk_box_set_spacing(GTK_BOX(bbox), 10); - - info_window->btn_mod = gtk_button_new_with_label(_("Modify")); - gtk_container_add(GTK_CONTAINER(bbox), info_window->btn_mod); - g_signal_connect(G_OBJECT(info_window->btn_mod), "clicked", - G_CALLBACK(_qq_group_info_window_modify), info_window); - - info_window->btn_close = gtk_button_new_with_label(_("Close")); - gtk_container_add(GTK_CONTAINER(bbox), info_window->btn_close); - g_signal_connect(G_OBJECT(info_window->btn_close), - "clicked", G_CALLBACK(_qq_group_info_window_close), info_window->window); - - if (!do_manage) - gtk_widget_set_sensitive(info_window->btn_mod, FALSE); - gtk_box_pack_start(GTK_BOX(vbox), bbox, TRUE, TRUE, 5); - gtk_widget_show_all(info_window->window); - - } else // we already have this - gtk_widget_grab_focus(info_window->window); - -} // qq_group_manage_window_show - -/*****************************************************************************/ -// END OF FILE
--- a/src/protocols/qq/group_admindlg.h Mon Jul 24 09:25:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/** -* 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 -/*****************************************************************************/ -#ifndef _QQ_GROUP_ADMINDLG_H_ -#define _QQ_GROUP_ADMINDLG_H_ - -#include <glib.h> -#include <gtk/gtk.h> -#include "connection.h" -#include "group.h" -#include "qq.h" - -void qq_group_detail_window_show(GaimConnection * gc, qq_group * group); - -void qq_qun_info_window_free(qq_data * qd); -#endif -/*****************************************************************************/ -// END OF FILE
--- a/src/protocols/qq/group_opt.c Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/group_opt.c Mon Jul 24 13:39:12 2006 +0000 @@ -30,7 +30,7 @@ #include "packet_parse.h" // create_packet_b #include "buddy_info.h" // qq_send_packet_get_info #include "char_conv.h" // utf8_to_qq -#include "group_admindlg.h" // qq_group_manage_window_show +//#include "group_admindlg.h" // qq_group_detail_window_show #include "group_find.h" // qq_group_find_by_internal_group_id #include "group_hash.h" // qq_group_refresh #include "group_info.h" // qq_send_cmd_group_get_group_info @@ -366,7 +366,8 @@ group = qq_group_find_by_internal_group_id(g->gc, g->uid); g_return_if_fail(group != NULL); - qq_group_detail_window_show(g->gc, group); + //XXX insert UI code here + //qq_group_detail_window_show(g->gc, group); g_free(g); } // qq_group_setup_with_gc_and_uid @@ -470,7 +471,8 @@ group = qq_group_find_by_internal_group_id(gc, internal_group_id); g_return_if_fail(group != NULL); - qq_group_detail_window_show(gc, group); + //XXX insert UI code here + //qq_group_detail_window_show(gc, group); } // qq_group_manage_members
--- a/src/protocols/qq/infodlg.c Mon Jul 24 09:25:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1127 +0,0 @@ -/** - * 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 "debug.h" // gaim_debug -#include "internal.h" // strlen, _("get_text") -#include "notify.h" // gaim_notify_error - -#include "utils.h" // get_face_gdkpixbuf -#include "char_conv.h" // qq_to_utf8 -#include "show.h" // qq_show_get_image -#include "infodlg.h" - -// must be defined after qq_infodlg.h to have <gtk/gtk.h> -#include "gtkdialogs.h" // GAIM_DIALOG, mainwindow - - -// the follwoing definition is in UTF-8 -const gint blood_types_count = 5; -const gchar *blood_types[] = { - "其它", "A", "B", "O", "AB", -}; - -const gint country_names_count = 6; -const gchar *country_names[] = { - "中国", "中国香港", "中国澳门", "中国台湾", - "新加坡", "马来西亚", "美国", -}; - -const gint province_names_count = 34; -const gchar *province_names[] = { - "北京", "天津", "上海", "重庆", "香港", - "河北", "山西", "内蒙古", "辽宁", "吉林", - "黑龙江", "江西", "浙江", "江苏", "安徽", - "福建", "山东", "河南", "湖北", "湖南", - "广东", "广西", "海南", "四川", "贵州", - "云南", "西藏", "陕西", "甘肃", "宁夏", - "青海", "新疆", "台湾", "澳门", -}; - -const gint zodiac_names_count = 13; -const gchar *zodiac_names[] = { - "-", "鼠", "牛", "虎", "兔", - "龙", "蛇", "马", "羊", "猴", - "鸡", "狗", "猪", -}; - -const gint horoscope_names_count = 13; -const gchar *horoscope_names[] = { - "-", "水瓶座", "双鱼座", "牡羊座", "金牛座", - "双子座", "巨蟹座", "狮子座", "处女座", "天秤座", - "天蝎座", "射手座", "魔羯座", -}; - -const gint occupation_names_count = 15; -const gchar *occupation_names[] = { - "全职", "兼职", "制造业", "商业", "失业中", - "学生", "工程师", "政府部门", "教育业", "服务行业", - "老板", "计算机业", "退休", "金融业", - "销售/广告/市场", -}; - -enum { - QQ_CONTACT_OPEN = 0x00, - QQ_CONTACT_ONLY_FRIENDS = 0x01, - QQ_CONTACT_CLOSE = 0x02, -}; - - -enum { - QQ_AUTH_NO_AUTH = 0x00, - QQ_AUTH_NEED_AUTH = 0x01, - QQ_AUTH_NO_ADD = 0x02, -}; - -typedef struct _change_icon_widgets change_icon_widgets; - -struct _change_icon_widgets { - GtkWidget *dialog; // dialog that shows all icons - GtkWidget *face; // the image widget we are going to change -}; - -/*****************************************************************************/ -static void _window_deleteevent(GtkWidget * widget, GdkEvent * event, gpointer data) { - gtk_widget_destroy(widget); // this will call _window_destroy -} // _window_deleteevent - -/*****************************************************************************/ -static void _window_close(GtkWidget * widget, gpointer data) -{ - // this will call _info_window_destroy if it is info-window - gtk_widget_destroy(GTK_WIDGET(data)); -} // _window_close - -/*****************************************************************************/ -static void _no_edit(GtkWidget * w) -{ - gtk_editable_set_editable(GTK_EDITABLE(w), FALSE); -} // _no_edit - -/*****************************************************************************/ -static GtkWidget *_qq_entry_new() -{ - GtkWidget *entry; - entry = gtk_entry_new(); - gtk_entry_set_max_length(GTK_ENTRY(entry), 255); // set the max length - return entry; -} // _qq_entry_new - -/*****************************************************************************/ -static void _qq_set_entry(GtkWidget * entry, gchar * text) -{ - gchar *text_utf8; - - text_utf8 = qq_to_utf8(text, QQ_CHARSET_DEFAULT); - gtk_entry_set_text(GTK_ENTRY(entry), text_utf8); - - g_free(text_utf8); -} // _qq_set_entry - -/*****************************************************************************/ -static gchar *_qq_get_entry(GtkWidget * entry) -{ - return utf8_to_qq(gtk_entry_get_text(GTK_ENTRY(entry)), QQ_CHARSET_DEFAULT); -} // _qq_get_entry - -/*****************************************************************************/ -static void _qq_set_text(GtkWidget * entry, gchar * text) -{ - gchar *text_utf8; - - text_utf8 = qq_to_utf8(text, QQ_CHARSET_DEFAULT); - gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)), text_utf8, -1); - - g_free(text_utf8); -} // _qq_set_text - -/*****************************************************************************/ -static gchar *_qq_get_text(GtkWidget * entry) -{ - gchar *str, *ret; - GtkTextIter start, end; - - gtk_text_buffer_get_bounds(gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)), &start, &end); - str = gtk_text_buffer_get_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(entry)), &start, &end, FALSE); - ret = utf8_to_qq(str, QQ_CHARSET_DEFAULT); - - return ret; -} // _qq_get_text - -/*****************************************************************************/ -static void _qq_set_image(GtkWidget * entry, gint index) -{ - GdkPixbuf *pixbuf; - - g_return_if_fail(entry != NULL && index >= 0); - - pixbuf = get_face_gdkpixbuf(index); - gtk_image_set_from_pixbuf(GTK_IMAGE(entry), pixbuf); - g_object_unref(pixbuf); - g_object_set_data(G_OBJECT(entry), "user_data", GINT_TO_POINTER(index)); -} // _qq_set_image - - -/*****************************************************************************/ -static void _qq_change_face(GtkWidget * w, gpointer * user_data) -{ - gint index; - change_icon_widgets *change_icon; - - change_icon = (change_icon_widgets *) user_data; - - index = (gint) g_object_get_data(G_OBJECT(w), "user_data"); - - _qq_set_image(change_icon->face, index); - _window_close(NULL, change_icon->dialog); - - g_free(change_icon); - -} // _qq_change_face - -/*****************************************************************************/ -static GList *_get_list_by_array(gchar ** array, gint size) -{ - gint i; - GList *cbitems; - - cbitems = NULL; - for (i = 0; i < size; i++) - cbitems = g_list_append(cbitems, array[i]); - return cbitems; -} // _get_list_by_array - -/*****************************************************************************/ -static void _qq_set_open_contact_radio(contact_info_window * info_window, gchar * is_open_contact) { - gint open; - GtkWidget **radio; - - open = atoi(is_open_contact); - radio = info_window->open_contact_radio; - - if (open == QQ_CONTACT_OPEN) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE); - else if (open == QQ_CONTACT_ONLY_FRIENDS) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[1]), TRUE); - else - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[2]), TRUE); -} // _qq_set_open_contact_radio - -/*****************************************************************************/ -static void _qq_set_auth_type_radio(contact_info_window * info_window, gchar * auth_type_str) { - gint auth_type; - GtkWidget **radio; - - auth_type = atoi(auth_type_str); - radio = info_window->auth_radio; - - if (auth_type == QQ_AUTH_NO_AUTH) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[0]), TRUE); - else if (auth_type == QQ_AUTH_NEED_AUTH) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[1]), TRUE); - else - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio[2]), TRUE); -} // _qq_set_auth_type_radio - -/*****************************************************************************/ -static void _info_window_destroy(GtkWidget * widget, gpointer data) -{ - GList *list; - qq_data *qd; - GaimConnection *gc; - contact_info_window *info_window; - - gc = (GaimConnection *) data; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - if (QQ_DEBUG) - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Destroy info window.\n"); - qd = (qq_data *) gc->proto_data; - list = qd->contact_info_window; - - while (list) { - info_window = (contact_info_window *) (list->data); - if (info_window->window != widget) - list = list->next; - else { - if (info_window->old_info) - g_strfreev((gchar **) info_window->old_info); - qd->contact_info_window = g_list_remove(qd->contact_info_window, info_window); - g_free(info_window); - break; - } - } // while -} // _info_window_destory - -/*****************************************************************************/ -void qq_contact_info_window_free(qq_data * qd) -{ - gint i; - contact_info_window *info; - - g_return_if_fail(qd != NULL); - - i = 0; - while (qd->contact_info_window) { - info = (contact_info_window *) qd->contact_info_window->data; - // remove the entry before free it - // in some rare cases, system might automatically (stupidly) - // remove the entry from the list when user free the entry, - // then, qd->contact_info_window becomes NULL and it causes crash - qd->contact_info_window = g_list_remove(qd->contact_info_window, info); - if (info->window) - gtk_widget_destroy(info->window); - g_free(info); - i++; - } - gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d conatct_info_window are freed\n", i); -} // qq_contact_info_window_free - -/*****************************************************************************/ -static void _info_window_refresh(GtkWidget * widget, gpointer data) -{ - GaimConnection *gc; - contact_info_window *info_window; - - gc = (GaimConnection *) data; - info_window = (contact_info_window *) - g_object_get_data(G_OBJECT(widget), "user_data"); - - qq_send_packet_get_info(gc, info_window->uid, TRUE); - gtk_widget_set_sensitive(info_window->refresh_button, FALSE); -} // _info_window_refresh - -/*****************************************************************************/ -static void _info_window_change(GtkWidget * widget, gpointer data) -{ - gchar *passwd[3]; - gboolean is_modify_passwd; - guint8 icon, auth_type, open_contact; - qq_data *qd; - GaimAccount *a; - GaimConnection *gc; - contact_info *info; - contact_info_window *info_window; - - gc = (GaimConnection *) data; - a = gc->account; - qd = gc->proto_data; - info_window = (contact_info_window *) - g_object_get_data(G_OBJECT(widget), "user_data"); - info = info_window->old_info; - - is_modify_passwd = FALSE; - passwd[0] = passwd[1] = passwd[2] = NULL; - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->is_modify_passwd))) - is_modify_passwd = TRUE; - - if (is_modify_passwd) { - passwd[0] = _qq_get_entry(info_window->old_password); - passwd[1] = _qq_get_entry(info_window->password[0]); - passwd[2] = _qq_get_entry(info_window->password[1]); - - if (g_ascii_strcasecmp(a->password, passwd[0])) { - gaim_notify_error(gc, _("Error"), _("Old password is wrong"), NULL); - g_free(passwd[0]); - g_free(passwd[1]); - g_free(passwd[2]); - return; - } - if (passwd[1][0] == '\0') { - gaim_notify_error(gc, _("Error"), _("Password can not be empty"), NULL); - g_free(passwd[0]); - g_free(passwd[1]); - g_free(passwd[2]); - return; - } - if (g_ascii_strcasecmp(passwd[1], passwd[2])) { - gaim_notify_error(gc, _("Error"), - _("Confirmed password is not the same as new password"), NULL); - g_free(passwd[0]); - g_free(passwd[1]); - g_free(passwd[2]); - return; - } - if (strlen(passwd[1]) > 16) { - gaim_notify_error(gc, _("Error"), _("Password can not longer than 16 characters"), NULL); - g_free(passwd[0]); - g_free(passwd[1]); - g_free(passwd[2]); - return; - } - } // if (is_modify_passwd) - - icon = (gint) g_object_get_data(G_OBJECT(info_window->face), "user_data"); - - info->face = g_strdup_printf("%d", icon); - info->nick = _qq_get_entry(info_window->nick); - info->age = _qq_get_entry(info_window->age); - info->gender = _qq_get_entry(info_window->gender); - info->country = _qq_get_entry(info_window->country); - info->province = _qq_get_entry(info_window->province); - info->city = _qq_get_entry(info_window->city); - info->email = _qq_get_entry(info_window->email); - info->address = _qq_get_entry(info_window->address); - info->zipcode = _qq_get_entry(info_window->zipcode); - info->tel = _qq_get_entry(info_window->tel); - info->name = _qq_get_entry(info_window->name); - info->college = _qq_get_entry(info_window->college); - info->occupation = _qq_get_entry(info_window->occupation); - info->homepage = _qq_get_entry(info_window->homepage); - info->intro = _qq_get_text(info_window->intro); - - info->blood = - get_index_str_by_name((gchar **) blood_types, - gtk_entry_get_text(GTK_ENTRY(info_window->blood)), blood_types_count); - info->zodiac = - get_index_str_by_name((gchar **) zodiac_names, - gtk_entry_get_text(GTK_ENTRY(info_window->zodiac)), zodiac_names_count); - info->horoscope = - get_index_str_by_name((gchar **) horoscope_names, - gtk_entry_get_text(GTK_ENTRY(info_window->horoscope)), horoscope_names_count); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->auth_radio[0]))) - auth_type = QQ_AUTH_NO_AUTH; - else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->auth_radio[1]))) - auth_type = QQ_AUTH_NEED_AUTH; - else - auth_type = QQ_AUTH_NO_ADD; - - info->auth_type = g_strdup_printf("%d", auth_type); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->open_contact_radio[0]))) - open_contact = QQ_CONTACT_OPEN; - else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->open_contact_radio[1]))) - open_contact = QQ_CONTACT_ONLY_FRIENDS; - else - open_contact = QQ_CONTACT_CLOSE; - - info->is_open_contact = g_strdup_printf("%d", open_contact); - - qq_send_packet_modify_info(gc, info, passwd[1]); - qq_refresh_buddy_and_myself(info, gc); - - gtk_widget_destroy(info_window->window); //close window -} - -/*****************************************************************************/ -static void _info_window_change_face(GtkWidget * widget, GdkEvent * event, contact_info_window * info_window) { - gint i; - GdkPixbuf *pixbuf; - GtkWidget *dialog, *image, *button, *vbox, *smiley_box; - change_icon_widgets *change_icon; - - change_icon = g_new0(change_icon_widgets, 1); - - smiley_box = NULL; - GAIM_DIALOG(dialog); // learned from gtkimhtmltoolbar.c - gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); - gtk_window_set_modal(GTK_WINDOW(dialog), FALSE); - - g_signal_connect(G_OBJECT(dialog), "delete_event", G_CALLBACK(_window_deleteevent), NULL); - - gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); - gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); - - change_icon->dialog = dialog; - change_icon->face = info_window->face; - - vbox = gtk_vbox_new(TRUE, 5); - - for (i = 0; i < 85; i++) { - if (i % 8 == 0) { - smiley_box = gtk_toolbar_new(); - gtk_box_pack_start(GTK_BOX(vbox), smiley_box, TRUE, TRUE, 0); - } - pixbuf = get_face_gdkpixbuf(i * 3); - image = gtk_image_new_from_pixbuf(pixbuf); - g_object_unref(pixbuf); - button = gtk_toolbar_append_item(GTK_TOOLBAR(smiley_box), - NULL, NULL, NULL, image, G_CALLBACK(_qq_change_face), change_icon); - g_object_set_data(G_OBJECT(button), "user_data", GINT_TO_POINTER(i * 3)); - gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); - } // for i - - gtk_container_add(GTK_CONTAINER(dialog), vbox); - gtk_container_set_border_width(GTK_CONTAINER(dialog), 5); - gtk_window_set_title(GTK_WINDOW(dialog), _("Choose my head icon")); - gtk_widget_show_all(dialog); -} // _info_window_change_face - -/*****************************************************************************/ -static void _change_passwd_checkbutton_callback(GtkWidget * widget, contact_info_window * info_window) { - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { - gtk_widget_set_sensitive(info_window->old_password, TRUE); - gtk_widget_set_sensitive(info_window->password[0], TRUE); - gtk_widget_set_sensitive(info_window->password[1], TRUE); - } else { - gtk_widget_set_sensitive(info_window->old_password, FALSE); - gtk_widget_set_sensitive(info_window->password[0], FALSE); - gtk_widget_set_sensitive(info_window->password[1], FALSE); - } -} // _change_passwd_checkbutton_callback - -/*****************************************************************************/ -static GtkWidget *_create_page_basic - (gint is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) { - GdkPixbuf *pixbuf; - GList *cbitems; - GtkWidget *hbox, *pixmap, *frame, *label, *table; - GtkWidget *entry, *combo, *alignment; - GtkWidget *event_box, *qq_show; - GtkTooltips *tooltips; - - tooltips = gtk_tooltips_new(); - - cbitems = NULL; - - hbox = gtk_hbox_new(FALSE, 0); - frame = gtk_frame_new(""); - gtk_container_set_border_width(GTK_CONTAINER(frame), 5); - gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); - - table = gtk_table_new(7, 3, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 2); - gtk_table_set_col_spacings(GTK_TABLE(table), 5); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_container_add(GTK_CONTAINER(frame), table); - - pixbuf = get_face_gdkpixbuf((guint8) strtol(info->face, NULL, 10)); - pixmap = gtk_image_new_from_pixbuf(pixbuf); - info_window->face = pixmap; - - alignment = gtk_alignment_new(0.25, 0, 0, 0); - - // set up icon - if (is_myself) { - g_object_set_data(G_OBJECT(info_window->face), "user_data", - GINT_TO_POINTER(strtol(info->face, NULL, 10))); - event_box = gtk_event_box_new(); - g_signal_connect(G_OBJECT(event_box), "button_press_event", - G_CALLBACK(_info_window_change_face), info_window); - gtk_container_add(GTK_CONTAINER(event_box), pixmap); - gtk_container_add(GTK_CONTAINER(alignment), event_box); - gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), event_box, _("Click to change icon"), NULL); - } else - gtk_container_add(GTK_CONTAINER(alignment), pixmap); - - gtk_table_attach(GTK_TABLE(table), alignment, 2, 3, 0, 2, GTK_FILL, 0, 0, 0); - - // set up qq_show image and event - qq_show = qq_show_default(info); - g_object_set_data(G_OBJECT(qq_show), "user_data", GINT_TO_POINTER((gint) atoi(info->uid))); - - frame = gtk_frame_new(""); - gtk_container_set_border_width(GTK_CONTAINER(frame), 0); - - if (strtol(info->qq_show, NULL, 10) != 0) { // buddy has qq_show - event_box = gtk_event_box_new(); - gtk_container_add(GTK_CONTAINER(frame), event_box); - gtk_container_add(GTK_CONTAINER(event_box), qq_show); - g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(qq_show_get_image), qq_show); - gtk_tooltips_set_tip(GTK_TOOLTIPS(tooltips), event_box, _("Click to refresh"), NULL); - } else // no event_box - gtk_container_add(GTK_CONTAINER(frame), qq_show); - - gtk_table_attach(GTK_TABLE(table), frame, 2, 3, 2, 7, GTK_EXPAND, 0, 0, 0); - - label = gtk_label_new(_("QQid")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Nickname")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->uid_entry = entry; - _qq_set_entry(info_window->uid_entry, info->uid); - gtk_widget_set_size_request(entry, 120, -1); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->nick = entry; - _qq_set_entry(info_window->nick, info->nick); - gtk_widget_set_size_request(entry, 120, -1); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Age")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Gender")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Country/Region")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, 0, 0, 0); - - combo = gtk_combo_new(); - cbitems = _get_list_by_array((gchar **) country_names, country_names_count); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems); - g_list_free(cbitems); - cbitems = NULL; - info_window->country = GTK_COMBO(combo)->entry; - _qq_set_entry(info_window->country, info->country); - gtk_widget_set_size_request(combo, 150, -1); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 4, 5, GTK_FILL, 0, 0, 0); - if (!is_myself) - gtk_widget_set_sensitive(combo, FALSE); - - entry = _qq_entry_new(); - info_window->age = entry; - _qq_set_entry(info_window->age, info->age); - gtk_widget_set_size_request(entry, 40, -1); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_FILL, 0, 0, 0); - - combo = gtk_combo_new(); - cbitems = g_list_append(cbitems, (char *)_("Male")); - cbitems = g_list_append(cbitems, (char *)_("Female")); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems); - g_list_free(cbitems); - cbitems = NULL; - info_window->gender = GTK_COMBO(combo)->entry; - gtk_widget_set_size_request(combo, 60, -1); - _qq_set_entry(info_window->gender, info->gender); - gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, GTK_FILL, 0, 0, 0); - if (!is_myself) - gtk_widget_set_sensitive(combo, FALSE); - - label = gtk_label_new(_("Province")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("City")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7, GTK_FILL, 0, 0, 0); - - combo = gtk_combo_new(); - cbitems = _get_list_by_array((gchar **) province_names, province_names_count); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems); - g_list_free(cbitems); - cbitems = NULL; - info_window->province = GTK_COMBO(combo)->entry; - _qq_set_entry(info_window->province, info->province); - gtk_widget_set_size_request(combo, 150, -1); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 5, 6, GTK_FILL, 0, 0, 0); - if (!is_myself) - gtk_widget_set_sensitive(combo, FALSE); - - entry = _qq_entry_new(); - info_window->city = entry; - gtk_widget_set_size_request(entry, 120, -1); - _qq_set_entry(info_window->city, info->city); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 6, 7, GTK_FILL, 0, 0, 0); - - return hbox; -} // _create_page_basic - -/*****************************************************************************/ -static GtkWidget *_create_page_contact - (int is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) { - GtkWidget *vbox1, *frame; - GtkWidget *hbox1, *entry, *label; - GtkWidget *hbox, *radio, *table; - - hbox = gtk_hbox_new(FALSE, 0); - vbox1 = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0); - - frame = gtk_frame_new(""); - gtk_container_set_border_width(GTK_CONTAINER(frame), 5); - gtk_box_pack_start(GTK_BOX(vbox1), frame, TRUE, TRUE, 0); - - table = gtk_table_new(2, 5, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 2); - gtk_table_set_col_spacings(GTK_TABLE(table), 5); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_container_add(GTK_CONTAINER(frame), table); - - label = gtk_label_new(_("Email")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Address")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Zipcode")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Tel")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Homepage")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->email = entry; - gtk_widget_set_size_request(entry, 240, -1); - _qq_set_entry(info_window->email, info->email); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->address = entry; - _qq_set_entry(info_window->address, info->address); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->zipcode = entry; - _qq_set_entry(info_window->zipcode, info->zipcode); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->tel = entry; - _qq_set_entry(info_window->tel, info->tel); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->homepage = entry; - _qq_set_entry(info_window->homepage, info->homepage); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 4, 5, GTK_FILL, 0, 0, 0); - - frame = gtk_frame_new(_("Above infomation")); - gtk_container_set_border_width(GTK_CONTAINER(frame), 5); - if (!is_myself) - gtk_widget_set_sensitive(frame, FALSE); - gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0); - - hbox1 = gtk_hbox_new(FALSE, 5); - gtk_container_add(GTK_CONTAINER(frame), hbox1); - - radio = gtk_radio_button_new_with_label(NULL, _("Open to all")); - info_window->open_contact_radio[0] = radio; - gtk_box_pack_start(GTK_BOX(hbox1), radio, FALSE, FALSE, 0); - - radio = gtk_radio_button_new_with_label_from_widget - (GTK_RADIO_BUTTON(radio), _("Only accessible by my frineds")); - info_window->open_contact_radio[1] = radio; - gtk_box_pack_start(GTK_BOX(hbox1), radio, FALSE, FALSE, 0); - - radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), _("Close to all")); - info_window->open_contact_radio[2] = radio; - gtk_box_pack_start(GTK_BOX(hbox1), radio, FALSE, FALSE, 0); - - _qq_set_open_contact_radio(info_window, info->is_open_contact); - - return hbox; -} // _create_page_contact - -/*****************************************************************************/ -static GtkWidget *_create_page_details - (int is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) { - GList *cbitems; - GtkWidget *text, *hbox, *frame; - GtkWidget *combo, *table, *label, *entry, *scrolled_window; - - cbitems = NULL; - - hbox = gtk_hbox_new(FALSE, 0); - frame = gtk_frame_new(""); - gtk_container_set_border_width(GTK_CONTAINER(frame), 5); - gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0); - - table = gtk_table_new(4, 4, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 2); - gtk_table_set_col_spacings(GTK_TABLE(table), 5); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_container_add(GTK_CONTAINER(frame), table); - - label = gtk_label_new(_("Real Name")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_(" Zodiac")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_(" Blood Type")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_(" Horoscope")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, 2, 3, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("College")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Career")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Intro")); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->name = entry; - gtk_widget_set_size_request(entry, 120, -1); - _qq_set_entry(info_window->name, info->name); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - info_window->college = entry; - gtk_widget_set_size_request(entry, 120, -1); - _qq_set_entry(info_window->college, info->college); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); - - combo = gtk_combo_new(); - cbitems = _get_list_by_array((gchar **) zodiac_names, zodiac_names_count); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems); - g_list_free(cbitems); - cbitems = NULL; - info_window->zodiac = GTK_COMBO(combo)->entry; - gtk_entry_set_text(GTK_ENTRY(info_window->zodiac), - get_name_by_index_str((gchar **) zodiac_names, info->zodiac, zodiac_names_count)); - gtk_widget_set_size_request(combo, 70, -1); - gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE); - gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 0, 1, GTK_FILL, 0, 0, 0); - if (!is_myself) - gtk_widget_set_sensitive(combo, FALSE); - - combo = gtk_combo_new(); - cbitems = _get_list_by_array((gchar **) blood_types, blood_types_count); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems); - g_list_free(cbitems); - cbitems = NULL; - info_window->blood = GTK_COMBO(combo)->entry; - gtk_entry_set_text(GTK_ENTRY(info_window->blood), - get_name_by_index_str((gchar **) blood_types, info->blood, blood_types_count)); - gtk_widget_set_size_request(combo, 70, -1); - gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE); - gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 1, 2, GTK_FILL, 0, 0, 0); - if (!is_myself) - gtk_widget_set_sensitive(combo, FALSE); - - combo = gtk_combo_new(); - cbitems = _get_list_by_array((gchar **) horoscope_names, horoscope_names_count); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems); - g_list_free(cbitems); - cbitems = NULL; - info_window->horoscope = GTK_COMBO(combo)->entry; - gtk_entry_set_text(GTK_ENTRY(info_window->horoscope), get_name_by_index_str((gchar **) - horoscope_names, - info->horoscope, - horoscope_names_count)); - gtk_widget_set_size_request(combo, 70, -1); - gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(combo)->entry), FALSE); - gtk_table_attach(GTK_TABLE(table), combo, 3, 4, 2, 3, GTK_FILL, 0, 0, 0); - if (!is_myself) - gtk_widget_set_sensitive(combo, FALSE); - - combo = gtk_combo_new(); - cbitems = _get_list_by_array((gchar **) occupation_names, occupation_names_count); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), cbitems); - g_list_free(cbitems); - cbitems = NULL; - info_window->occupation = GTK_COMBO(combo)->entry; - _qq_set_entry(info_window->occupation, info->occupation); - gtk_widget_set_size_request(combo, 120, -1); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 2, 3, GTK_FILL, 0, 0, 0); - if (!is_myself) - gtk_widget_set_sensitive(combo, FALSE); - - text = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); - info_window->intro = text; - gtk_widget_set_size_request(text, -1, 90); - _qq_set_text(info_window->intro, info->intro); - - scrolled_window = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_container_add(GTK_CONTAINER(scrolled_window), text); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2); - gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2); - - gtk_table_attach(GTK_TABLE(table), scrolled_window, 1, 4, 3, 4, GTK_FILL, 0, 0, 0); - return hbox; -} // _create_page_details - -/*****************************************************************************/ -static GtkWidget *_create_page_security - (int is_myself, contact_info * info, GaimConnection * gc, contact_info_window * info_window) { - GtkWidget *hbox, *frame, *vbox1, *vbox2; - GtkWidget *entry, *table, *label, *check_button; - GtkWidget *radio, *alignment; - - hbox = gtk_hbox_new(FALSE, 0); - vbox1 = gtk_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0); - - frame = gtk_frame_new(_("Change Password")); - gtk_container_set_border_width(GTK_CONTAINER(frame), 5); - gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0); - - table = gtk_table_new(3, 3, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 2); - gtk_table_set_col_spacings(GTK_TABLE(table), 5); - gtk_container_set_border_width(GTK_CONTAINER(table), 5); - gtk_container_add(GTK_CONTAINER(frame), table); - - label = gtk_label_new(_("Old Passwd")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); - - check_button = gtk_check_button_new_with_label(_("I wanna change")); - info_window->is_modify_passwd = check_button; - g_signal_connect(G_OBJECT(check_button), "toggled", - G_CALLBACK(_change_passwd_checkbutton_callback), info_window); - gtk_table_attach(GTK_TABLE(table), check_button, 2, 3, 0, 1, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("New Passwd")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("(less than 16 char)")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2, GTK_FILL, 0, 0, 0); - - label = gtk_label_new(_("Confirm")); - gtk_misc_set_alignment(GTK_MISC(label), 0, .5); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); - gtk_widget_set_sensitive(entry, FALSE); - info_window->old_password = entry; - gtk_widget_set_size_request(entry, 160, -1); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 0, 1, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); - gtk_widget_set_sensitive(entry, FALSE); - info_window->password[0] = entry; - gtk_widget_set_size_request(entry, 160, -1); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 1, 2, GTK_FILL, 0, 0, 0); - - entry = _qq_entry_new(); - gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); - gtk_widget_set_sensitive(entry, FALSE); - info_window->password[1] = entry; - gtk_widget_set_size_request(entry, 160, -1); - gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, GTK_FILL, 0, 0, 0); - - alignment = gtk_alignment_new(0, 0, 0, 0); - gtk_widget_set_size_request(alignment, -1, 5); - gtk_box_pack_start(GTK_BOX(vbox1), alignment, FALSE, FALSE, 0); - - frame = gtk_frame_new(_("Authentication")); - gtk_container_set_border_width(GTK_CONTAINER(frame), 5); - gtk_box_pack_start(GTK_BOX(vbox1), frame, FALSE, FALSE, 0); - - vbox2 = gtk_vbox_new(FALSE, 1); - gtk_container_add(GTK_CONTAINER(frame), vbox2); - - radio = gtk_radio_button_new_with_label(NULL, _("Anyone can add me")); - info_window->auth_radio[0] = radio; - gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0); - - radio = gtk_radio_button_new_with_label_from_widget - (GTK_RADIO_BUTTON(radio), _("User needs to be authenticated to add me")); - info_window->auth_radio[1] = radio; - gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0); - - radio = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio), _("Nobody can add me")); - info_window->auth_radio[2] = radio; - gtk_box_pack_start(GTK_BOX(vbox2), radio, FALSE, FALSE, 0); - - _qq_set_auth_type_radio(info_window, info->auth_type); - - return hbox; -} // _create_page_security - -/*****************************************************************************/ -void qq_show_contact_info_dialog(contact_info * info, GaimConnection * gc, contact_info_window * info_window) { - - GaimAccount *a = gc->account; - gboolean is_myself; - GtkWidget *label, *window, *notebook, *vbox, *bbox, *button; - - is_myself = (!strcmp(info->uid, a->username)); - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); -// gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(mainwindow)); //by gfhuang - info_window->window = window; - - // we need to duplicate here, - // as the passed-in info structure will be freed in his function - info_window->old_info = (contact_info *) g_strdupv((gchar **) info); - - /* When the window is given the "delete_event" signal (this is given - * by the window manager, usually by the "close" option, or on the - * titlebar), we ask it to call the delete_event () function - * as defined above. The data passed to the callback - * function is NULL and is ignored in the callback function. - */ - g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(_window_deleteevent), NULL); - - /* Here we connect the "destroy" event to a signal handler. - * This event occurs when we call gtk_widget_destroy() on the window, - * or if we return FALSE in the "delete_event" callback. - */ - g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(_info_window_destroy), gc); - - gtk_window_set_resizable(GTK_WINDOW(window), FALSE); - - if (is_myself) - gtk_window_set_title(GTK_WINDOW(window), _("My Information")); - else - gtk_window_set_title(GTK_WINDOW(window), _("My Buddy's Information")); - gtk_container_set_border_width(GTK_CONTAINER(window), 5); - - vbox = gtk_vbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(window), vbox); - - notebook = gtk_notebook_new(); - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT); - - label = gtk_label_new(_("Basic")); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_basic(is_myself, info, gc, info_window), label); - - label = gtk_label_new(_("Contact")); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_contact(is_myself, info, gc, info_window), label); - - label = gtk_label_new(_("Details")); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_details(is_myself, info, gc, info_window), label); - - if (is_myself) { - label = gtk_label_new(_("Security")); - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), - _create_page_security(is_myself, info, gc, info_window), label); - } - - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); - - bbox = gtk_hbutton_box_new(); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_box_set_spacing(GTK_BOX(bbox), 10); - - button = gtk_button_new_with_label(_("Modify")); - g_object_set_data(G_OBJECT(button), "user_data", (gpointer) info_window); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_info_window_change), gc); - gtk_container_add(GTK_CONTAINER(bbox), button); - - if (is_myself) - gtk_widget_set_sensitive(button, TRUE); - else - gtk_widget_set_sensitive(button, FALSE); - - button = gtk_button_new_with_label(_("Refresh")); - info_window->refresh_button = button; - g_object_set_data(G_OBJECT(button), "user_data", (gpointer) info_window); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_info_window_refresh), gc); - gtk_container_add(GTK_CONTAINER(bbox), button); - - button = gtk_button_new_with_label(_("Close")); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(_window_close), info_window->window); - gtk_container_add(GTK_CONTAINER(bbox), button); - - gtk_box_pack_start(GTK_BOX(vbox), bbox, TRUE, TRUE, 5); - - _no_edit(info_window->uid_entry); // uid entry cannot be changed - if (!is_myself) { - _no_edit(info_window->nick); - _no_edit(info_window->country); - _no_edit(info_window->age); - _no_edit(info_window->gender); - _no_edit(info_window->province); - _no_edit(info_window->city); - _no_edit(info_window->email); - _no_edit(info_window->address); - _no_edit(info_window->zipcode); - _no_edit(info_window->tel); - _no_edit(info_window->name); - _no_edit(info_window->blood); - _no_edit(info_window->college); - _no_edit(info_window->occupation); - _no_edit(info_window->zodiac); - _no_edit(info_window->horoscope); - _no_edit(info_window->homepage); - gtk_text_view_set_editable(GTK_TEXT_VIEW(info_window->intro), FALSE); - } - gtk_widget_show_all(window); -} // qq_show_contact_info_dialog - -/*****************************************************************************/ -void qq_refresh_contact_info_dialog(contact_info * new_info, GaimConnection * gc, contact_info_window * info_window) { - GaimAccount *a; - gboolean is_myself; - contact_info *info; - a = gc->account; - - if (info_window->old_info) - g_strfreev((gchar **) info_window->old_info); - - // we need to duplicate here, - // as the passed-in info structure will be freed in his function - info = (contact_info *) g_strdupv((gchar **) new_info); - info_window->old_info = info; - - is_myself = !(g_ascii_strcasecmp(info->uid, a->username)); - gtk_widget_set_sensitive(info_window->refresh_button, TRUE); - - if (is_myself) { - _qq_set_auth_type_radio(info_window, info->auth_type); - _qq_set_open_contact_radio(info_window, info->is_open_contact); - } - - _qq_set_entry(info_window->uid_entry, info->uid); - _qq_set_entry(info_window->nick, info->nick); - _qq_set_entry(info_window->country, info->country); - _qq_set_entry(info_window->age, info->age); - _qq_set_entry(info_window->gender, info->gender); - _qq_set_entry(info_window->province, info->province); - _qq_set_entry(info_window->city, info->city); - _qq_set_entry(info_window->email, info->email); - _qq_set_entry(info_window->address, info->address); - _qq_set_entry(info_window->zipcode, info->zipcode); - _qq_set_entry(info_window->tel, info->tel); - _qq_set_entry(info_window->name, info->name); - gtk_entry_set_text(GTK_ENTRY(info_window->zodiac), - get_name_by_index_str((gchar **) zodiac_names, info->zodiac, zodiac_names_count)); - gtk_entry_set_text(GTK_ENTRY(info_window->horoscope), get_name_by_index_str((gchar **) - horoscope_names, - info->horoscope, - horoscope_names_count)); - gtk_entry_set_text(GTK_ENTRY(info_window->blood), - get_name_by_index_str((gchar **) blood_types, info->blood, blood_types_count)); - _qq_set_entry(info_window->college, info->college); - _qq_set_entry(info_window->occupation, info->occupation); - _qq_set_entry(info_window->homepage, info->homepage); - - _qq_set_image(info_window->face, (guint8) atoi(info->face)); - - _qq_set_text(info_window->intro, info->intro); -} // qq_refresh_contact_info_dialog - -/*****************************************************************************/ -// END OF FILE
--- a/src/protocols/qq/infodlg.h Mon Jul 24 09:25:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/** - * 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 -/*****************************************************************************/ -#ifndef _QQ_INFODLG_H_ -#define _QQ_INFODLG_H_ - -#include <glib.h> -#include <gtk/gtk.h> -#include "connection.h" // GaimConnection - -#include "buddy_info.h" // contact_info -#include "qq.h" // qq_data - -typedef struct _contact_info_window contact_info_window; - -struct _contact_info_window { - guint32 uid; - GtkWidget *window; - GtkWidget *refresh_button; - GtkWidget *uid_entry, - *face, - *nick, - *country, - *age, - *gender, - *province, - *city, - *email, - *address, *zipcode, *tel, *name, *blood, *college, *occupation, *zodiac, *horoscope, *homepage, *intro; - GtkWidget *open_contact_radio[3]; - GtkWidget *auth_radio[3], *is_modify_passwd, *old_password, *password[2]; - contact_info *old_info; -}; - -void qq_contact_info_window_free(qq_data * qd); - -void qq_show_contact_info_dialog(contact_info * info, GaimConnection * gc, contact_info_window * info_window); -void qq_refresh_contact_info_dialog(contact_info * info, GaimConnection * gc, contact_info_window * info_window); - -#endif -/*****************************************************************************/ -// END OF FILE
--- a/src/protocols/qq/qq.c Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/qq.c Mon Jul 24 13:39:12 2006 +0000 @@ -32,10 +32,8 @@ #include "request.h" #include "accountopt.h" #include "prpl.h" -#include "gtkroomlist.h" -#include "gtklog.h" #include "server.h" -#include "util.h" /* GaimMenuAction, gaim_menu_action_new, gaim2beta2, gfhuang*/ +#include "util.h" /* GaimMenuAction, gaim_menu_action_new */ #include "utils.h" #include "buddy_info.h" @@ -50,7 +48,6 @@ #include "group.h" /* chat_info, etc */ #include "header_info.h" /* qq_get_cmd_desc */ #include "im.h" -#include "infodlg.h" #include "keep_alive.h" #include "ip_location.h" /* qq_ip_get_location */ #include "login_logout.h" @@ -88,48 +85,12 @@ }; const gint tcp_server_amount = (sizeof(tcp_server_list) / sizeof(tcp_server_list[0])); -/*********** Prototypes ***********/ - -static void _qq_login(GaimAccount * account); -static void _qq_close(GaimConnection * gc); -static const gchar *_qq_list_icon(GaimAccount * a, GaimBuddy * b); -static gchar *_qq_status_text(GaimBuddy *b); -static void _qq_tooltip_text(GaimBuddy *b, GString *tooltip, gboolean full); -static void _qq_list_emblems(GaimBuddy * b, const char **se, const char **sw, const char **nw, const char **ne); -static GList *_qq_away_states(GaimAccount *ga); -static void _qq_set_away(GaimAccount *account, GaimStatus *status); -static gint _qq_send_im(GaimConnection * gc, const gchar * who, const gchar * message, GaimMessageFlags flags); -static int _qq_chat_send(GaimConnection *gc, int channel, const char *message, GaimMessageFlags flags); -static void _qq_get_info(GaimConnection * gc, const gchar * who); -static void _qq_menu_get_my_info(GaimPluginAction * action); -//static void _qq_menu_block_buddy(GaimBlistNode * node); -static void _qq_menu_show_login_info(GaimPluginAction * action); -static void _qq_menu_show_about(GaimPluginAction * action); -static void _qq_menu_any_cmd_send_cb(GaimConnection * gc, GaimRequestFields * fields); -static void _qq_menu_any_cmd(GaimPluginAction * action); -static void _qq_menu_locate_ip_cb(GaimConnection * gc, GaimRequestFields * fields); -static void _qq_menu_locate_ip(GaimPluginAction *action); -static void _qq_menu_search_or_add_permanent_group(GaimPluginAction * action); -static void _qq_menu_create_permanent_group(GaimPluginAction * action); -static void _qq_menu_unsubscribe_group(GaimBlistNode * node); -static void _qq_menu_manage_group(GaimBlistNode * node); -static void _qq_menu_show_system_message(GaimPluginAction *action); -//static void _qq_menu_send_file(GaimBlistNode * node, gpointer ignored); -static GList *_qq_actions(GaimPlugin * plugin, gpointer context); -static GList *_qq_chat_menu(GaimBlistNode *node); -static GList *_qq_buddy_menu(GaimBlistNode * node); -static void _qq_keep_alive(GaimConnection * gc); -static void _qq_get_chat_buddy_info(GaimConnection * gc, gint channel, const gchar * who); -static gchar *_qq_get_chat_buddy_real_name(GaimConnection * gc, gint channel, const gchar * who); -//static GaimPluginPrefFrame *get_plugin_pref_frame(GaimPlugin * plugin); -static void init_plugin(GaimPlugin * plugin); - static void _qq_login(GaimAccount * account) { const gchar *qq_server, *qq_port; qq_data *qd; GaimConnection *gc; - GaimPresence *presence; //gfhuang + GaimPresence *presence; gboolean login_hidden, use_tcp; g_return_if_fail(account != NULL); @@ -145,7 +106,6 @@ qq_server = gaim_account_get_string(account, "server", NULL); qq_port = gaim_account_get_string(account, "port", NULL); use_tcp = gaim_account_get_bool(account, "use_tcp", FALSE); -// login_hidden = gaim_account_get_bool(account, "hidden", FALSE); gfhuang presence = gaim_account_get_presence(account); login_hidden = gaim_presence_is_status_primitive_active(presence, GAIM_STATUS_INVISIBLE); @@ -183,19 +143,27 @@ /* returns the icon name for a buddy or protocol */ static const gchar *_qq_list_icon(GaimAccount * a, GaimBuddy * b) { + /* XXX temp commented out until we figure out what to do with + * status icons */ + /* gchar *filename; qq_buddy *q_bud; gchar icon_suffix; + */ /* do not use g_return_val_if_fail, as it is not assertion */ if (b == NULL || b->proto_data == NULL) return "qq"; + /* q_bud = (qq_buddy *) b->proto_data; + icon_suffix = get_suffix_from_status(q_bud->status); filename = get_icon_name(q_bud->icon / 3 + 1, icon_suffix); return filename; + */ + return "qq"; } @@ -203,21 +171,15 @@ static gchar *_qq_status_text(GaimBuddy *b) { qq_buddy *q_bud; -// gboolean show_info; GString *status; gchar *ret; -// show_info = gaim_prefs_get_bool("/plugins/prpl/qq/show_status_by_icon"); -// if (!show_info) -// return NULL; - q_bud = (qq_buddy *) b->proto_data; if (q_bud == NULL) return NULL; status = g_string_new(""); - //by gfhuang switch(q_bud->status) { case QQ_BUDDY_OFFLINE: g_string_append(status, "My Offline"); @@ -270,19 +232,19 @@ static void _qq_tooltip_text(GaimBuddy *b, GString *tooltip, gboolean full) { qq_buddy *q_bud; - gchar *country, *country_utf8, *city, *city_utf8; - guint32 ip_value; + //gchar *country, *country_utf8, *city, *city_utf8; + //guint32 ip_value; gchar *ip_str; g_return_if_fail(b != NULL); q_bud = (qq_buddy *) b->proto_data; - g_return_if_fail(q_bud != NULL); + //g_return_if_fail(q_bud != NULL); -// if (is_online(q_bud->status)) //disable by gfhuang + if (GAIM_BUDDY_IS_ONLINE(b) && q_bud != NULL) { + /* ip_value = ntohl(*(guint32 *) (q_bud->ip)); -// tooltip = g_string_new(""); beta2, gfhuang if (qq_ip_get_location(ip_value, &country, &city)) { country_utf8 = qq_to_utf8(country, QQ_CHARSET_DEFAULT); city_utf8 = qq_to_utf8(city, QQ_CHARSET_DEFAULT); @@ -292,12 +254,13 @@ g_free(country_utf8); g_free(city_utf8); } - //memory leak fixed by gfhuang + */ ip_str = gen_ip_str(q_bud->ip); - g_string_append_printf(tooltip, "\n<b>%s Address:</b> %s:%d", (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) + if (strlen(ip_str) != 0) { + g_string_append_printf(tooltip, "\n<b>%s Address:</b> %s:%d", (q_bud->comm_flag & QQ_COMM_FLAG_TCP_MODE) ? "TCP" : "UDP", ip_str, q_bud->port); + } g_free(ip_str); - //added by gfhuang g_string_append_printf(tooltip, "\n<b>Age:</b> %d", q_bud->age); switch (q_bud->gender) { case QQ_BUDDY_GENDER_GG: @@ -319,25 +282,13 @@ } /* we can show tiny icons on the four corners of buddy icon, */ -static void _qq_list_emblems(GaimBuddy * b, const char **se, const char **sw, const char **nw, const char **ne) { //add const by gfhuang +static void _qq_list_emblems(GaimBuddy * b, const char **se, const char **sw, const char **nw, const char **ne) { // each char ** are refering to filename in pixmaps/gaim/status/default/*png qq_buddy *q_bud = b->proto_data; -// GaimPresence *presence; const char *emblems[4] = { NULL, NULL, NULL, NULL }; int i = 0; -/* presence = gaim_buddy_get_presence(b); - - if (!gaim_presence_is_online(presence)) - emblems[i++] = "offline"; - else if (gaim_presence_is_status_active(presence, "busy") || - gaim_presence_is_status_active(presence, "phone")) - emblems[i++] = "occupied"; - else if (!gaim_presence_is_available(presence)) - emblems[i++] = "away"; -*/ - if (q_bud == NULL) { emblems[0] = "offline"; @@ -351,9 +302,6 @@ if (q_bud->comm_flag & QQ_COMM_FLAG_VIDEO) emblems[i++] = "video"; - -// if (!(user->list_op & (1 << MSN_LIST_RL))) -// emblems[i++] = "nr"; } *se = emblems[0]; @@ -365,7 +313,6 @@ } /* QQ away status (used to initiate QQ away packet) */ -//Rewritten by gfhuang static GList *_qq_away_states(GaimAccount *ga) { GaimStatusType *status; @@ -379,7 +326,7 @@ "away", _("QQ: Away"), FALSE, TRUE, FALSE); types = g_list_append(types, status); - status = gaim_status_type_new_full(GAIM_STATUS_INVISIBLE, /* HIDDEN, change to gaim2beta2, gfhuang */ + status = gaim_status_type_new_full(GAIM_STATUS_INVISIBLE, "invisible", _("QQ: Invisible"), FALSE, TRUE, FALSE); types = g_list_append(types, status); @@ -389,29 +336,10 @@ return types; } -/* -GList *_qq_away_states(GaimConnection * gc) -{ - GList *m; - - g_return_val_if_fail(gc != NULL, NULL); - - m = NULL; - m = g_list_append(m, _("QQ: Available")); - m = g_list_append(m, _("QQ: Away")); - m = g_list_append(m, _("QQ: Invisible")); - m = g_list_append(m, GAIM_AWAY_CUSTOM); - return m; -} -*/ - - /* initiate QQ away with proper change_status packet */ -//void _qq_set_away(GaimConnection * gc, const char *state, const char *msg) static void _qq_set_away(GaimAccount *account, GaimStatus *status) { - // by gfhuang GaimConnection *gc = gaim_account_get_connection(account); const char *state = gaim_status_get_id(status); @@ -422,7 +350,6 @@ qd = (qq_data *) gc->proto_data; - // by gfhuang if(0 == strcmp(state, "available")) qd->status = QQ_SELF_STATUS_AVAILABLE; else if (0 == strcmp(state, "away")) @@ -432,38 +359,11 @@ else qd->status = QQ_SELF_STATUS_AVAILABLE; -/* if (gc->away) { //disable by gfhuang, 1.2006 - g_free(gc->away); - gc->away = NULL; - } - - if (msg) { - qd->status = QQ_SELF_STATUS_CUSTOM; - gc->away = g_strdup(msg); - } else if (state) { - gc->away = g_strdup(""); - if (g_ascii_strcasecmp(state, _("QQ: Available")) == 0) - qd->status = QQ_SELF_STATUS_AVAILABLE; - else if (g_ascii_strcasecmp(state, _("QQ: Away")) == 0) - qd->status = QQ_SELF_STATUS_AWAY; - else if (g_ascii_strcasecmp(state, _("QQ: Invisible")) == 0) - qd->status = QQ_SELF_STATUS_INVISIBLE; - else if (g_ascii_strcasecmp(state, GAIM_AWAY_CUSTOM) == 0) { - if (gc->is_idle) - qd->status = QQ_SELF_STATUS_IDLE; - else - qd->status = QQ_SELF_STATUS_AVAILABLE; - } - } else if (gc->is_idle) - qd->status = QQ_SELF_STATUS_IDLE; - else - qd->status = QQ_SELF_STATUS_AVAILABLE; -*/ qq_send_packet_change_status(gc); } -// IMPORTANT: GaimConvImFlags -> GaimMessageFlags //gfhuang +// IMPORTANT: GaimConvImFlags -> GaimMessageFlags /* send an instance msg to a buddy */ static gint _qq_send_im(GaimConnection * gc, const gchar * who, const gchar * message, GaimMessageFlags flags) { @@ -495,7 +395,7 @@ } /* send a chat msg to a QQ Qun */ -static int _qq_chat_send(GaimConnection *gc, int channel, const char *message, GaimMessageFlags flags/*gfhuang*/) +static int _qq_chat_send(GaimConnection *gc, int channel, const char *message, GaimMessageFlags flags) { gchar *msg, *msg_with_qq_smiley; qq_group *group; @@ -531,11 +431,11 @@ return; } - qq_send_packet_get_info(gc, uid, TRUE); /* need to show up info window */ + qq_send_packet_get_info(gc, uid, TRUE); } /* get my own information */ -static void _qq_menu_get_my_info(GaimPluginAction * action) +static void _qq_menu_modify_my_info(GaimPluginAction * action) { GaimConnection *gc = (GaimConnection *) action->context; qq_data *qd; @@ -543,7 +443,8 @@ g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; - _qq_get_info(gc, uid_to_gaim_name(qd->uid)); + //_qq_get_info(gc, uid_to_gaim_name(qd->uid)); + qq_prepare_modify_info(gc); } /* remove a buddy from my list and remove myself from his list */ @@ -615,136 +516,7 @@ g_string_free(info, TRUE); } -/* show about page about QQ plugin */ -static void _qq_menu_show_about(GaimPluginAction * action) -{ - GaimConnection *gc = (GaimConnection *) action->context; - qq_data *qd; - GString *info; - gchar *head; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - qd = (qq_data *) gc->proto_data; - info = g_string_new("<html><body>\n"); - - g_string_append_printf(info, _("<b>Author</b> : %s<br>\n"), OPENQ_AUTHOR); - g_string_append(info, "Copyright (c) 2004. All rights reserved.<br><br>\n"); - - g_string_append(info, _("<p><b>Code Contributors</b><br>\n")); - g_string_append(info, "gfhuang : patches for gaim 2.0.0beta2<br>\n"); - g_string_append(info, "henryouly : file transfer, udp sock5 proxy and qq_show<br>\n"); - g_string_append(info, "arfankai : fixed bugs in char_conv.c<br>\n"); - g_string_append(info, "rakescar : provided filter for HTML tag<br>\n"); - g_string_append(info, "yyw : improved performance on PPC linux<br>\n"); - g_string_append(info, "lvxiang : provided ip to location original code<br><br>\n"); - - g_string_append(info, _("<p><b>Acknowledgement</b><br>\n")); - g_string_append(info, "Shufeng Tan : http://sf.net/projects/perl-oicq<br>\n"); - g_string_append(info, "Jeff Ye : http://www.sinomac.com<br>\n"); - g_string_append(info, "Hu Zheng : http://forlinux.yeah.net<br><br>\n"); - - g_string_append(info, "<p>And, my parents...\n"); - - g_string_append(info, "</body></html>"); - - head = g_strdup_printf("About QQ Plugin Ver %s", VERSION); - gaim_notify_formatted(gc, NULL, head, NULL, info->str, NULL, NULL); - - g_free(head); - g_string_free(info, TRUE); -} - -/* callback of sending any command to QQ server */ -static void _qq_menu_any_cmd_send_cb(GaimConnection * gc, GaimRequestFields * fields) -{ - GList *groups, *flds; - GaimRequestField *field; - const gchar *id, *value; - gchar *cmd_str, *data_str, **segments; - guint16 cmd; - guint8 *data; - gint i, data_len; - - cmd_str = NULL; - data_str = NULL; - cmd = 0x00; - data = NULL; - data_len = 0; - - for (groups = gaim_request_fields_get_groups(fields); groups; groups = groups->next) { - for (flds = gaim_request_field_group_get_fields(groups->data); flds; flds = flds->next) { - field = flds->data; - id = gaim_request_field_get_id(field); - value = gaim_request_field_string_get_value(field); - - if (!g_ascii_strcasecmp(id, "cmd")) - cmd_str = g_strdup(value); - else if (!g_ascii_strcasecmp(id, "data")) - data_str = g_strdup(value); - } - } - - if (cmd_str != NULL) - cmd = (guint16) strtol(cmd_str, NULL, 16); - - if (data_str != NULL) { - if (NULL == (segments = split_data(data_str, strlen(data_str), ",", 0))) { - g_free(cmd_str); - g_free(data_str); - return; - } - for (data_len = 0; segments[data_len] != NULL; data_len++) {; - } - data = g_newa(guint8, data_len); - for (i = 0; i < data_len; i++) - data[i] = (guint8) strtol(segments[i], NULL, 16); - g_strfreev(segments); - } - - if (cmd && data_len > 0) { - gaim_debug(GAIM_DEBUG_INFO, "QQ", - "Send Any cmd: %s, data dump\n%s", qq_get_cmd_desc(cmd), hex_dump_to_str(data, data_len)); - qq_send_cmd(gc, cmd, TRUE, 0, TRUE, data, data_len); - } - - g_free(cmd_str); - g_free(data_str); -} - -/* send any command with data to QQ server, for testing and debuggin only */ -static void _qq_menu_any_cmd(GaimPluginAction * action) -{ - GaimConnection *gc = (GaimConnection *) action->context; - qq_data *qd; - const char *tips; - GaimRequestField *field; - GaimRequestFields *fields; - GaimRequestFieldGroup *group; - - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - qd = (qq_data *) gc->proto_data; - - tips = _("Separate the value with \",\"\nAllow \"0x\" before each value"); - fields = gaim_request_fields_new(); - group = gaim_request_field_group_new(NULL); - gaim_request_fields_add_group(fields, group); - - /* sample: 0x22 */ - field = gaim_request_field_string_new("cmd", _("CMD Code"), NULL, FALSE); - gaim_request_field_group_add_field(group, field); - /* sample: 0x00,0x15,0xAB */ - /* or: 00,15,AB */ - /* the delimit is ",", allow 0x before the value */ - field = gaim_request_field_string_new("data", _("Raw Data"), NULL, FALSE); - gaim_request_field_group_add_field(group, field); - - gaim_request_fields(gc, _("QQ Any Command"), - _("Send Arbitrary Command"), tips, fields, - _("Send"), G_CALLBACK(_qq_menu_any_cmd_send_cb), _("Cancel"), NULL, gc); -} - -/* added by gfhuang */ +/* static void _qq_menu_locate_ip_cb(GaimConnection * gc, GaimRequestFields * fields) { GList *groups, *flds; @@ -790,7 +562,6 @@ } } -/* added by gfhuang */ static void _qq_menu_locate_ip(GaimPluginAction *action) { GaimConnection *gc = (GaimConnection *) action->context; @@ -811,12 +582,16 @@ _("Locate an IP address"), NULL, fields, _("Check"), G_CALLBACK(_qq_menu_locate_ip_cb), _("Cancel"), NULL, gc); } +*/ +/* static void _qq_menu_search_or_add_permanent_group(GaimPluginAction * action) { gaim_gtk_roomlist_dialog_show(); } +*/ +/* static void _qq_menu_create_permanent_group(GaimPluginAction * action) { GaimConnection *gc = (GaimConnection *) action->context; @@ -827,49 +602,43 @@ "OpenQ", FALSE, FALSE, NULL, _("Create"), G_CALLBACK(qq_group_create_with_name), _("Cancel"), NULL, gc); } +*/ -static void _qq_menu_unsubscribe_group(GaimBlistNode * node) // by gfhuang, gpointer param_components) +/* XXX re-enable this +static void _qq_menu_unsubscribe_group(GaimBlistNode * node) { -// GaimBuddy *buddy; by gfhuang GaimChat *chat = (GaimChat *)node; GaimConnection *gc = gaim_account_get_connection(chat->account); GHashTable *components = chat -> components; -// GHashTable *components = (GHashTable *) param_components; -// g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); bug! found by gfhuang g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); -// buddy = (GaimBuddy *) node; -// gc = gaim_account_get_connection(buddy->account); - g_return_if_fail(gc != NULL && components != NULL); qq_group_exit(gc, components); } -static void _qq_menu_manage_group(GaimBlistNode * node) // by gfhuang, gpointer param_components) +// XXX re-enable this +static void _qq_menu_manage_group(GaimBlistNode * node) { -// GaimBuddy *buddy; by gfhuang GaimChat *chat = (GaimChat *)node; GaimConnection *gc = gaim_account_get_connection(chat->account); GHashTable *components = chat -> components; -// GHashTable *components = (GHashTable *) param_components; -// g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); bug! found by gfhuang g_return_if_fail(GAIM_BLIST_NODE_IS_CHAT(node)); -// buddy = (GaimBuddy *) node; -// gc = gaim_account_get_connection(buddy->account); - g_return_if_fail(gc != NULL && components != NULL); qq_group_manage_group(gc, components); } +*/ +/* static void _qq_menu_show_system_message(GaimPluginAction *action) { GaimConnection *gc = (GaimConnection *) action->context; g_return_if_fail ( gc != NULL ); gaim_gtk_log_show(GAIM_LOG_IM, "systemim", gaim_connection_get_account(gc)); } +*/ /* TODO: re-enable this static void _qq_menu_send_file(GaimBlistNode * node, gpointer ignored) @@ -896,61 +665,61 @@ GaimPluginAction *act; m = NULL; - act = gaim_plugin_action_new(_("Modify My Information"), _qq_menu_get_my_info); + act = gaim_plugin_action_new(_("Modify My Information"), _qq_menu_modify_my_info); m = g_list_append(m, act); act = gaim_plugin_action_new(_("Show Login Information"), _qq_menu_show_login_info); m = g_list_append(m, act); + /* XXX consider re-enabling this act = gaim_plugin_action_new(_("Show System Message"), _qq_menu_show_system_message); m = g_list_append(m, act); + */ - act = gaim_plugin_action_new(_("Any QQ Command"), _qq_menu_any_cmd); - m = g_list_append(m, act); - + /* XXX the old group gtk code needs to moved to the gaim UI before this can be used act = gaim_plugin_action_new(_("Qun: Search a permanent Qun"), _qq_menu_search_or_add_permanent_group); m = g_list_append(m, act); act = gaim_plugin_action_new(_("Qun: Create a permanent Qun"), _qq_menu_create_permanent_group); m = g_list_append(m, act); + */ + /* XXX consider re-enabling this act = gaim_plugin_action_new(_("Locate an IP"), _qq_menu_locate_ip); m = g_list_append(m, act); + */ - act = gaim_plugin_action_new(_("About QQ Plugin"), _qq_menu_show_about); - m = g_list_append(m, act); - return m; } /* chat-related (QQ Qun) menu shown up with right-click */ -static GList *_qq_chat_menu(GaimBlistNode *node) //gfhuang +/* XXX re-enable this +static GList *_qq_chat_menu(GaimBlistNode *node) { GList *m; GaimMenuAction *act; m = NULL; - act = gaim_menu_action_new(_("Exit this QQ Qun"), GAIM_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL); //add NULL by gfhuang + act = gaim_menu_action_new(_("Exit this QQ Qun"), GAIM_CALLBACK(_qq_menu_unsubscribe_group), NULL, NULL); m = g_list_append(m, act); - act = gaim_menu_action_new(_("Show Details"), GAIM_CALLBACK(_qq_menu_manage_group), NULL, NULL); //add NULL by gfhuang + act = gaim_menu_action_new(_("Show Details"), GAIM_CALLBACK(_qq_menu_manage_group), NULL, NULL); m = g_list_append(m, act); return m; } +*/ /* buddy-related menu shown up with right-click */ +/* XXX re-enable this static GList *_qq_buddy_menu(GaimBlistNode * node) { GList *m; - /*GaimBlistNodeAction->GaimMenuAction, gaim2beta2, gfhuang*/ -// GaimMenuAction *act; - if(GAIM_BLIST_NODE_IS_CHAT(node)) //by gfhuang + if(GAIM_BLIST_NODE_IS_CHAT(node)) return _qq_chat_menu(node); m = NULL; - /*gaim_blist_node_action_new -> gaim_menu_action_new, gaim2beta2, gfhuang */ - +*/ /* TODO : not working, temp commented out by gfhuang act = gaim_menu_action_new(_("Block this buddy"), GAIM_CALLBACK(_qq_menu_block_buddy), NULL, NULL); //add NULL by gfhuang @@ -960,9 +729,10 @@ m = g_list_append(m, act); // } */ - +/* return m; } +*/ static void _qq_keep_alive(GaimConnection * gc) @@ -980,8 +750,7 @@ group = (qq_group *) list->data; if (group->my_status == QQ_GROUP_MEMBER_STATUS_IS_MEMBER || group->my_status == QQ_GROUP_MEMBER_STATUS_IS_ADMIN) -// no need to get info time and time again, online members enough, gfhuang -// qq_send_cmd_group_get_group_info(gc, group); + // no need to get info time and time again, online members enough qq_send_cmd_group_get_online_member(gc, group); list = list->next; @@ -1018,49 +787,6 @@ gaim_notify_warning(gc, NULL, _("This function has not be implemented yet"), _("Please wait for new version")); } -/* -static GaimPluginPrefFrame *get_plugin_pref_frame(GaimPlugin * plugin) -{ - GaimPluginPrefFrame *frame; - GaimPluginPref *ppref; - - frame = gaim_plugin_pref_frame_new(); - - ppref = gaim_plugin_pref_new_with_label(_("Convert IP to location")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/qq/ipfile", _("IP file")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_label(_("Display Options")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_name_and_label - ("/plugins/prpl/qq/show_status_by_icon", _("Show gender/age information beside buddy icons")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_name_and_label - ("/plugins/prpl/qq/show_fake_video", _("Fake an video for GAIM QQ (re-login to activate)")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_label(_("System Options")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_name_and_label - ("/plugins/prpl/qq/prompt_for_missing_packet", _("Prompt user for actions if there are missing packets")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_name_and_label - ("/plugins/prpl/qq/prompt_group_msg_on_recv", _("Pop up Qun chat window when receive Qun message")); - gaim_plugin_pref_frame_add(frame, ppref); - - ppref = gaim_plugin_pref_new_with_name_and_label("/plugins/prpl/qq/datadir", _("OpenQ installed directory")); - gaim_plugin_pref_frame_add(frame, ppref); - - return frame; -} -*/ - GaimPlugin *my_protocol = NULL; static GaimPluginProtocolInfo prpl_info = { OPT_PROTO_CHAT_TOPIC | OPT_PROTO_USE_POINTSIZE, @@ -1072,7 +798,7 @@ _qq_status_text, /* status_text */ _qq_tooltip_text, /* tooltip_text */ _qq_away_states, /* away_states */ - _qq_buddy_menu, /* blist_node_menu */ + NULL, /* blist_node_menu */ qq_chat_info, /* chat_info */ NULL, /* chat_info_defaults */ _qq_login, /* login */ @@ -1118,19 +844,13 @@ qq_roomlist_get_list, /* roomlist_get_list */ qq_roomlist_cancel, /* roomlist_cancel */ NULL, /* roomlist_expand_category */ - qq_can_receive_file, /* can_receive_file */ - qq_send_file, /* send_file */ - NULL, /* new xfer, by gfhuang */ - NULL, /* offline_message, gaim2beta2, gfhuang */ - NULL, /* GaimWhiteboardPrplOps, gaim2beta2, gfhuang */ + NULL, /* can_receive_file */ + qq_send_file, /* send_file */ + NULL, /* new xfer */ + NULL, /* offline_message */ + NULL, /* GaimWhiteboardPrplOps */ }; -/* -static GaimPluginUiInfo prefs_info = { - get_plugin_pref_frame -}; -*/ - static GaimPluginInfo info = { GAIM_PLUGIN_MAGIC, GAIM_MAJOR_VERSION,
--- a/src/protocols/qq/qq_proxy.c Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/qq_proxy.c Mon Jul 24 13:39:12 2006 +0000 @@ -37,9 +37,8 @@ #include "packet_parse.h" // MAX_PACKET_SIZE #include "buddy_info.h" // qq_info_query_free #include "buddy_opt.h" // qq_add_buddy_request_free -#include "group_admindlg.h" // qq_qun_info_window_free +#include "char_conv.h" // qq_sending_im_msg_cb #include "group_free.h" // qq_group_packets_free -#include "infodlg.h" // qq_contact_info_window_free #include "login_logout.h" // qq_send_packet_login #include "qq_proxy.h" // #include "recv_core.h" // qq_pending, qq_b4_packets_free @@ -126,6 +125,17 @@ } // _qq_fill_host /*****************************************************************************/ +// set up any finalizing start-up stuff +static void _qq_start_services(GaimConnection *gc) +{ + /* start watching for IMs about to be sent */ + /* + gaim_signal_connect(gaim_conversations_get_handle(), + "sending-im-msg", gc, + GAIM_CALLBACK(qq_sending_im_msg_cb), NULL); + */ +} + // the callback function after socket is built // we setup the qq protocol related configuration here static void _qq_got_login(gpointer data, gint source, GaimInputCondition cond) @@ -171,6 +181,8 @@ gaim_connection_update_progress(gc, buf, 1, QQ_CONNECT_STEPS); g_free(buf); + _qq_start_services(gc); + // qq_send_packet_login(gc); // finally ready to fire qq_send_packet_request_login_token(gc); } // _qq_got_login @@ -206,8 +218,6 @@ qq_group_free_all(qd); qq_add_buddy_request_free(qd); qq_info_query_free(qd); - qq_contact_info_window_free(qd); - qq_qun_info_window_free(qd); qq_buddies_list_free(gc->account /* by gfhuang */, qd); } // _qq_common_clean
--- a/src/protocols/qq/qq_proxy.h Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/qq_proxy.h Mon Jul 24 13:39:12 2006 +0000 @@ -51,6 +51,7 @@ gint qq_connect(GaimAccount * account, const gchar * host, guint16 port, gboolean use_tcp, gboolean is_redirect); void qq_disconnect(GaimConnection * gc); +void _qq_show_packet(gchar * des, gchar * buf, gint len); #endif //_QQ_PROXY_H /*****************************************************************************/
--- a/src/protocols/qq/show.c Mon Jul 24 09:25:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ -/** -* 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 - * - * This code is based on qq_show.c, kindly contributed by herryouly@linuxsir - */ - -// START OF FILE -/*****************************************************************************/ -#include <sys/types.h> // mkdir -#include <sys/stat.h> - -#include "internal.h" // _("get_text") -#include "debug.h" // gaim_debug -#include "notify.h" // gaim_notify_error -#include "util.h" // gaim_url_fetch - -#include "show.h" - -#define QQ_SHOW_SERVER "http://qqshow-user.tencent.com" -#define QQ_SHOW_IMAGE "10/00/00.gif" - -#define QQ_SHOW_CACHE_DIR "qqshow" -#define QQ_SHOW_DEFAULT_IMAGE "qqshow_default.gif" - -#define QQ_SHOW_DEST_X 0 -#define QQ_SHOW_DEST_Y 0 -#define QQ_SHOW_DEST_WIDTH 120 -#define QQ_SHOW_DEST_HEIGHT 180 -#define QQ_SHOW_OFFSET_X -10 -#define QQ_SHOW_OFFSET_Y -35 -#define QQ_SHOW_SCALE_X 0.68 -#define QQ_SHOW_SCALE_Y 0.68 - -enum { - QQ_SHOW_READ, - QQ_SHOW_WRITE, -}; - -/*****************************************************************************/ -// return the local cached QQ show file name for uid -static gchar *_qq_show_get_cache_name(guint32 uid, gint io) -{ - gchar *path, *file, *file_fullname; - - g_return_val_if_fail(uid > 0, NULL); - - path = g_build_filename(gaim_user_dir(), QQ_SHOW_CACHE_DIR, NULL); - if (!g_file_test(path, G_FILE_TEST_EXISTS)) - g_mkdir(path, 0700); - - file = g_strdup_printf("%d.gif", uid); - file_fullname = g_build_filename(path, file, NULL); - - if (io == QQ_SHOW_READ) { - if (!g_file_test(file_fullname, G_FILE_TEST_EXISTS)) { - gaim_debug(GAIM_DEBUG_WARNING, "QQ", "No cached QQ show image for buddy %d\n", uid); - g_free(file_fullname); - file_fullname = - g_build_filename(gaim_prefs_get_string - ("/plugins/prpl/qq/datadir"), - "pixmaps", "gaim", "status", "default", QQ_SHOW_DEFAULT_IMAGE, NULL); - } // if g_file_test - } // if io - - g_free(path); - g_free(file); - return file_fullname; - -} // _qq_show_get_cache_name - -/*****************************************************************************/ -// scale the image to suit my window -static GdkPixbuf *_qq_show_scale_image(GdkPixbuf * pixbuf_src) -{ - GdkPixbuf *pixbuf_dst; - - pixbuf_dst = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, - QQ_SHOW_DEST_WIDTH * QQ_SHOW_SCALE_X, QQ_SHOW_DEST_HEIGHT * QQ_SHOW_SCALE_Y); - - gdk_pixbuf_scale(pixbuf_src, pixbuf_dst, - QQ_SHOW_DEST_X * QQ_SHOW_SCALE_X, - QQ_SHOW_DEST_Y * QQ_SHOW_SCALE_Y, - QQ_SHOW_DEST_WIDTH * QQ_SHOW_SCALE_X, - QQ_SHOW_DEST_HEIGHT * QQ_SHOW_SCALE_Y, - QQ_SHOW_OFFSET_X * QQ_SHOW_SCALE_X, - QQ_SHOW_OFFSET_Y * QQ_SHOW_SCALE_Y, QQ_SHOW_SCALE_X, QQ_SHOW_SCALE_Y, GDK_INTERP_BILINEAR); - - g_object_unref(G_OBJECT(pixbuf_src)); - return pixbuf_dst; -} // qq_show_scale_image - -/*****************************************************************************/ -// keep a local copy of QQ show image to speed up loading -static void _qq_show_cache_image(const gchar * url_ret, size_t len, guint32 uid) -{ - - GError *err; - GIOChannel *cache; - gchar *file; - - g_return_if_fail(uid > 0); - - err = NULL; - file = _qq_show_get_cache_name(uid, QQ_SHOW_WRITE); - cache = g_io_channel_new_file(file, "w", &err); - - if (err != NULL) { // file error - gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Error with QQ show file: %s\n", err->message); - g_error_free(err); - return; - } else { // OK, go ahead - g_io_channel_set_encoding(cache, NULL, NULL); // binary mode - g_io_channel_write_chars(cache, url_ret, len, NULL, &err); - if (err != NULL) { - gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Fail cache QQ show for %d: %s\n", uid, err->message); - g_error_free(err); - } else - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Cache QQ show for %d, done\n", uid); - g_io_channel_shutdown(cache, TRUE, NULL); - } // if err - -} // _qq_show_cache_image - -/*****************************************************************************/ -// display the image for downloaded data -static void qq_show_render_image(void *data, const gchar * url_ret, size_t len) -{ - guint32 uid; - GdkPixbufLoader *pixbuf_loader; - GdkPixbuf *pixbuf_src, *pixbuf_dst; - GtkWidget *qq_show; - - g_return_if_fail(data != NULL && url_ret != NULL && len > 0); - - qq_show = (GtkWidget *) data; - - pixbuf_loader = gdk_pixbuf_loader_new(); - gdk_pixbuf_loader_write(pixbuf_loader, url_ret, len, NULL); - gdk_pixbuf_loader_close(pixbuf_loader, NULL); // finish loading - - pixbuf_src = gdk_pixbuf_loader_get_pixbuf(pixbuf_loader); - - if (pixbuf_src != NULL) { - uid = (guint32) g_object_get_data(G_OBJECT(qq_show), "user_data"); - _qq_show_cache_image(url_ret, len, uid); - pixbuf_dst = _qq_show_scale_image(pixbuf_src); - gtk_image_set_from_pixbuf(GTK_IMAGE(qq_show), pixbuf_dst); - } else { - gaim_notify_error(NULL, NULL, _("Fail getting QQ show image"), NULL); - } // if pixbuf_src - -} // qq_show_render_image - -/*****************************************************************************/ -// show the default image (either local cache or default image) -GtkWidget *qq_show_default(contact_info * info) -{ - guint32 uid; - GdkPixbuf *pixbuf_src; - GError *err; - gchar *file; - - g_return_val_if_fail(info != NULL, NULL); - - uid = strtol(info->uid, NULL, 10); - g_return_val_if_fail(uid != 0, NULL); - - file = _qq_show_get_cache_name(uid, QQ_SHOW_READ); - gaim_debug(GAIM_DEBUG_INFO, "QQ", "Load QQ show image: %s\n", file); - - err = NULL; - pixbuf_src = gdk_pixbuf_new_from_file(file, &err); - - if (err != NULL) { - gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail loaing QQ show: %s\n", err->message); - g_free(file); - return NULL; - } // if err - - g_free(file); - return gtk_image_new_from_pixbuf(_qq_show_scale_image(pixbuf_src)); -} // qq_show_default - -/*****************************************************************************/ -// refresh the image -void qq_show_get_image(GtkWidget * event_box, GdkEventButton * event, gpointer data) -{ - gchar *url; - gint uid; - GtkWidget *qq_show; - - qq_show = (GtkWidget *) data; - g_return_if_fail(qq_show != NULL); - - uid = (gint) g_object_get_data(G_OBJECT(qq_show), "user_data"); - g_return_if_fail(uid != 0); - - url = g_strdup_printf("%s/%d/%s", QQ_SHOW_SERVER, uid, QQ_SHOW_IMAGE); - gaim_url_fetch(url, FALSE, NULL, TRUE, qq_show_render_image, qq_show); - - g_free(url); -} // qq_show_get_image - -/*****************************************************************************/
--- a/src/protocols/qq/show.h Mon Jul 24 09:25:48 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/** -* 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 -/*****************************************************************************/ -#ifndef _QQ_SHOW_H_ -#define _QQ_SHOW_H_ - -#include <glib.h> -#include <gtk/gtk.h> - -#include "buddy_info.h" // contact_info - -GtkWidget *qq_show_default(contact_info * info); - -void qq_show_get_image(GtkWidget * event_box, GdkEventButton * event, gpointer data); - -#endif -/*****************************************************************************/
--- a/src/protocols/qq/utils.c Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/utils.c Mon Jul 24 13:39:12 2006 +0000 @@ -125,8 +125,11 @@ // the return needs to be freed gchar *gen_ip_str(guint8 * ip) { - return g_strdup_printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); -} // gen_ip_str + if (ip == NULL || ip[0] == 0) + return g_strdup_printf(""); + else + return g_strdup_printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); +} // by gfhuang guint8 *str_ip_gen(gchar *str) { @@ -168,36 +171,7 @@ // atoi is not thread-safe and also not async-cancel safe // atoi is deprecated by strtol() and should not be used in new code return (p == NULL) ? 0 : strtol(p + strlen(QQ_NAME_PREFIX), NULL, 10); -} // gaim_name_to_uid - -/*****************************************************************************/ -// convert QQ icon index into its pixbuf -GdkPixbuf *get_face_gdkpixbuf(guint8 index) -{ - gint set, suffix; - gchar *image_name, *file_name; - GdkPixbuf *pixbuf; - const gchar *datadir; - - set = (index / 3) + 1; - suffix = (index % 3) + 1; - - image_name = g_strdup_printf("%s.png", get_icon_name(set, suffix)); - // we need to configure DATADIR in Makefile.am - // st = -DDATADIR=\"$(datadir)\" - datadir = gaim_prefs_get_string("/plugins/prpl/qq/datadir"); - if (datadir == NULL || strlen(datadir) == 0) - file_name = g_build_filename(datadir, "pixmaps", "gaim", "status", "default", image_name, NULL); - else - file_name = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image_name, NULL); - - pixbuf = gdk_pixbuf_new_from_file(file_name, NULL); - - g_free(image_name); - g_free(file_name); - - return pixbuf; -} // get_face_gdkpixbuf +} /*****************************************************************************/ // try to dump the data as GBK @@ -227,6 +201,7 @@ } // try_dump_gbk /*****************************************************************************/ + // dump a chunk of raw data into hex string // the return should be freed later gchar *hex_dump_to_str(const guint8 * buffer, gint bytes) @@ -255,16 +230,16 @@ g_string_append_c(str, '.'); else g_string_append_c(str, ch); - } // for j + } g_string_append_c(str, '\n'); - } // for i + } ret = str->str; // GString can be freed without freeing it character data g_string_free(str, FALSE); return ret; -} // hex_dump_to_str +} /*****************************************************************************/ // ENF OF FILE
--- a/src/protocols/qq/utils.h Mon Jul 24 09:25:48 2006 +0000 +++ b/src/protocols/qq/utils.h Mon Jul 24 13:39:12 2006 +0000 @@ -20,13 +20,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// START OF FILE -/*****************************************************************************/ #ifndef _QQ_MY_UTILS_H_ #define _QQ_MY_UTILS_H_ +#include <stdio.h> #include <glib.h> -#include <gtk/gtk.h> #define QQ_NAME_PREFIX "qq-" @@ -36,19 +34,15 @@ gchar **split_data(guint8 * data, gint len, const gchar * delimit, gint expected_fields); gchar *gen_ip_str(guint8 * ip); -guint8 *str_ip_gen(gchar *str); //by gfhuang +guint8 *str_ip_gen(gchar *str); gchar *uid_to_gaim_name(guint32 uid); guint32 gaim_name_to_uid(const gchar * name); gchar *get_icon_name(gint set, gint suffix); -GdkPixbuf *get_face_gdkpixbuf(guint8 index); - void try_dump_as_gbk(guint8 * data, gint len); gchar *hex_dump_to_str(const guint8 * buf, gint buf_len); #endif -/*****************************************************************************/ -// END OF FILE