14192
|
1 /**
|
|
2 * The QQ2003C protocol plugin
|
|
3 *
|
|
4 * for gaim
|
|
5 *
|
|
6 * Copyright (C) 2004 Puzzlebird
|
|
7 *
|
|
8 * This program is free software; you can redistribute it and/or modify
|
|
9 * it under the terms of the GNU General Public License as published by
|
|
10 * the Free Software Foundation; either version 2 of the License, or
|
|
11 * (at your option) any later version.
|
|
12 *
|
|
13 * This program is distributed in the hope that it will be useful,
|
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16 * GNU General Public License for more details.
|
|
17 *
|
|
18 * You should have received a copy of the GNU General Public License
|
|
19 * along with this program; if not, write to the Free Software
|
|
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
21 */
|
|
22
|
|
23 #include "internal.h"
|
|
24 #include "debug.h"
|
|
25 #include "notify.h"
|
|
26 #include "request.h"
|
|
27
|
|
28 #include "utils.h"
|
|
29 #include "packet_parse.h"
|
|
30 #include "buddy_info.h"
|
|
31 #include "char_conv.h"
|
|
32 #include "crypt.h"
|
|
33 #include "header_info.h"
|
|
34 #include "keep_alive.h"
|
|
35 #include "send_core.h"
|
|
36
|
14611
|
37 #define QQ_PRIMARY_INFORMATION _("Primary Information")
|
|
38 #define QQ_ADDITIONAL_INFORMATION _("Additional Information")
|
|
39 #define QQ_INTRO _("Personal Introduction")
|
|
40 #define QQ_NUMBER _("QQ Number")
|
|
41 #define QQ_NICKNAME _("Nickname")
|
|
42 #define QQ_NAME _("Name")
|
|
43 #define QQ_AGE _("Age")
|
|
44 #define QQ_GENDER _("Gender")
|
|
45 #define QQ_COUNTRY _("Country/Region")
|
|
46 #define QQ_PROVINCE _("Province/State")
|
|
47 #define QQ_CITY _("City")
|
|
48 #define QQ_HOROSCOPE _("Horoscope Symbol")
|
|
49 #define QQ_OCCUPATION _("Occupation")
|
|
50 #define QQ_ZODIAC _("Zodiac Sign")
|
|
51 #define QQ_BLOOD _("Blood Type")
|
|
52 #define QQ_COLLEGE _("College")
|
|
53 #define QQ_EMAIL _("Email")
|
|
54 #define QQ_ADDRESS _("Address")
|
|
55 #define QQ_ZIPCODE _("Zipcode")
|
|
56 #define QQ_CELL _("Cellphone Number")
|
|
57 #define QQ_TELEPHONE _("Phone Number")
|
|
58 #define QQ_HOMEPAGE _("Homepage")
|
14192
|
59
|
14611
|
60 #define QQ_HOROSCOPE_SIZE 13
|
14192
|
61 static const gchar *horoscope_names[] = {
|
14611
|
62 "-", N_("Aquarius"), N_("Pisces"), N_("Aries"), N_("Taurus"),
|
|
63 N_("Gemini"), N_("Cancer"), N_("Leo"), N_("Virgo"), N_("Libra"),
|
|
64 N_("Scorpio"), N_("Sagittarius"), N_("Capricorn")
|
14192
|
65 };
|
|
66
|
14611
|
67 #define QQ_ZODIAC_SIZE 13
|
|
68 static const gchar *zodiac_names[] = {
|
|
69 "-", N_("Rat"), N_("Ox"), N_("Tiger"), N_("Rabbit"),
|
|
70 N_("Dragon"), N_("Snake"), N_("Horse"), N_("Goat"), N_("Monkey"),
|
|
71 N_("Rooster"), N_("Dog"), N_("Pig")
|
14192
|
72 };
|
|
73
|
14611
|
74 #define QQ_BLOOD_SIZE 6
|
|
75 static const gchar *blood_types[] = {
|
|
76 "-", "A", "B", "O", "AB", N_("Other")
|
14192
|
77 };
|
|
78
|
14611
|
79 #define QQ_GENDER_SIZE 2
|
|
80 static const gchar *genders[] = {
|
|
81 N_("Male"),
|
|
82 N_("Female")
|
14192
|
83 };
|
|
84
|
14611
|
85 #define QQ_CONTACT_FIELDS 37
|
14192
|
86
|
14611
|
87 /* There is no user id stored in the reply packet for information query
|
|
88 * we have to manually store the query, so that we know the query source */
|
|
89 typedef struct _qq_info_query {
|
|
90 guint32 uid;
|
|
91 gboolean show_window;
|
|
92 gboolean modify_info;
|
|
93 } qq_info_query;
|
14192
|
94
|
14611
|
95 /* We get an info packet on ourselves before we modify our information.
|
|
96 * Even though not all of the information is modifiable, it still
|
|
97 * all needs to be there when we send out the modify info packet */
|
|
98 typedef struct _modify_info_data {
|
|
99 GaimConnection *gc;
|
|
100 contact_info *info;
|
|
101 } modify_info_data;
|
14192
|
102
|
14611
|
103 /* return -1 as a sentinel */
|
|
104 static gint choice_index(const gchar *value, const gchar **choice, gint choice_size)
|
14192
|
105 {
|
|
106 gint len, i;
|
|
107
|
|
108 len = strlen(value);
|
14611
|
109 if (len > 3 || len == 0) return -1;
|
|
110 for (i = 0; i < len; i++) {
|
14192
|
111 if (!g_ascii_isdigit(value[i]))
|
14611
|
112 return -1;
|
|
113 }
|
|
114 i = strtol(value, NULL, 10);
|
|
115 if (i >= choice_size)
|
|
116 return -1;
|
|
117
|
|
118 return i;
|
|
119 }
|
|
120
|
|
121 /* return should be freed */
|
|
122 static gchar *field_value(const gchar *field, const gchar **choice, gint choice_size)
|
|
123 {
|
|
124 gint index, len;
|
|
125
|
|
126 len = strlen(field);
|
|
127 if (len == 0) {
|
|
128 return NULL;
|
|
129 } else if (choice != NULL) {
|
|
130 /* some choice fields are also customizable */
|
|
131 index = choice_index(field, choice, choice_size);
|
|
132 if (index == -1) {
|
|
133 if (strcmp(field, "-") != 0) {
|
|
134 return qq_to_utf8(field, QQ_CHARSET_DEFAULT);
|
|
135 } else {
|
|
136 return NULL;
|
|
137 }
|
|
138 /* else ASCIIized index */
|
|
139 } else {
|
|
140 if (strcmp(choice[index], "-") != 0)
|
|
141 return g_strdup(choice[index]);
|
|
142 else
|
|
143 return NULL;
|
|
144 }
|
|
145 } else {
|
|
146 if (strcmp(field, "-") != 0) {
|
|
147 return qq_to_utf8(field, QQ_CHARSET_DEFAULT);
|
|
148 } else {
|
|
149 return NULL;
|
|
150 }
|
|
151 }
|
|
152 }
|
|
153
|
|
154 static void append_field_value(GString *info_text, const gchar *field,
|
|
155 const gchar *title, const gchar **choice, gint choice_size)
|
|
156 {
|
|
157 gchar *value = field_value(field, choice, choice_size);
|
|
158
|
|
159 if (value != NULL) {
|
|
160 g_string_append_printf(info_text, "<br /><b>%s:</b> %s", title, value);
|
|
161 g_free(value);
|
|
162 }
|
14192
|
163 }
|
|
164
|
14611
|
165 static GString *info_to_str(const contact_info *info)
|
14192
|
166 {
|
14611
|
167 GString *info_text, *extra_info;
|
|
168 const gchar *intro;
|
|
169 gint len;
|
14192
|
170
|
|
171 info_text = g_string_new("");
|
14611
|
172 g_string_append_printf(info_text, "<b>%s</b><br /><br />", QQ_PRIMARY_INFORMATION);
|
|
173 g_string_append_printf(info_text, "<b>%s:</b> %s", QQ_NUMBER, info->uid);
|
|
174 append_field_value(info_text, info->nick, QQ_NICKNAME, NULL, 0);
|
|
175 append_field_value(info_text, info->name, QQ_NAME, NULL, 0);
|
|
176 append_field_value(info_text, info->age, QQ_AGE, NULL, 0);
|
|
177 append_field_value(info_text, info->gender, QQ_GENDER, genders, QQ_GENDER_SIZE);
|
|
178 append_field_value(info_text, info->country, QQ_COUNTRY, NULL, 0);
|
|
179 append_field_value(info_text, info->province, QQ_PROVINCE, NULL, 0);
|
|
180 append_field_value(info_text, info->city, QQ_CITY, NULL, 0);
|
|
181
|
|
182 extra_info = g_string_new("");
|
|
183 g_string_append_printf(extra_info, "<br /><br /><b>%s</b><br />", QQ_ADDITIONAL_INFORMATION);
|
|
184 len = extra_info->len;
|
|
185 append_field_value(extra_info, info->horoscope, QQ_HOROSCOPE, horoscope_names, QQ_HOROSCOPE_SIZE);
|
|
186 append_field_value(extra_info, info->occupation, QQ_OCCUPATION, NULL, 0);
|
|
187 append_field_value(extra_info, info->zodiac, QQ_ZODIAC, zodiac_names, QQ_ZODIAC_SIZE);
|
|
188 append_field_value(extra_info, info->blood, QQ_BLOOD, blood_types, QQ_BLOOD_SIZE);
|
|
189 append_field_value(extra_info, info->college, QQ_COLLEGE, NULL, 0);
|
|
190 append_field_value(extra_info, info->email, QQ_EMAIL, NULL, 0);
|
|
191 append_field_value(extra_info, info->address, QQ_ADDRESS, NULL, 0);
|
|
192 append_field_value(extra_info, info->zipcode, QQ_ZIPCODE, NULL, 0);
|
|
193 append_field_value(extra_info, info->hp_num, QQ_CELL, NULL, 0);
|
|
194 append_field_value(extra_info, info->tel, QQ_TELEPHONE, NULL, 0);
|
|
195 append_field_value(extra_info, info->homepage, QQ_HOMEPAGE, NULL, 0);
|
|
196 if (len != extra_info->len)
|
|
197 g_string_append(info_text, extra_info->str);
|
|
198 g_string_free(extra_info, TRUE);
|
|
199
|
|
200 intro = field_value(info->intro, NULL, 0);
|
|
201 if (intro) {
|
|
202 g_string_append_printf(info_text, "<br /><br /><b>%s</b><br /><br />", QQ_INTRO);
|
|
203 g_string_append(info_text, intro);
|
|
204 }
|
|
205
|
|
206 /* for debugging */
|
|
207 /*
|
|
208 g_string_append_printf(info_text, "<br /><br /><b>%s</b><br />", "Miscellaneous");
|
|
209 append_field_value(info_text, info->pager_sn, "pager_sn", NULL, 0);
|
|
210 append_field_value(info_text, info->pager_num, "pager_num", NULL, 0);
|
|
211 append_field_value(info_text, info->pager_sp, "pager_sp", NULL, 0);
|
|
212 append_field_value(info_text, info->pager_base_num, "pager_base_num", NULL, 0);
|
|
213 append_field_value(info_text, info->pager_type, "pager_type", NULL, 0);
|
|
214 append_field_value(info_text, info->auth_type, "auth_type", NULL, 0);
|
|
215 append_field_value(info_text, info->unknown1, "unknown1", NULL, 0);
|
|
216 append_field_value(info_text, info->unknown2, "unknown2", NULL, 0);
|
|
217 append_field_value(info_text, info->face, "face", NULL, 0);
|
|
218 append_field_value(info_text, info->hp_type, "hp_type", NULL, 0);
|
|
219 append_field_value(info_text, info->unknown3, "unknown3", NULL, 0);
|
|
220 append_field_value(info_text, info->unknown4, "unknown4", NULL, 0);
|
|
221 append_field_value(info_text, info->unknown5, "unknown5", NULL, 0);
|
|
222 append_field_value(info_text, info->is_open_hp, "is_open_hp", NULL, 0);
|
|
223 append_field_value(info_text, info->is_open_contact, "is_open_contact", NULL, 0);
|
|
224 append_field_value(info_text, info->qq_show, "qq_show", NULL, 0);
|
|
225 append_field_value(info_text, info->unknown6, "unknown6", NULL, 0);
|
|
226 */
|
14192
|
227
|
|
228 return info_text;
|
|
229 }
|
|
230
|
|
231 /* send a packet to get detailed information of uid */
|
14265
|
232 void qq_send_packet_get_info(GaimConnection *gc, guint32 uid, gboolean show_window)
|
14192
|
233 {
|
|
234 qq_data *qd;
|
14519
|
235 gchar uid_str[11];
|
14192
|
236 qq_info_query *query;
|
|
237
|
14629
|
238 g_return_if_fail(uid != 0);
|
14192
|
239
|
|
240 qd = (qq_data *) gc->proto_data;
|
14519
|
241 g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
|
14192
|
242 qq_send_cmd(gc, QQ_CMD_GET_USER_INFO, TRUE, 0, TRUE, (guint8 *) uid_str, strlen(uid_str));
|
|
243
|
|
244 query = g_new0(qq_info_query, 1);
|
|
245 query->uid = uid;
|
|
246 query->show_window = show_window;
|
|
247 query->modify_info = FALSE;
|
|
248 qd->info_query = g_list_append(qd->info_query, query);
|
|
249 }
|
|
250
|
|
251 /* set up the fields requesting personal information and send a get_info packet
|
|
252 * for myself */
|
|
253 void qq_prepare_modify_info(GaimConnection *gc)
|
|
254 {
|
|
255 qq_data *qd;
|
|
256 GList *ql;
|
|
257 qq_info_query *query;
|
|
258
|
|
259 qd = (qq_data *) gc->proto_data;
|
|
260 qq_send_packet_get_info(gc, qd->uid, FALSE);
|
|
261 /* traverse backwards so we get the most recent info_query */
|
|
262 for (ql = g_list_last(qd->info_query); ql != NULL; ql = g_list_previous(ql)) {
|
|
263 query = ql->data;
|
|
264 if (query->uid == qd->uid)
|
|
265 query->modify_info = TRUE;
|
|
266 }
|
|
267 }
|
|
268
|
|
269 /* send packet to modify personal information */
|
14611
|
270 static void qq_send_packet_modify_info(GaimConnection *gc, gchar **segments)
|
14192
|
271 {
|
|
272 gint i;
|
|
273 guint8 *raw_data, *cursor, bar;
|
|
274
|
14629
|
275 g_return_if_fail(segments != NULL);
|
14192
|
276
|
|
277 bar = 0x1f;
|
|
278 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 128);
|
|
279 cursor = raw_data;
|
|
280
|
|
281 create_packet_b(raw_data, &cursor, bar);
|
|
282
|
14611
|
283 /* important! skip the first uid entry */
|
14192
|
284 for (i = 1; i < QQ_CONTACT_FIELDS; i++) {
|
|
285 create_packet_b(raw_data, &cursor, bar);
|
14611
|
286 create_packet_data(raw_data, &cursor, (guint8 *) segments[i], strlen(segments[i]));
|
14192
|
287 }
|
|
288 create_packet_b(raw_data, &cursor, bar);
|
|
289
|
|
290 qq_send_cmd(gc, QQ_CMD_UPDATE_INFO, TRUE, 0, TRUE, raw_data, cursor - raw_data);
|
|
291
|
|
292 }
|
|
293
|
|
294 static void modify_info_cancel_cb(modify_info_data *mid)
|
|
295 {
|
|
296 qq_data *qd;
|
|
297
|
|
298 qd = (qq_data *) mid->gc->proto_data;
|
|
299 qd->modifying_info = FALSE;
|
|
300
|
14611
|
301 g_strfreev((gchar **) mid->info);
|
14192
|
302 g_free(mid);
|
|
303 }
|
|
304
|
14611
|
305 static gchar *parse_field(GList **list, gboolean choice)
|
14192
|
306 {
|
14611
|
307 gchar *value;
|
|
308 GaimRequestField *field;
|
14192
|
309
|
14611
|
310 field = (GaimRequestField *) (*list)->data;
|
|
311 if (choice) {
|
|
312 value = g_strdup_printf("%d", gaim_request_field_choice_get_value(field));
|
14192
|
313 } else {
|
14611
|
314 value = (gchar *) gaim_request_field_string_get_value(field);
|
14192
|
315 if (value == NULL)
|
|
316 value = g_strdup("-");
|
|
317 else
|
|
318 value = utf8_to_qq(value, QQ_CHARSET_DEFAULT);
|
|
319 }
|
14611
|
320 *list = g_list_remove_link(*list, *list);
|
|
321
|
|
322 return value;
|
14192
|
323 }
|
|
324
|
14611
|
325 /* parse fields and send info packet */
|
14192
|
326 static void modify_info_ok_cb(modify_info_data *mid, GaimRequestFields *fields)
|
|
327 {
|
|
328 GaimConnection *gc;
|
|
329 qq_data *qd;
|
14611
|
330 GList *list, *groups;
|
14192
|
331 contact_info *info;
|
|
332
|
|
333 gc = mid->gc;
|
|
334 qd = (qq_data *) gc->proto_data;
|
|
335 qd->modifying_info = FALSE;
|
14611
|
336
|
|
337 info = mid->info;
|
|
338
|
14192
|
339 groups = gaim_request_fields_get_groups(fields);
|
14611
|
340 list = gaim_request_field_group_get_fields(groups->data);
|
|
341 info->uid = parse_field(&list, FALSE);
|
|
342 info->nick = parse_field(&list, FALSE);
|
|
343 info->name = parse_field(&list, FALSE);
|
|
344 info->age = parse_field(&list, FALSE);
|
|
345 info->gender = parse_field(&list, TRUE);
|
|
346 info->country = parse_field(&list, FALSE);
|
|
347 info->province = parse_field(&list, FALSE);
|
|
348 info->city = parse_field(&list, FALSE);
|
|
349 groups = g_list_remove_link(groups, groups);
|
|
350 list = gaim_request_field_group_get_fields(groups->data);
|
|
351 info->horoscope = parse_field(&list, TRUE);
|
|
352 info->occupation = parse_field(&list, FALSE);
|
|
353 info->zodiac = parse_field(&list, TRUE);
|
|
354 info->blood = parse_field(&list, TRUE);
|
|
355 info->college = parse_field(&list, FALSE);
|
|
356 info->email = parse_field(&list, FALSE);
|
|
357 info->address = parse_field(&list, FALSE);
|
|
358 info->zipcode = parse_field(&list, FALSE);
|
|
359 info->hp_num = parse_field(&list, FALSE);
|
|
360 info->tel = parse_field(&list, FALSE);
|
|
361 info->homepage = parse_field(&list, FALSE);
|
|
362 groups = g_list_remove_link(groups, groups);
|
|
363 list = gaim_request_field_group_get_fields(groups->data);
|
|
364 info->intro = parse_field(&list, FALSE);
|
|
365 groups = g_list_remove_link(groups, groups);
|
14192
|
366
|
14611
|
367 qq_send_packet_modify_info(gc, (gchar **) info);
|
|
368
|
|
369 g_strfreev((gchar **) mid->info);
|
14192
|
370 g_free(mid);
|
|
371 }
|
|
372
|
14611
|
373 static GaimRequestFieldGroup *setup_field_group(GaimRequestFields *fields, const gchar *title)
|
14192
|
374 {
|
14611
|
375 GaimRequestFieldGroup *group;
|
14192
|
376
|
14611
|
377 group = gaim_request_field_group_new(title);
|
|
378 gaim_request_fields_add_group(fields, group);
|
|
379
|
|
380 return group;
|
|
381 }
|
14192
|
382
|
14611
|
383 static void add_string_field_to_group(GaimRequestFieldGroup *group,
|
|
384 const gchar *id, const gchar *title, const gchar *value)
|
|
385 {
|
|
386 GaimRequestField *field;
|
|
387 gchar *utf8_value;
|
|
388
|
|
389 utf8_value = qq_to_utf8(value, QQ_CHARSET_DEFAULT);
|
|
390 field = gaim_request_field_string_new(id, title, utf8_value, FALSE);
|
|
391 gaim_request_field_group_add_field(group, field);
|
|
392 g_free(utf8_value);
|
14192
|
393 }
|
|
394
|
14611
|
395 static void add_choice_field_to_group(GaimRequestFieldGroup *group,
|
|
396 const gchar *id, const gchar *title, const gchar *value,
|
|
397 const gchar **choice, gint choice_size)
|
|
398 {
|
|
399 GaimRequestField *field;
|
|
400 gint i, index;
|
|
401
|
|
402 index = choice_index(value, choice, choice_size);
|
|
403 field = gaim_request_field_choice_new(id, title, index);
|
|
404 for (i = 0; i < choice_size; i++)
|
|
405 gaim_request_field_choice_add(field, choice[i]);
|
|
406 gaim_request_field_group_add_field(group, field);
|
|
407 }
|
|
408
|
|
409 /* take the info returned by a get_info packet for myself and set up a request form */
|
|
410 static void create_modify_info_dialogue(GaimConnection *gc, const contact_info *info)
|
14192
|
411 {
|
|
412 qq_data *qd;
|
14611
|
413 GaimRequestFieldGroup *group;
|
14192
|
414 GaimRequestFields *fields;
|
|
415 GaimRequestField *field;
|
|
416 modify_info_data *mid;
|
|
417
|
|
418 /* so we only have one dialog open at a time */
|
|
419 qd = (qq_data *) gc->proto_data;
|
|
420 if (!qd->modifying_info) {
|
|
421 qd->modifying_info = TRUE;
|
|
422
|
|
423 fields = gaim_request_fields_new();
|
|
424
|
14611
|
425 group = setup_field_group(fields, QQ_PRIMARY_INFORMATION);
|
|
426 field = gaim_request_field_string_new("uid", QQ_NUMBER, info->uid, FALSE);
|
|
427 gaim_request_field_group_add_field(group, field);
|
14192
|
428 gaim_request_field_string_set_editable(field, FALSE);
|
14611
|
429 add_string_field_to_group(group, "nick", QQ_NICKNAME, info->nick);
|
|
430 add_string_field_to_group(group, "name", QQ_NAME, info->name);
|
|
431 add_string_field_to_group(group, "age", QQ_AGE, info->age);
|
|
432 add_choice_field_to_group(group, "gender", QQ_GENDER, info->gender, genders, QQ_GENDER_SIZE);
|
|
433 add_string_field_to_group(group, "country", QQ_COUNTRY, info->country);
|
|
434 add_string_field_to_group(group, "province", QQ_PROVINCE, info->province);
|
|
435 add_string_field_to_group(group, "city", QQ_CITY, info->city);
|
|
436 group = setup_field_group(fields, QQ_ADDITIONAL_INFORMATION);
|
|
437 add_choice_field_to_group(group, "horoscope", QQ_HOROSCOPE, info->horoscope, horoscope_names, QQ_HOROSCOPE_SIZE);
|
|
438 add_string_field_to_group(group, "occupation", QQ_OCCUPATION, info->occupation);
|
|
439 add_choice_field_to_group(group, "zodiac", QQ_ZODIAC, info->zodiac, zodiac_names, QQ_ZODIAC_SIZE);
|
|
440 add_choice_field_to_group(group, "blood", QQ_BLOOD, info->blood, blood_types, QQ_BLOOD_SIZE);
|
|
441 add_string_field_to_group(group, "college", QQ_COLLEGE, info->college);
|
|
442 add_string_field_to_group(group, "email", QQ_EMAIL, info->email);
|
|
443 add_string_field_to_group(group, "address", QQ_ADDRESS, info->address);
|
|
444 add_string_field_to_group(group, "zipcode", QQ_ZIPCODE, info->zipcode);
|
|
445 add_string_field_to_group(group, "hp_num", QQ_CELL, info->hp_num);
|
|
446 add_string_field_to_group(group, "tel", QQ_TELEPHONE, info->tel);
|
|
447 add_string_field_to_group(group, "homepage", QQ_HOMEPAGE, info->homepage);
|
14192
|
448
|
14611
|
449 group = setup_field_group(fields, QQ_INTRO);
|
|
450 field = gaim_request_field_string_new("intro", QQ_INTRO, info->intro, TRUE);
|
|
451 gaim_request_field_group_add_field(group, field);
|
|
452
|
|
453 /* prepare unmodifiable info */
|
14192
|
454 mid = g_new0(modify_info_data, 1);
|
|
455 mid->gc = gc;
|
14611
|
456 /* QQ_CONTACT_FIELDS+1 so that the array is NULL-terminated and can be g_strfreev()'ed later */
|
|
457 mid->info = (contact_info *) g_new0(gchar *, QQ_CONTACT_FIELDS+1);
|
|
458 mid->info->pager_sn = g_strdup(info->pager_sn);
|
|
459 mid->info->pager_num = g_strdup(info->pager_num);
|
|
460 mid->info->pager_sp = g_strdup(info->pager_sp);
|
|
461 mid->info->pager_base_num = g_strdup(info->pager_base_num);
|
|
462 mid->info->pager_type = g_strdup(info->pager_type);
|
|
463 mid->info->auth_type = g_strdup(info->auth_type);
|
|
464 mid->info->unknown1 = g_strdup(info->unknown1);
|
|
465 mid->info->unknown2 = g_strdup(info->unknown2);
|
|
466 mid->info->face = g_strdup(info->face);
|
|
467 mid->info->hp_type = g_strdup(info->hp_type);
|
|
468 mid->info->unknown3 = g_strdup(info->unknown3);
|
|
469 mid->info->unknown4 = g_strdup(info->unknown4);
|
|
470 mid->info->unknown5 = g_strdup(info->unknown5);
|
|
471 /* TODO stop hiding these 2 */
|
|
472 mid->info->is_open_hp = g_strdup(info->is_open_hp);
|
|
473 mid->info->is_open_contact = g_strdup(info->is_open_contact);
|
|
474 mid->info->qq_show = g_strdup(info->qq_show);
|
|
475 mid->info->unknown6 = g_strdup(info->unknown6);
|
14192
|
476
|
|
477 gaim_request_fields(gc, _("Modify my information"),
|
|
478 _("Modify my information"), NULL, fields,
|
|
479 _("Update my information"), G_CALLBACK(modify_info_ok_cb),
|
|
480 _("Cancel"), G_CALLBACK(modify_info_cancel_cb),
|
|
481 mid);
|
|
482 }
|
|
483 }
|
|
484
|
|
485 /* process the reply of modify_info packet */
|
|
486 void qq_process_modify_info_reply(guint8 *buf, gint buf_len, GaimConnection *gc)
|
|
487 {
|
|
488 qq_data *qd;
|
|
489 gint len;
|
|
490 guint8 *data;
|
|
491
|
|
492 g_return_if_fail(buf != NULL && buf_len != 0);
|
|
493
|
|
494 qd = (qq_data *) gc->proto_data;
|
|
495 len = buf_len;
|
|
496 data = g_newa(guint8, len);
|
|
497
|
|
498 if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
|
|
499 data[len] = '\0';
|
|
500 if (qd->uid == atoi((gchar *) data)) { /* return should be my uid */
|
|
501 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Update info ACK OK\n");
|
|
502 gaim_notify_info(gc, NULL, _("Your information has been updated"), NULL);
|
|
503 }
|
|
504 } else {
|
|
505 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt modify info reply\n");
|
|
506 }
|
|
507 }
|
|
508
|
|
509 /* after getting info or modify myself, refresh the buddy list accordingly */
|
|
510 void qq_refresh_buddy_and_myself(contact_info *info, GaimConnection *gc)
|
|
511 {
|
|
512 GaimBuddy *b;
|
|
513 qq_data *qd;
|
|
514 qq_buddy *q_bud;
|
|
515 gchar *alias_utf8;
|
|
516
|
|
517 qd = (qq_data *) gc->proto_data;
|
|
518
|
|
519 alias_utf8 = qq_to_utf8(info->nick, QQ_CHARSET_DEFAULT);
|
|
520 if (qd->uid == strtol(info->uid, NULL, 10)) { /* it is me */
|
|
521 qd->my_icon = strtol(info->face, NULL, 10);
|
|
522 if (alias_utf8 != NULL)
|
|
523 gaim_account_set_alias(gc->account, alias_utf8);
|
|
524 }
|
|
525 /* update buddy list (including myself, if myself is the buddy) */
|
|
526 b = gaim_find_buddy(gc->account, uid_to_gaim_name(strtol(info->uid, NULL, 10)));
|
|
527 q_bud = (b == NULL) ? NULL : (qq_buddy *) b->proto_data;
|
|
528 if (q_bud != NULL) { /* I have this buddy */
|
|
529 q_bud->age = strtol(info->age, NULL, 10);
|
|
530 q_bud->gender = strtol(info->gender, NULL, 10);
|
|
531 q_bud->icon = strtol(info->face, NULL, 10);
|
|
532 if (alias_utf8 != NULL)
|
|
533 q_bud->nickname = g_strdup(alias_utf8);
|
|
534 qq_update_buddy_contact(gc, q_bud);
|
|
535 }
|
|
536 g_free(alias_utf8);
|
|
537 }
|
|
538
|
|
539 /* process reply to get_info packet */
|
|
540 void qq_process_get_info_reply(guint8 *buf, gint buf_len, GaimConnection *gc)
|
|
541 {
|
|
542 gint len;
|
|
543 guint8 *data;
|
|
544 gchar **segments;
|
|
545 qq_info_query *query;
|
|
546 qq_data *qd;
|
|
547 contact_info *info;
|
|
548 GList *list, *query_list;
|
|
549 GString *info_text;
|
|
550
|
|
551 g_return_if_fail(buf != NULL && buf_len != 0);
|
|
552
|
|
553 qd = (qq_data *) gc->proto_data;
|
|
554 list = query_list = NULL;
|
|
555 len = buf_len;
|
|
556 data = g_newa(guint8, len);
|
|
557 info = NULL;
|
|
558
|
|
559 if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
|
|
560 if (NULL == (segments = split_data(data, len, "\x1e", QQ_CONTACT_FIELDS)))
|
|
561 return;
|
|
562
|
|
563 info = (contact_info *) segments;
|
14265
|
564 if (qd->modifying_face && strtol(info->face, NULL, 10) != qd->my_icon) {
|
|
565 gchar *icon = g_strdup_printf("%i", qd->my_icon);
|
|
566 qd->modifying_face = FALSE;
|
|
567 memcpy(info->face, icon, 2);
|
14611
|
568 qq_send_packet_modify_info(gc, segments);
|
14265
|
569 g_free(icon);
|
|
570 }
|
|
571
|
14192
|
572 qq_refresh_buddy_and_myself(info, gc);
|
|
573
|
|
574 query_list = qd->info_query;
|
|
575 /* ensure we're processing the right query */
|
|
576 while (query_list) {
|
|
577 query = (qq_info_query *) query_list->data;
|
|
578 if (query->uid == atoi(info->uid)) {
|
|
579 if (query->show_window) {
|
14611
|
580 info_text = info_to_str(info);
|
14192
|
581 gaim_notify_userinfo(gc, info->uid, info_text->str, NULL, NULL);
|
|
582 g_string_free(info_text, TRUE);
|
|
583 } else if (query->modify_info) {
|
14611
|
584 create_modify_info_dialogue(gc, info);
|
14192
|
585 }
|
|
586 qd->info_query = g_list_remove(qd->info_query, qd->info_query->data);
|
|
587 g_free(query);
|
|
588 break;
|
|
589 }
|
|
590 query_list = query_list->next;
|
|
591 }
|
|
592
|
|
593 g_strfreev(segments);
|
|
594 } else {
|
|
595 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Error decrypt get info reply\n");
|
|
596 }
|
|
597 }
|
|
598
|
|
599 void qq_info_query_free(qq_data *qd)
|
|
600 {
|
|
601 gint i;
|
|
602 qq_info_query *p;
|
|
603
|
|
604 g_return_if_fail(qd != NULL);
|
|
605
|
|
606 i = 0;
|
|
607 while (qd->info_query != NULL) {
|
|
608 p = (qq_info_query *) (qd->info_query->data);
|
|
609 qd->info_query = g_list_remove(qd->info_query, p);
|
|
610 g_free(p);
|
|
611 i++;
|
|
612 }
|
|
613 gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d info queries are freed!\n", i);
|
|
614 }
|