comparison libpurple/protocols/qq/buddy_opt.c @ 24048:d57928c9dd8f

2008.09.19 - ccpaging <ccpaging(at)gmail.com> * Rewrite buddy modify info, there is a ticket for this problem * Use ship32 to trans action code between request packet and reply packet process
author SHiNE CsyFeK <csyfek@gmail.com>
date Fri, 19 Sep 2008 14:46:41 +0000
parents bcfc98c7a55f
children bdfcfd71449c
comparison
equal deleted inserted replaced
24047:b72816d1a131 24048:d57928c9dd8f
24 24
25 #include "debug.h" 25 #include "debug.h"
26 #include "internal.h" 26 #include "internal.h"
27 #include "notify.h" 27 #include "notify.h"
28 #include "request.h" 28 #include "request.h"
29 #include "privacy.h"
29 30
30 #include "buddy_info.h" 31 #include "buddy_info.h"
31 #include "buddy_list.h" 32 #include "buddy_list.h"
32 #include "buddy_opt.h" 33 #include "buddy_opt.h"
33 #include "char_conv.h" 34 #include "char_conv.h"
50 QQ_MY_AUTH_APPROVE = 0x30, /* ASCII value of "0" */ 51 QQ_MY_AUTH_APPROVE = 0x30, /* ASCII value of "0" */
51 QQ_MY_AUTH_REJECT = 0x31, /* ASCII value of "1" */ 52 QQ_MY_AUTH_REJECT = 0x31, /* ASCII value of "1" */
52 QQ_MY_AUTH_REQUEST = 0x32, /* ASCII value of "2" */ 53 QQ_MY_AUTH_REQUEST = 0x32, /* ASCII value of "2" */
53 }; 54 };
54 55
55 typedef struct _qq_add_buddy_request {
56 guint32 uid;
57 guint16 seq;
58 } qq_add_buddy_request;
59
60 /* send packet to remove a buddy from my buddy list */ 56 /* send packet to remove a buddy from my buddy list */
61 static void _qq_send_packet_remove_buddy(PurpleConnection *gc, guint32 uid) 57 static void request_buddy_remove(PurpleConnection *gc, guint32 uid)
62 { 58 {
63 gchar uid_str[11]; 59 gchar uid_str[11];
64 60
65 g_return_if_fail(uid > 0); 61 g_return_if_fail(uid > 0);
66 62
67 g_snprintf(uid_str, sizeof(uid_str), "%d", uid); 63 g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
68 qq_send_cmd(gc, QQ_CMD_DEL_BUDDY, (guint8 *) uid_str, strlen(uid_str)); 64 qq_send_cmd(gc, QQ_CMD_BUDDY_REMOVE, (guint8 *) uid_str, strlen(uid_str));
69 } 65 }
70 66
71 /* try to remove myself from someone's buddy list */ 67 /* try to remove myself from someone's buddy list */
72 static void _qq_send_packet_remove_self_from(PurpleConnection *gc, guint32 uid) 68 static void request_buddy_remove_me(PurpleConnection *gc, guint32 uid)
73 { 69 {
74 guint8 raw_data[16] = {0}; 70 guint8 raw_data[16] = {0};
75 gint bytes = 0; 71 gint bytes = 0;
76 72
77 g_return_if_fail(uid > 0); 73 g_return_if_fail(uid > 0);
78 74
79 bytes += qq_put32(raw_data + bytes, uid); 75 bytes += qq_put32(raw_data + bytes, uid);
80 76
81 qq_send_cmd(gc, QQ_CMD_REMOVE_SELF, raw_data, bytes); 77 qq_send_cmd(gc, QQ_CMD_REMOVE_ME, raw_data, bytes);
82 } 78 }
83 79
84 /* try to add a buddy without authentication */ 80 /* try to add a buddy without authentication */
85 static void _qq_send_packet_add_buddy(PurpleConnection *gc, guint32 uid) 81 static void request_buddy_add_no_auth(PurpleConnection *gc, guint32 uid)
86 { 82 {
87 qq_data *qd = (qq_data *) gc->proto_data;
88 qq_add_buddy_request *req;
89 gchar uid_str[11]; 83 gchar uid_str[11];
90 84
91 g_return_if_fail(uid > 0); 85 g_return_if_fail(uid > 0);
92 86
93 /* we need to send the ascii code of this uid to qq server */ 87 /* we need to send the ascii code of this uid to qq server */
94 g_snprintf(uid_str, sizeof(uid_str), "%d", uid); 88 g_snprintf(uid_str, sizeof(uid_str), "%d", uid);
95 qq_send_cmd(gc, QQ_CMD_ADD_BUDDY_WO_AUTH, (guint8 *) uid_str, strlen(uid_str)); 89 qq_send_cmd_mess(gc, QQ_CMD_BUDDY_ADD_NO_AUTH,
96 90 (guint8 *) uid_str, strlen(uid_str), 0, uid);
97 /* must be set after sending packet to get the correct send_seq */
98 req = g_new0(qq_add_buddy_request, 1);
99 req->seq = qd->send_seq;
100 req->uid = uid;
101 qd->add_buddy_request = g_list_append(qd->add_buddy_request, req);
102 } 91 }
103 92
104 /* this buddy needs authentication, text conversion is done at lowest level */ 93 /* this buddy needs authentication, text conversion is done at lowest level */
105 static void _qq_send_packet_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text) 94 static void request_buddy_auth(PurpleConnection *gc, guint32 uid, const gchar response, const gchar *text)
106 { 95 {
107 gchar *text_qq, uid_str[11]; 96 gchar *text_qq, uid_str[11];
108 guint8 bar, *raw_data; 97 guint8 bar, *raw_data;
109 gint bytes = 0; 98 gint bytes = 0;
110 99
123 bytes += qq_put8(raw_data + bytes, bar); 112 bytes += qq_put8(raw_data + bytes, bar);
124 bytes += qq_putdata(raw_data + bytes, (guint8 *) text_qq, strlen(text_qq)); 113 bytes += qq_putdata(raw_data + bytes, (guint8 *) text_qq, strlen(text_qq));
125 g_free(text_qq); 114 g_free(text_qq);
126 } 115 }
127 116
128 qq_send_cmd(gc, QQ_CMD_BUDDY_AUTH, raw_data, bytes); 117 qq_send_cmd(gc, QQ_CMD_BUDDY_ADD_AUTH, raw_data, bytes);
129 } 118 }
130 119
131 static void _qq_send_packet_add_buddy_auth_with_gc_and_uid(gc_and_uid *g, const gchar *text) 120 static void request_buddy_add_auth_cb(qq_add_request *add_req, const gchar *text)
132 { 121 {
133 PurpleConnection *gc; 122 g_return_if_fail(add_req != NULL);
134 guint32 uid; 123 if (add_req->gc == NULL || add_req->uid == 0) {
135 g_return_if_fail(g != NULL); 124 g_free(add_req);
136 125 return;
137 gc = g->gc; 126 }
138 uid = g->uid; 127
139 g_return_if_fail(uid != 0); 128 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REQUEST, text);
140 129 g_free(add_req);
141 _qq_send_packet_buddy_auth(gc, uid, QQ_MY_AUTH_REQUEST, text);
142 g_free(g);
143 } 130 }
144 131
145 /* the real packet to reject and request is sent from here */ 132 /* the real packet to reject and request is sent from here */
146 static void _qq_reject_add_request_real(gc_and_uid *g, const gchar *reason) 133 static void buddy_add_deny_reason_cb(qq_add_request *add_req, const gchar *reason)
147 { 134 {
148 gint uid; 135 g_return_if_fail(add_req != NULL);
149 PurpleConnection *gc; 136 if (add_req->gc == NULL || add_req->uid == 0) {
150 137 g_free(add_req);
151 g_return_if_fail(g != NULL); 138 return;
152 139 }
153 gc = g->gc; 140
154 uid = g->uid; 141 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_REJECT, reason);
155 g_return_if_fail(uid != 0); 142 g_free(add_req);
156
157 _qq_send_packet_buddy_auth(gc, uid, QQ_MY_AUTH_REJECT, reason);
158 g_free(g);
159 } 143 }
160 144
161 /* we approve other's request of adding me as friend */ 145 /* we approve other's request of adding me as friend */
162 void qq_approve_add_request_with_gc_and_uid(gc_and_uid *g) 146 static void buddy_add_authorize_cb(qq_add_request *add_req)
163 { 147 {
164 gint uid; 148 g_return_if_fail(add_req != NULL);
165 PurpleConnection *gc; 149 if (add_req->gc == NULL || add_req->uid != 0) {
166 150 g_free(add_req);
167 g_return_if_fail(g != NULL); 151 return;
168 152 }
169 gc = g->gc; 153
170 uid = g->uid; 154 request_buddy_auth(add_req->gc, add_req->uid, QQ_MY_AUTH_APPROVE, NULL);
171 g_return_if_fail(uid != 0); 155 g_free(add_req);
172
173 _qq_send_packet_buddy_auth(gc, uid, QQ_MY_AUTH_APPROVE, NULL);
174 g_free(g);
175 }
176
177 void qq_do_nothing_with_gc_and_uid(gc_and_uid *g, const gchar *msg)
178 {
179 g_free(g);
180 } 156 }
181 157
182 /* we reject other's request of adding me as friend */ 158 /* we reject other's request of adding me as friend */
183 void qq_reject_add_request_with_gc_and_uid(gc_and_uid *g) 159 static void buddy_add_deny_cb(qq_add_request *add_req)
184 { 160 {
185 gint uid; 161 gint uid;
186 gchar *msg1, *msg2; 162 gchar *msg1, *msg2;
187 PurpleConnection *gc; 163 PurpleConnection *gc;
188 gc_and_uid *g2; 164 gchar *purple_name;
189 gchar *nombre; 165
190 166 g_return_if_fail(add_req != NULL);
191 g_return_if_fail(g != NULL); 167 if (add_req->gc == NULL || add_req->uid == 0) {
192 168 g_free(add_req);
193 gc = g->gc; 169 return;
194 uid = g->uid; 170 }
195 g_return_if_fail(uid != 0); 171
196 172 gc = add_req->gc;
197 g_free(g); 173 uid = add_req->uid;
198
199 g2 = g_new0(gc_and_uid, 1);
200 g2->gc = gc;
201 g2->uid = uid;
202 174
203 msg1 = g_strdup_printf(_("You rejected %d's request"), uid); 175 msg1 = g_strdup_printf(_("You rejected %d's request"), uid);
204 msg2 = g_strdup(_("Message:")); 176 msg2 = g_strdup(_("Message:"));
205 177
206 nombre = uid_to_purple_name(uid); 178 purple_name = uid_to_purple_name(uid);
207 purple_request_input(gc, _("Reject request"), msg1, msg2, 179 purple_request_input(gc, _("Reject request"), msg1, msg2,
208 _("Sorry, you are not my style..."), TRUE, FALSE, 180 _("Sorry, you are not my style..."), TRUE, FALSE,
209 NULL, _("Reject"), G_CALLBACK(_qq_reject_add_request_real), _("Cancel"), NULL, 181 NULL, _("Reject"), G_CALLBACK(buddy_add_deny_reason_cb), _("Cancel"), NULL,
210 purple_connection_get_account(gc), nombre, NULL, 182 purple_connection_get_account(gc), purple_name, NULL,
211 g2); 183 add_req);
212 g_free(nombre); 184 g_free(purple_name);
213 } 185 }
214 186
215 void qq_add_buddy_with_gc_and_uid(gc_and_uid *g) 187 /* suggested by rakescar@linuxsir, can still approve after search */
188 static void buddy_add_check_info_cb(qq_add_request *add_req)
189 {
190 PurpleConnection *gc;
191 guint32 uid;
192 gchar *purple_name;
193
194 g_return_if_fail(add_req != NULL);
195 if (add_req->gc == NULL || add_req->uid == 0) {
196 g_free(add_req);
197 return;
198 }
199
200 gc = add_req->gc;
201 uid = add_req->uid;
202
203 qq_request_buddy_info(gc, uid, 0, QQ_BUDDY_INFO_DISPLAY);
204
205 purple_name = uid_to_purple_name(uid);
206 purple_request_action
207 (gc, NULL, _("Do you approve the requestion?"), "",
208 PURPLE_DEFAULT_ACTION_NONE,
209 purple_connection_get_account(gc), purple_name, NULL,
210 add_req, 2,
211 _("Reject"), G_CALLBACK(buddy_add_deny_cb),
212 _("Approve"), G_CALLBACK(buddy_add_authorize_cb));
213 g_free(purple_name);
214 }
215
216 /* add a buddy and send packet to QQ server
217 * note that when purple load local cached buddy list into its blist
218 * it also calls this funtion, so we have to
219 * define qd->is_login=TRUE AFTER serv_finish_login(gc) */
220 void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
221 {
222 qq_data *qd;
223 guint32 uid;
224 PurpleBuddy *b;
225
226 qd = (qq_data *) gc->proto_data;
227 if (!qd->is_login)
228 return; /* IMPORTANT ! */
229
230 uid = purple_name_to_uid(buddy->name);
231 if (uid > 0) {
232 request_buddy_add_no_auth(gc, uid);
233 return;
234 }
235
236 b = purple_find_buddy(gc->account, buddy->name);
237 if (b != NULL) {
238 purple_blist_remove_buddy(b);
239 }
240 purple_notify_error(gc, NULL, _("QQ Number Error"), _("Invalid QQ Number"));
241 }
242
243 void qq_change_buddys_group(PurpleConnection *gc, const char *who,
244 const char *old_group, const char *new_group)
216 { 245 {
217 gint uid; 246 gint uid;
247 g_return_if_fail(who != NULL);
248
249 if (strcmp(new_group, PURPLE_GROUP_QQ_UNKNOWN) == 0) {
250 if (purple_privacy_check(gc->account, who)) {
251 purple_privacy_deny(gc->account, who, TRUE, FALSE);
252 } else {
253 purple_privacy_deny_add(gc->account, who, TRUE);
254 }
255 return;
256 }
257
258 if (strcmp(old_group, PURPLE_GROUP_QQ_UNKNOWN) != 0) {
259 return;
260 }
261
262 uid = purple_name_to_uid(who);
263 g_return_if_fail(uid != 0);
264
265 purple_privacy_deny_remove(gc->account, who, TRUE);
266
267 purple_debug_info("QQ", "Add unknow buddy %d\n", uid);
268 request_buddy_add_no_auth(gc, uid);
269 }
270
271 static void buddy_cancel_cb(qq_add_request *add_req, const gchar *msg)
272 {
273 g_return_if_fail(add_req != NULL);
274 g_free(add_req);
275 }
276
277 static void buddy_add_no_auth_cb(qq_add_request *add_req)
278 {
279 g_return_if_fail(add_req != NULL);
280 if (add_req->gc == NULL || add_req->uid == 0) {
281 g_free(add_req);
282 return;
283 }
284
285 request_buddy_add_no_auth(add_req->gc, add_req->uid);
286 g_free(add_req);
287 }
288
289 static void buddy_remove_both_cb(qq_add_request *add_req)
290 {
218 PurpleConnection *gc; 291 PurpleConnection *gc;
219 292 qq_data *qd;
220 g_return_if_fail(g != NULL); 293 gchar *purple_name;
221 294 PurpleBuddy *buddy;
222 gc = g->gc; 295 qq_buddy *q_buddy;
223 uid = g->uid; 296
224 g_return_if_fail(uid != 0); 297 g_return_if_fail(add_req != NULL);
225 298 if (add_req->gc == NULL || add_req->uid == 0) {
226 _qq_send_packet_add_buddy(gc, uid); 299 g_free(add_req);
227 g_free(g); 300 return;
228 } 301 }
229 302
230 void qq_block_buddy_with_gc_and_uid(gc_and_uid *g) 303 gc = add_req->gc;
231 { 304 qd = (qq_data *) gc->proto_data;
305
306 request_buddy_remove(gc, add_req->uid);
307 request_buddy_remove_me(gc, add_req->uid);
308
309 purple_name = uid_to_purple_name(add_req->uid);
310 buddy = purple_find_buddy(gc->account, purple_name);
311 if (buddy == NULL) {
312 g_free(add_req);
313 return;
314 }
315
316 q_buddy = (qq_buddy *) buddy->proto_data;
317 if (q_buddy != NULL)
318 qd->buddies = g_list_remove(qd->buddies, q_buddy);
319 else
320 purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name);
321
322 purple_blist_remove_buddy(buddy);
323 g_free(add_req);
324 }
325
326 /* remove a buddy from my list and remove myself from his list */
327 /* TODO: re-enable this */
328 void qq_remove_buddy_and_me(PurpleBlistNode * node)
329 {
330 PurpleConnection *gc;
331 qq_data *qd;
232 guint32 uid; 332 guint32 uid;
233 PurpleConnection *gc; 333 qq_add_request *add_req;
234 PurpleBuddy buddy; 334 PurpleBuddy *buddy;
235 PurpleGroup group; 335 const gchar *who;
236 336
237 g_return_if_fail(g != NULL); 337 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
238 338
239 gc = g->gc; 339 buddy = (PurpleBuddy *) node;
240 uid = g->uid; 340 gc = purple_account_get_connection(buddy->account);
341 qd = (qq_data *) gc->proto_data;
342 if (!qd->is_login)
343 return;
344
345 who = buddy->name;
346 g_return_if_fail(who != NULL);
347
348 uid = purple_name_to_uid(who);
241 g_return_if_fail(uid > 0); 349 g_return_if_fail(uid > 0);
242 350
243 buddy.name = uid_to_purple_name(uid); 351 add_req = g_new0(qq_add_request, 1);
244 group.name = PURPLE_GROUP_QQ_BLOCKED; 352 add_req->gc = gc;
245 353 add_req->uid = uid;
246 qq_remove_buddy(gc, &buddy, &group); 354
247 _qq_send_packet_remove_self_from(gc, uid); 355 purple_request_action(gc, _("Block Buddy"),
356 "Are you sure you want to block this buddy?",
357 NULL,
358 1,
359 purple_connection_get_account(gc), NULL, NULL,
360 add_req, 2,
361 _("Cancel"), G_CALLBACK(buddy_cancel_cb),
362 _("Block"), G_CALLBACK(buddy_remove_both_cb));
248 } 363 }
249 364
250 /* process reply to add_buddy_auth request */ 365 /* process reply to add_buddy_auth request */
251 void qq_process_add_buddy_auth_reply(guint8 *data, gint data_len, PurpleConnection *gc) 366 void qq_process_buddy_add_auth(guint8 *data, gint data_len, PurpleConnection *gc)
252 { 367 {
253 qq_data *qd; 368 qq_data *qd;
254 gchar **segments, *msg_utf8; 369 gchar **segments, *msg_utf8;
255 370
256 g_return_if_fail(data != NULL && data_len != 0); 371 g_return_if_fail(data != NULL && data_len != 0);
269 purple_debug_info("QQ", "Add buddy with auth request OK\n"); 384 purple_debug_info("QQ", "Add buddy with auth request OK\n");
270 } 385 }
271 } 386 }
272 387
273 /* process the server reply for my request to remove a buddy */ 388 /* process the server reply for my request to remove a buddy */
274 void qq_process_remove_buddy_reply(guint8 *data, gint data_len, PurpleConnection *gc) 389 void qq_process_buddy_remove(guint8 *data, gint data_len, PurpleConnection *gc)
275 { 390 {
276 qq_data *qd; 391 qq_data *qd;
277 392
278 g_return_if_fail(data != NULL && data_len != 0); 393 g_return_if_fail(data != NULL && data_len != 0);
279 394
289 purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), _("Remove buddy")); 404 purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), _("Remove buddy"));
290 } 405 }
291 } 406 }
292 407
293 /* process the server reply for my request to remove myself from a buddy */ 408 /* process the server reply for my request to remove myself from a buddy */
294 void qq_process_remove_self_reply(guint8 *data, gint data_len, PurpleConnection *gc) 409 void qq_process_buddy_remove_me(guint8 *data, gint data_len, PurpleConnection *gc)
295 { 410 {
296 qq_data *qd; 411 qq_data *qd;
297 412
298 g_return_if_fail(data != NULL && data_len != 0); 413 g_return_if_fail(data != NULL && data_len != 0);
299 414
300 qd = (qq_data *) gc->proto_data; 415 qd = (qq_data *) gc->proto_data;
301 416
302 if (data[0] != QQ_REMOVE_SELF_REPLY_OK) { 417 if (data[0] != QQ_REMOVE_SELF_REPLY_OK) {
303 /* there is no reason return from server */ 418 /* there is no reason return from server */
304 purple_debug_warning("QQ", "Remove self fails\n"); 419 purple_debug_warning("QQ", "Remove self fails\n");
305 purple_notify_info(gc, _("QQ Buddy"), _("Failed:"), _("Remove from other's buddy list")); 420 purple_notify_info(gc, _("QQ Buddy"), _("Failed:"), _("Remove me from other's buddy list"));
306 } else { /* if reply */ 421 } else { /* if reply */
307 purple_debug_info("QQ", "Remove from a buddy OK\n"); 422 purple_debug_info("QQ", "Remove from a buddy OK\n");
308 /* TODO: Does the user really need to be notified about this? */ 423 #if 0
309 purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), _("Remove from other's buddy list")); 424 purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), _("Remove from other's buddy list"));
310 } 425 #endif
311 } 426 }
312 427 }
313 void qq_process_add_buddy_reply(guint8 *data, gint data_len, guint16 seq, PurpleConnection *gc) 428
314 { 429 void qq_process_buddy_add_no_auth(guint8 *data, gint data_len, guint32 uid, PurpleConnection *gc)
315 qq_data *qd; 430 {
316 gint for_uid; 431 qq_data *qd;
317 gchar *msg, **segments, *uid, *reply; 432 gchar *msg, **segments, *dest_uid, *reply;
318 GList *list;
319 PurpleBuddy *b; 433 PurpleBuddy *b;
320 gc_and_uid *g; 434 qq_add_request *add_req;
321 qq_add_buddy_request *req;
322 gchar *nombre; 435 gchar *nombre;
323 436
324 g_return_if_fail(data != NULL && data_len != 0); 437 g_return_if_fail(data != NULL && data_len != 0);
325 438
326 for_uid = 0; 439 qd = (qq_data *) gc->proto_data;
327 qd = (qq_data *) gc->proto_data; 440
328 441 if (uid == 0) { /* we have no record for this */
329 list = qd->add_buddy_request; 442 purple_debug_error("QQ", "Process buddy add, unknow id\n");
330 while (list != NULL) {
331 req = (qq_add_buddy_request *) list->data;
332 if (req->seq == seq) { /* reply to this */
333 for_uid = req->uid;
334 qd->add_buddy_request = g_list_remove(qd->add_buddy_request, qd->add_buddy_request->data);
335 g_free(req);
336 break;
337 }
338 list = list->next;
339 }
340
341 if (for_uid == 0) { /* we have no record for this */
342 purple_debug_error("QQ", "We have no record for add buddy reply [%d], discard\n", seq);
343 return; 443 return;
344 } else { 444 } else {
345 purple_debug_info("QQ", "Add buddy reply [%d] is for id [%d]\n", seq, for_uid); 445 purple_debug_info("QQ", "Process buddy add for id [%d]\n", uid);
346 } 446 }
347 447
348 if (NULL == (segments = split_data(data, data_len, "\x1f", 2))) 448 if (NULL == (segments = split_data(data, data_len, "\x1f", 2)))
349 return; 449 return;
350 450
351 uid = segments[0]; 451 dest_uid = segments[0];
352 reply = segments[1]; 452 reply = segments[1];
353 if (strtol(uid, NULL, 10) != qd->uid) { /* should not happen */ 453 if (strtol(dest_uid, NULL, 10) != qd->uid) { /* should not happen */
354 purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", uid); 454 purple_debug_error("QQ", "Add buddy reply is to [%s], not me!", dest_uid);
355 g_strfreev(segments); 455 g_strfreev(segments);
356 return; 456 return;
357 } 457 }
358 458
359 if (strtol(reply, NULL, 10) > 0) { /* need auth */ 459 if (strtol(reply, NULL, 10) > 0) { /* need auth */
360 purple_debug_warning("QQ", "Add buddy attempt fails, need authentication\n"); 460 purple_debug_warning("QQ", "Add buddy attempt fails, need authentication\n");
361 nombre = uid_to_purple_name(for_uid); 461 nombre = uid_to_purple_name(uid);
362 b = purple_find_buddy(gc->account, nombre); 462 b = purple_find_buddy(gc->account, nombre);
363 if (b != NULL) 463 if (b != NULL)
364 purple_blist_remove_buddy(b); 464 purple_blist_remove_buddy(b);
365 g = g_new0(gc_and_uid, 1); 465 add_req = g_new0(qq_add_request, 1);
366 g->gc = gc; 466 add_req->gc = gc;
367 g->uid = for_uid; 467 add_req->uid = uid;
368 msg = g_strdup_printf(_("%d needs authentication"), for_uid); 468 msg = g_strdup_printf(_("%d needs authentication"), uid);
369 purple_request_input(gc, NULL, msg, 469 purple_request_input(gc, NULL, msg,
370 _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */ 470 _("Input request here"), /* TODO: Awkward string to fix post string freeze - standardize auth dialogues? -evands */
371 _("Would you be my friend?"), 471 _("Would you be my friend?"),
372 TRUE, FALSE, NULL, _("Send"), 472 TRUE, FALSE, NULL, _("Send"),
373 G_CALLBACK 473 G_CALLBACK(request_buddy_add_auth_cb),
374 (_qq_send_packet_add_buddy_auth_with_gc_and_uid), 474 _("Cancel"), G_CALLBACK(buddy_cancel_cb),
375 _("Cancel"), G_CALLBACK(qq_do_nothing_with_gc_and_uid),
376 purple_connection_get_account(gc), nombre, NULL, 475 purple_connection_get_account(gc), nombre, NULL,
377 g); 476 add_req);
378 g_free(msg); 477 g_free(msg);
379 g_free(nombre); 478 g_free(nombre);
380 } else { /* add OK */ 479 } else { /* add OK */
381 qq_add_buddy_by_recv_packet(gc, for_uid, TRUE, TRUE); 480 qq_create_buddy(gc, uid, TRUE, TRUE);
382 msg = g_strdup_printf(_("Add into %d's buddy list"), for_uid); 481 msg = g_strdup_printf(_("Add into %d's buddy list"), uid);
383 purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), msg); 482 purple_notify_info(gc, _("QQ Buddy"), _("Successed:"), msg);
384 g_free(msg); 483 g_free(msg);
385 } 484 }
386 g_strfreev(segments); 485 g_strfreev(segments);
387 } 486 }
388 487
389 PurpleGroup *qq_get_purple_group(const gchar *group_name) 488 PurpleGroup *qq_create_group(const gchar *group_name)
390 { 489 {
391 PurpleGroup *g; 490 PurpleGroup *g;
392 491
393 g_return_val_if_fail(group_name != NULL, NULL); 492 g_return_val_if_fail(group_name != NULL, NULL);
394 493
402 return g; 501 return g;
403 } 502 }
404 503
405 /* we add new buddy, if the received packet is from someone not in my list 504 /* we add new buddy, if the received packet is from someone not in my list
406 * return the PurpleBuddy that is just created */ 505 * return the PurpleBuddy that is just created */
407 PurpleBuddy *qq_add_buddy_by_recv_packet(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create) 506 PurpleBuddy *qq_create_buddy(PurpleConnection *gc, guint32 uid, gboolean is_known, gboolean create)
408 { 507 {
409 PurpleAccount *a; 508 PurpleBuddy *buddy;
410 PurpleBuddy *b; 509 PurpleGroup *group;
411 PurpleGroup *g;
412 qq_data *qd; 510 qq_data *qd;
413 qq_buddy *q_bud; 511 qq_buddy *q_bud;
414 gchar *name, *group_name; 512 gchar *buddy_name, *group_name;
415 513
416 a = gc->account; 514 g_return_val_if_fail(gc->account != NULL && uid != 0, NULL);
417 qd = (qq_data *) gc->proto_data; 515 qd = (qq_data *) gc->proto_data;
418 g_return_val_if_fail(a != NULL && uid != 0, NULL); 516
419 517 if (is_known) {
420 group_name = is_known ? 518 group_name = g_strdup_printf(PURPLE_GROUP_QQ_FORMAT,
421 g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, purple_account_get_username(a)) : g_strdup(PURPLE_GROUP_QQ_UNKNOWN); 519 purple_account_get_username(gc->account));
422 520 } else {
423 g = qq_get_purple_group(group_name); 521 group_name = g_strdup(PURPLE_GROUP_QQ_UNKNOWN);
424 522 }
425 name = uid_to_purple_name(uid); 523
426 b = purple_find_buddy(gc->account, name); 524 group = qq_create_group(group_name);
525
526 buddy_name = uid_to_purple_name(uid);
527 buddy = purple_find_buddy(gc->account, buddy_name);
427 /* remove old, we can not simply return here 528 /* remove old, we can not simply return here
428 * because there might be old local copy of this buddy */ 529 * because there might be old local copy of this buddy */
429 if (b != NULL) 530 if (buddy != NULL)
430 purple_blist_remove_buddy(b); 531 purple_blist_remove_buddy(buddy);
431 532
432 b = purple_buddy_new(a, name, NULL); 533 buddy = purple_buddy_new(gc->account, buddy_name, NULL);
534 if ( !is_known ) {
535 if (purple_privacy_check(gc->account, buddy_name)) {
536 purple_privacy_deny(gc->account, buddy_name, TRUE, FALSE);
537 } else {
538 purple_privacy_deny_add(gc->account, buddy_name, TRUE);
539 }
540 }
433 541
434 if (!create) 542 if (!create)
435 b->proto_data = NULL; 543 buddy->proto_data = NULL;
436 else { 544 else {
437 q_bud = g_new0(qq_buddy, 1); 545 q_bud = g_new0(qq_buddy, 1);
438 q_bud->uid = uid; 546 q_bud->uid = uid;
439 b->proto_data = q_bud; 547 buddy->proto_data = q_bud;
440 qd->buddies = g_list_append(qd->buddies, q_bud); 548 qd->buddies = g_list_append(qd->buddies, q_bud);
441 qq_send_packet_get_info(gc, q_bud->uid, FALSE); 549 qq_request_buddy_info(gc, qd->uid, 0, 0);
442 qq_request_get_buddies_online(gc, 0, 0); 550 qq_request_get_buddies_online(gc, 0, 0);
443 } 551 qq_request_get_level(gc, qd->uid);
444 552 }
445 purple_blist_add_buddy(b, NULL, g, NULL); 553
446 purple_debug_warning("QQ", "Add new buddy: [%s]\n", name); 554 purple_blist_add_buddy(buddy, NULL, group, NULL);
447 555 purple_debug_warning("QQ", "Add new buddy: [%s]\n", buddy_name);
448 g_free(name); 556
557 g_free(buddy_name);
449 g_free(group_name); 558 g_free(group_name);
450 559
451 return b; 560 return buddy;
452 }
453
454 /* add a buddy and send packet to QQ server
455 * note that when purple load local cached buddy list into its blist
456 * it also calls this funtion, so we have to
457 * define qd->is_login=TRUE AFTER serv_finish_login(gc) */
458 void qq_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
459 {
460 qq_data *qd;
461 guint32 uid;
462 PurpleBuddy *b;
463
464 qd = (qq_data *) gc->proto_data;
465 if (!qd->is_login)
466 return; /* IMPORTANT ! */
467
468 uid = purple_name_to_uid(buddy->name);
469 if (uid > 0)
470 _qq_send_packet_add_buddy(gc, uid);
471 else {
472 b = purple_find_buddy(gc->account, buddy->name);
473 if (b != NULL)
474 purple_blist_remove_buddy(b);
475 purple_notify_error(gc, NULL,
476 _("QQ Number Error"),
477 _("Invalid QQ Number"));
478 }
479 } 561 }
480 562
481 /* remove a buddy and send packet to QQ server accordingly */ 563 /* remove a buddy and send packet to QQ server accordingly */
482 void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) 564 void qq_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
483 { 565 {
484 qq_data *qd; 566 qq_data *qd;
485 PurpleBuddy *b;
486 qq_buddy *q_bud; 567 qq_buddy *q_bud;
487 guint32 uid; 568 guint32 uid;
488 569
489 qd = (qq_data *) gc->proto_data; 570 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
571 g_return_if_fail(buddy != NULL);
572 qd = (qq_data *) gc->proto_data;
573
490 uid = purple_name_to_uid(buddy->name); 574 uid = purple_name_to_uid(buddy->name);
491
492 if (!qd->is_login) 575 if (!qd->is_login)
493 return; 576 return;
494 577
495 if (uid > 0) 578 if (uid > 0) {
496 _qq_send_packet_remove_buddy(gc, uid); 579 request_buddy_remove(gc, uid);
497 580 }
498 b = purple_find_buddy(gc->account, buddy->name); 581
499 if (b != NULL) { 582 q_bud = (qq_buddy *) buddy->proto_data;
500 q_bud = (qq_buddy *) b->proto_data; 583 if (q_bud != NULL)
501 if (q_bud != NULL) 584 qd->buddies = g_list_remove(qd->buddies, q_bud);
502 qd->buddies = g_list_remove(qd->buddies, q_bud); 585 else
503 else 586 purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name);
504 purple_debug_warning("QQ", "We have no qq_buddy record for %s\n", buddy->name); 587
505 /* remove buddy on blist, this does not trigger qq_remove_buddy again 588 /* Do not call purple_blist_remove_buddy,
506 * do this only if the request comes from block request, 589 * otherwise purple segmentation fault */
507 * otherwise purple segmentation fault */ 590 }
508 if (g_ascii_strcasecmp(group->name, PURPLE_GROUP_QQ_BLOCKED) == 0) 591
509 purple_blist_remove_buddy(b); 592 /* free all qq_buddy */
510 }
511 }
512
513 /* free add buddy request queue */
514 void qq_add_buddy_request_free(qq_data *qd)
515 {
516 gint count;
517 qq_add_buddy_request *p;
518
519 count = 0;
520 while (qd->add_buddy_request != NULL) {
521 p = (qq_add_buddy_request *) (qd->add_buddy_request->data);
522 qd->add_buddy_request = g_list_remove(qd->add_buddy_request, p);
523 g_free(p);
524 count++;
525 }
526 if (count > 0) {
527 purple_debug_info("QQ", "%d add buddy requests are freed!\n", count);
528 }
529 }
530
531 /* free up all qq_buddy */
532 void qq_buddies_list_free(PurpleAccount *account, qq_data *qd) 593 void qq_buddies_list_free(PurpleAccount *account, qq_data *qd)
533 { 594 {
534 gint count; 595 gint count;
535 qq_buddy *p; 596 qq_buddy *p;
536 gchar *name; 597 gchar *name;
553 } 614 }
554 if (count > 0) { 615 if (count > 0) {
555 purple_debug_info("QQ", "%d qq_buddy structures are freed!\n", count); 616 purple_debug_info("QQ", "%d qq_buddy structures are freed!\n", count);
556 } 617 }
557 } 618 }
619
620 /* someone wants to add you to his buddy list */
621 static void server_buddy_add_request(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8)
622 {
623 gchar *message, *reason;
624 guint32 uid;
625 qq_add_request *g, *g2;
626 PurpleBuddy *b;
627 gchar *name;
628
629 g_return_if_fail(from != NULL && to != NULL);
630
631 uid = strtol(from, NULL, 10);
632 g = g_new0(qq_add_request, 1);
633 g->gc = gc;
634 g->uid = uid;
635
636 name = uid_to_purple_name(uid);
637
638 /* TODO: this should go through purple_account_request_authorization() */
639 message = g_strdup_printf(_("%s wants to add you [%s] as a friend"), from, to);
640 reason = g_strdup_printf(_("Message: %s"), msg_utf8);
641
642 purple_request_action
643 (gc, NULL, message, reason, PURPLE_DEFAULT_ACTION_NONE,
644 purple_connection_get_account(gc), name, NULL,
645 g, 3,
646 _("Reject"),
647 G_CALLBACK(buddy_add_deny_cb),
648 _("Approve"),
649 G_CALLBACK(buddy_add_authorize_cb),
650 _("Search"), G_CALLBACK(buddy_add_check_info_cb));
651
652 g_free(message);
653 g_free(reason);
654
655 /* XXX: Is this needed once the above goes through purple_account_request_authorization()? */
656 b = purple_find_buddy(gc->account, name);
657 if (b == NULL) { /* the person is not in my list */
658 g2 = g_new0(qq_add_request, 1);
659 g2->gc = gc;
660 g2->uid = strtol(from, NULL, 10);
661 message = g_strdup_printf(_("%s is not in buddy list"), from);
662 purple_request_action(gc, NULL, message,
663 _("Would you add?"), PURPLE_DEFAULT_ACTION_NONE,
664 purple_connection_get_account(gc), name, NULL,
665 g2, 3,
666 _("Cancel"), NULL,
667 _("Add"), G_CALLBACK(buddy_add_no_auth_cb),
668 _("Search"), G_CALLBACK(buddy_add_check_info_cb));
669 g_free(message);
670 }
671
672 g_free(name);
673 }
674
675 /* when you are added by a person, QQ server will send sys message */
676 static void server_buddy_added(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8)
677 {
678 gchar *message;
679 PurpleBuddy *b;
680 guint32 uid;
681 qq_add_request *add_req;
682 gchar *name;
683
684 g_return_if_fail(from != NULL && to != NULL);
685
686 uid = strtol(from, NULL, 10);
687 name = uid_to_purple_name(uid);
688 b = purple_find_buddy(gc->account, name);
689
690 if (b == NULL) { /* the person is not in my list */
691 add_req = g_new0(qq_add_request, 1);
692 add_req->gc = gc;
693 add_req->uid = uid; /* only need to get value */
694 message = g_strdup_printf(_("You have been added by %s"), from);
695 purple_request_action(gc, NULL, message,
696 _("Would you like to add him?"),
697 PURPLE_DEFAULT_ACTION_NONE,
698 purple_connection_get_account(gc), name, NULL,
699 add_req, 3,
700 _("Cancel"), G_CALLBACK(buddy_cancel_cb),
701 _("Add"), G_CALLBACK(buddy_add_no_auth_cb),
702 _("Search"), G_CALLBACK(buddy_add_check_info_cb));
703 } else {
704 message = g_strdup_printf(_("%s added you [%s] to buddy list"), from, to);
705 purple_notify_info(gc, _("QQ Budy"), _("Successed:"), message);
706 }
707
708 g_free(name);
709 g_free(message);
710 }
711
712 /* the buddy approves your request of adding him/her as your friend */
713 static void server_buddy_added_me(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8)
714 {
715 gchar *message;
716 qq_data *qd;
717
718 g_return_if_fail(from != NULL && to != NULL);
719
720 qd = (qq_data *) gc->proto_data;
721 qq_create_buddy(gc, strtol(from, NULL, 10), TRUE, TRUE);
722
723 message = g_strdup_printf(_("Requestion approved by %s"), from);
724 purple_notify_info(gc, _("QQ Buddy"), _("Notice:"), message);
725
726 g_free(message);
727 }
728
729 /* you are rejected by the person */
730 static void server_buddy_rejected_me(PurpleConnection *gc, gchar *from, gchar *to, gchar *msg_utf8)
731 {
732 gchar *message, *reason;
733
734 g_return_if_fail(from != NULL && to != NULL);
735
736 message = g_strdup_printf(_("Requestion rejected by %s"), from);
737 reason = g_strdup_printf(_("Message: %s"), msg_utf8);
738
739 purple_notify_info(gc, _("QQ Buddy"), message, reason);
740 g_free(message);
741 g_free(reason);
742 }
743
744 void qq_process_buddy_from_server(PurpleConnection *gc, int funct,
745 gchar *from, gchar *to, gchar *msg_utf8)
746 {
747 switch (funct) {
748 case QQ_SERVER_BUDDY_ADDED:
749 server_buddy_added(gc, from, to, msg_utf8);
750 break;
751 case QQ_SERVER_BUDDY_ADD_REQUEST:
752 server_buddy_add_request(gc, from, to, msg_utf8);
753 break;
754 case QQ_SERVER_BUDDY_ADDED_ME:
755 server_buddy_added_me(gc, from, to, msg_utf8);
756 break;
757 case QQ_SERVER_BUDDY_REJECTED_ME:
758 server_buddy_rejected_me(gc, from, to, msg_utf8);
759 break;
760 default:
761 purple_debug_warning("QQ", "Unknow buddy operate (%d) from server\n", funct);
762 break;
763 }
764 }