libpurple/protocols/gg/gg.c

branch
soc.2013.gobjectification
changeset 34946
76aa2e0f8701
parent 34940
c0aef3b64c56
parent 34437
ca6d1b4d24b5
child 34948
e31ee6f00ff8
child 36744
a7c26ee6e466
equal deleted inserted replaced
34945:54af0dd9faa5 34946:76aa2e0f8701
37 #include "util.h" 37 #include "util.h"
38 #include "request.h" 38 #include "request.h"
39 #include "xmlnode.h" 39 #include "xmlnode.h"
40 40
41 #include "gg.h" 41 #include "gg.h"
42 #include "confer.h" 42 #include "chat.h"
43 #include "search.h" 43 #include "search.h"
44 #include "blist.h" 44 #include "blist.h"
45 #include "utils.h" 45 #include "utils.h"
46 #include "resolver-purple.h" 46 #include "resolver-purple.h"
47 #include "account.h" 47 #include "account.h"
49 #include "purplew.h" 49 #include "purplew.h"
50 #include "libgadu-events.h" 50 #include "libgadu-events.h"
51 #include "multilogon.h" 51 #include "multilogon.h"
52 #include "status.h" 52 #include "status.h"
53 #include "servconn.h" 53 #include "servconn.h"
54 #include "tcpsocket.h"
54 #include "pubdir-prpl.h" 55 #include "pubdir-prpl.h"
56 #include "message-prpl.h"
57 #include "html.h"
58 #include "libgaduw.h"
55 59
56 /* ---------------------------------------------------------------------- */ 60 /* ---------------------------------------------------------------------- */
57 61
58 ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy) 62 ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy)
59 { 63 {
60 ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy); 64 ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy);
61 if (buddy_data) 65 if (buddy_data)
62 return buddy_data; 66 return buddy_data;
63 67
64 buddy_data = g_new0(ggp_buddy_data, 1); 68 buddy_data = g_new0(ggp_buddy_data, 1); //TODO: leak
65 purple_buddy_set_protocol_data(buddy, buddy_data); 69 purple_buddy_set_protocol_data(buddy, buddy_data);
66 return buddy_data; 70 return buddy_data;
67 } 71 }
68 72
69 static void ggp_buddy_free(PurpleBuddy *buddy) 73 static void ggp_buddy_free(PurpleBuddy *buddy)
73 if (!buddy_data) 77 if (!buddy_data)
74 return; 78 return;
75 79
76 g_free(buddy_data); 80 g_free(buddy_data);
77 purple_buddy_set_protocol_data(buddy, NULL); 81 purple_buddy_set_protocol_data(buddy, NULL);
82 }
83
84 const gchar * ggp_get_imtoken(PurpleConnection *gc)
85 {
86 GGPInfo *accdata = purple_connection_get_protocol_data(gc);
87
88 if (accdata->imtoken)
89 return accdata->imtoken;
90
91 if (accdata->imtoken_warned)
92 return NULL;
93 accdata->imtoken_warned = TRUE;
94
95 purple_notify_error(gc, _("Authentication failed"),
96 _("IMToken value has not been received."),
97 _("Some features will be disabled. "
98 "You may try again after a while."));
99 return NULL;
100 }
101
102 uin_t ggp_own_uin(PurpleConnection *gc)
103 {
104 return ggp_str_to_uin(purple_account_get_username(
105 purple_connection_get_account(gc)));
78 } 106 }
79 107
80 /* ---------------------------------------------------------------------- */ 108 /* ---------------------------------------------------------------------- */
81 // buddy list import/export from/to file 109 // buddy list import/export from/to file
82 110
163 purple_request_file(action, _("Load buddylist from file..."), NULL, 191 purple_request_file(action, _("Load buddylist from file..."), NULL,
164 FALSE, G_CALLBACK(ggp_callback_buddylist_load_ok), NULL, 192 FALSE, G_CALLBACK(ggp_callback_buddylist_load_ok), NULL,
165 purple_request_cpar_from_connection(gc), gc); 193 purple_request_cpar_from_connection(gc), gc);
166 } 194 }
167 195
168 /* ----- CONFERENCES ---------------------------------------------------- */
169
170 static void ggp_callback_add_to_chat_ok(PurpleBuddy *buddy, PurpleRequestFields *fields)
171 {
172 PurpleConnection *conn;
173 PurpleRequestField *field;
174 GList *sel;
175
176 conn = purple_account_get_connection(purple_buddy_get_account(buddy));
177
178 g_return_if_fail(conn != NULL);
179
180 field = purple_request_fields_get_field(fields, "name");
181 sel = purple_request_field_list_get_selected(field);
182
183 if (sel == NULL) {
184 purple_debug_error("gg", "No chat selected\n");
185 return;
186 }
187
188 ggp_confer_participants_add_uin(conn, sel->data,
189 ggp_str_to_uin(purple_buddy_get_name(buddy)));
190 }
191
192 static void ggp_bmenu_add_to_chat(PurpleBlistNode *node, gpointer ignored)
193 {
194 PurpleBuddy *buddy;
195 PurpleConnection *gc;
196 GGPInfo *info;
197
198 PurpleRequestFields *fields;
199 PurpleRequestFieldGroup *group;
200 PurpleRequestField *field;
201
202 GList *l;
203 gchar *msg;
204
205 buddy = (PurpleBuddy *)node;
206 gc = purple_account_get_connection(purple_buddy_get_account(buddy));
207 info = purple_connection_get_protocol_data(gc);
208
209 fields = purple_request_fields_new();
210 group = purple_request_field_group_new(NULL);
211 purple_request_fields_add_group(fields, group);
212
213 field = purple_request_field_list_new("name", "Chat name");
214 for (l = info->chats; l != NULL; l = l->next) {
215 GGPChat *chat = l->data;
216 purple_request_field_list_add_icon(field, chat->name, NULL, chat->name);
217 }
218 purple_request_field_group_add_field(group, field);
219
220 msg = g_strdup_printf(_("Select a chat for buddy: %s"),
221 purple_buddy_get_alias(buddy));
222 purple_request_fields(gc,
223 _("Add to chat..."),
224 _("Add to chat..."),
225 msg,
226 fields,
227 _("Add"), G_CALLBACK(ggp_callback_add_to_chat_ok),
228 _("Cancel"), NULL,
229 purple_request_cpar_from_connection(gc),
230 buddy);
231 g_free(msg);
232 }
233
234 /* ----- BLOCK BUDDIES -------------------------------------------------- */ 196 /* ----- BLOCK BUDDIES -------------------------------------------------- */
235 197
236 static void ggp_add_deny(PurpleConnection *gc, const char *who) 198 static void ggp_add_deny(PurpleConnection *gc, const char *who)
237 { 199 {
238 GGPInfo *info = purple_connection_get_protocol_data(gc); 200 GGPInfo *info = purple_connection_get_protocol_data(gc);
256 } 218 }
257 219
258 /* ---------------------------------------------------------------------- */ 220 /* ---------------------------------------------------------------------- */
259 /* ----- INTERNAL CALLBACKS --------------------------------------------- */ 221 /* ----- INTERNAL CALLBACKS --------------------------------------------- */
260 /* ---------------------------------------------------------------------- */ 222 /* ---------------------------------------------------------------------- */
261
262 /**
263 * Dispatch a message received from a buddy.
264 *
265 * @param gc PurpleConnection.
266 * @param ev Gadu-Gadu event structure.
267 *
268 * Image receiving, some code borrowed from Kadu http://www.kadu.net
269 */
270 void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event_msg *ev, gboolean multilogon)
271 {
272 GGPInfo *info = purple_connection_get_protocol_data(gc);
273 PurpleChatConversation *chat;
274 gchar *from;
275 gchar *msg;
276 gchar *tmp;
277 time_t mtime;
278 uin_t sender = ev->sender;
279
280 if (ev->message == NULL)
281 {
282 purple_debug_warning("gg", "ggp_recv_message_handler: NULL as message pointer\n");
283 return;
284 }
285
286 from = g_strdup_printf("%lu", (unsigned long int)ev->sender);
287
288 tmp = g_strdup_printf("%s", ev->message);
289 purple_str_strip_char(tmp, '\r');
290 msg = g_markup_escape_text(tmp, -1);
291 g_free(tmp);
292
293 if (ev->msgclass & GG_CLASS_QUEUED)
294 mtime = ev->time;
295 else
296 mtime = time(NULL);
297
298 /* We got richtext message */
299 if (ev->formats_length)
300 {
301 gboolean got_image = FALSE, bold = FALSE, italic = FALSE, under = FALSE;
302 char *cformats = (char *)ev->formats;
303 char *cformats_end = cformats + ev->formats_length;
304 gint increased_len = 0;
305 struct gg_msg_richtext_format *actformat;
306 struct gg_msg_richtext_image *actimage;
307 GString *message = g_string_new(msg);
308
309 purple_debug_info("gg", "ggp_recv_message_handler: richtext msg from (%s): %s %i formats\n", from, msg, ev->formats_length);
310
311 while (cformats < cformats_end)
312 {
313 gint byteoffset;
314 actformat = (struct gg_msg_richtext_format *)cformats;
315 cformats += sizeof(struct gg_msg_richtext_format);
316 byteoffset = g_utf8_offset_to_pointer(message->str, actformat->position + increased_len) - message->str;
317
318 if(actformat->position == 0 && actformat->font == 0) {
319 purple_debug_warning("gg", "ggp_recv_message_handler: bogus formatting (inc: %i)\n", increased_len);
320 continue;
321 }
322 purple_debug_info("gg", "ggp_recv_message_handler: format at pos: %i, image:%i, bold:%i, italic: %i, under:%i (inc: %i)\n",
323 actformat->position,
324 (actformat->font & GG_FONT_IMAGE) != 0,
325 (actformat->font & GG_FONT_BOLD) != 0,
326 (actformat->font & GG_FONT_ITALIC) != 0,
327 (actformat->font & GG_FONT_UNDERLINE) != 0,
328 increased_len);
329
330 if (actformat->font & GG_FONT_IMAGE)
331 {
332 const char *placeholder;
333
334 got_image = TRUE;
335 actimage = (struct gg_msg_richtext_image*)(cformats);
336 cformats += sizeof(struct gg_msg_richtext_image);
337 purple_debug_info("gg", "ggp_recv_message_handler: image received, size: %d, crc32: %i\n", actimage->size, actimage->crc32);
338
339 /* Checking for errors, image size shouldn't be
340 * larger than 255.000 bytes */
341 if (actimage->size > 255000) {
342 purple_debug_warning("gg", "ggp_recv_message_handler: received image large than 255 kb\n");
343 continue;
344 }
345
346 gg_image_request(info->session, ev->sender,
347 actimage->size, actimage->crc32);
348
349 placeholder = ggp_image_pending_placeholder(actimage->crc32);
350 g_string_insert(message, byteoffset, placeholder);
351 increased_len += strlen(placeholder);
352 continue;
353 }
354
355 if (actformat->font & GG_FONT_BOLD) {
356 if (bold == FALSE) {
357 g_string_insert(message, byteoffset, "<b>");
358 increased_len += 3;
359 bold = TRUE;
360 }
361 } else if (bold) {
362 g_string_insert(message, byteoffset, "</b>");
363 increased_len += 4;
364 bold = FALSE;
365 }
366
367 if (actformat->font & GG_FONT_ITALIC) {
368 if (italic == FALSE) {
369 g_string_insert(message, byteoffset, "<i>");
370 increased_len += 3;
371 italic = TRUE;
372 }
373 } else if (italic) {
374 g_string_insert(message, byteoffset, "</i>");
375 increased_len += 4;
376 italic = FALSE;
377 }
378
379 if (actformat->font & GG_FONT_UNDERLINE) {
380 if (under == FALSE) {
381 g_string_insert(message, byteoffset, "<u>");
382 increased_len += 3;
383 under = TRUE;
384 }
385 } else if (under) {
386 g_string_insert(message, byteoffset, "</u>");
387 increased_len += 4;
388 under = FALSE;
389 }
390
391 if (actformat->font & GG_FONT_COLOR) {
392 cformats += sizeof(struct gg_msg_richtext_color);
393 }
394 }
395
396 msg = message->str;
397 g_string_free(message, FALSE);
398
399 if (got_image)
400 {
401 ggp_image_got_im(gc, sender, msg, mtime);
402 return;
403 }
404 }
405
406 purple_debug_info("gg", "ggp_recv_message_handler: msg from (%s): %s (class = %d; rcpt_count = %d; multilogon = %d)\n",
407 from, msg, ev->msgclass,
408 ev->recipients_count,
409 multilogon);
410
411 if (multilogon && ev->recipients_count != 0) {
412 purple_debug_warning("gg", "ggp_recv_message_handler: conference multilogon messages are not yet handled\n");
413 } else if (multilogon) {
414 PurpleAccount *account = purple_connection_get_account(gc);
415 PurpleIMConversation *im;
416 const gchar *who = ggp_uin_to_str(ev->sender); // not really sender
417 im = purple_conversations_find_im_with_account(who, account);
418 if (im == NULL)
419 im = purple_im_conversation_new(account, who);
420 purple_conversation_write(PURPLE_CONVERSATION(im), purple_account_get_username(account), msg, PURPLE_MESSAGE_SEND, mtime);
421 } else if (ev->recipients_count == 0) {
422 serv_got_im(gc, from, msg, 0, mtime);
423 } else {
424 const char *chat_name;
425 int chat_id;
426
427 chat_name = ggp_confer_find_by_participants(gc,
428 ev->recipients,
429 ev->recipients_count);
430
431 if (chat_name == NULL) {
432 chat_name = ggp_confer_add_new(gc, NULL);
433 serv_got_joined_chat(gc, info->chats_count, chat_name);
434
435 ggp_confer_participants_add_uin(gc, chat_name,
436 ev->sender);
437
438 ggp_confer_participants_add(gc, chat_name,
439 ev->recipients,
440 ev->recipients_count);
441 }
442 chat = ggp_confer_find_by_name(gc, chat_name);
443 chat_id = purple_chat_conversation_get_id(chat);
444
445 serv_got_chat_in(gc, chat_id,
446 ggp_buddylist_get_buddy_name(gc, ev->sender),
447 PURPLE_MESSAGE_RECV, msg, mtime);
448 }
449 g_free(msg);
450 g_free(from);
451 }
452 223
453 static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int length) { 224 static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int length) {
454 gchar *from; 225 gchar *from;
455 226
456 from = g_strdup_printf("%u", uin); 227 from = g_strdup_printf("%u", uin);
471 * @todo: this may not be necessary anymore 242 * @todo: this may not be necessary anymore
472 */ 243 */
473 static void ggp_xml_event_handler(PurpleConnection *gc, char *data) 244 static void ggp_xml_event_handler(PurpleConnection *gc, char *data)
474 { 245 {
475 PurpleXmlNode *xml = NULL; 246 PurpleXmlNode *xml = NULL;
476 PurpleXmlNode *purple_xmlnode_next_event; 247 PurpleXmlNode *xmlnode_next_event;
477 248
478 xml = purple_xmlnode_from_str(data, -1); 249 xml = purple_xmlnode_from_str(data, -1);
479 if (xml == NULL) 250 if (xml == NULL)
251 {
252 purple_debug_error("gg", "ggp_xml_event_handler: "
253 "invalid xml: [%s]\n", data);
480 goto out; 254 goto out;
481 255 }
482 purple_xmlnode_next_event = purple_xmlnode_get_child(xml, "event"); 256
483 while (purple_xmlnode_next_event != NULL) 257 xmlnode_next_event = purple_xmlnode_get_child(xml, "event");
258 while (xmlnode_next_event != NULL)
484 { 259 {
485 PurpleXmlNode *purple_xmlnode_current_event = purple_xmlnode_next_event; 260 PurpleXmlNode *xmlnode_current_event = xmlnode_next_event;
486 261
487 PurpleXmlNode *purple_xmlnode_type; 262 PurpleXmlNode *xmlnode_type;
488 char *event_type_raw; 263 char *event_type_raw;
489 int event_type = 0; 264 int event_type = 0;
490 265
491 PurpleXmlNode *purple_xmlnode_sender; 266 PurpleXmlNode *xmlnode_sender;
492 char *event_sender_raw; 267 char *event_sender_raw;
493 uin_t event_sender = 0; 268 uin_t event_sender = 0;
494 269
495 purple_xmlnode_next_event = purple_xmlnode_get_next_twin(purple_xmlnode_next_event); 270 xmlnode_next_event = purple_xmlnode_get_next_twin(xmlnode_next_event);
496 271
497 purple_xmlnode_type = purple_xmlnode_get_child(purple_xmlnode_current_event, "type"); 272 xmlnode_type = purple_xmlnode_get_child(xmlnode_current_event, "type");
498 if (purple_xmlnode_type == NULL) 273 if (xmlnode_type == NULL)
499 continue; 274 continue;
500 event_type_raw = purple_xmlnode_get_data(purple_xmlnode_type); 275 event_type_raw = purple_xmlnode_get_data(xmlnode_type);
501 if (event_type_raw != NULL) 276 if (event_type_raw != NULL)
502 event_type = atoi(event_type_raw); 277 event_type = atoi(event_type_raw);
503 g_free(event_type_raw); 278 g_free(event_type_raw);
504 279
505 purple_xmlnode_sender = purple_xmlnode_get_child(purple_xmlnode_current_event, "sender"); 280 xmlnode_sender = purple_xmlnode_get_child(xmlnode_current_event, "sender");
506 if (purple_xmlnode_sender != NULL) 281 if (xmlnode_sender != NULL)
507 { 282 {
508 event_sender_raw = purple_xmlnode_get_data(purple_xmlnode_sender); 283 event_sender_raw = purple_xmlnode_get_data(xmlnode_sender);
509 if (event_sender_raw != NULL) 284 if (event_sender_raw != NULL)
510 event_sender = ggp_str_to_uin(event_sender_raw); 285 event_sender = ggp_str_to_uin(event_sender_raw);
511 g_free(event_sender_raw); 286 g_free(event_sender_raw);
512 } 287 }
513 288
547 322
548 switch (ev->type) { 323 switch (ev->type) {
549 case GG_EVENT_NONE: 324 case GG_EVENT_NONE:
550 /* Nothing happened. */ 325 /* Nothing happened. */
551 break; 326 break;
327 case GG_EVENT_CONN_FAILED:
328 purple_connection_error (gc,
329 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
330 _("Server disconnected"));
331 break;
552 case GG_EVENT_MSG: 332 case GG_EVENT_MSG:
553 ggp_recv_message_handler(gc, &ev->event.msg, FALSE); 333 ggp_message_got(gc, &ev->event.msg);
554 break; 334 break;
555 case GG_EVENT_ACK: 335 #if GGP_ENABLE_GG11
556 /* Changing %u to %i fixes compiler warning */ 336 case GG_EVENT_ACK110:
557 purple_debug_info("gg", 337 break;
558 "ggp_callback_recv: message sent to: %i, delivery status=%d, seq=%d\n", 338 #endif
559 ev->event.ack.recipient, ev->event.ack.status,
560 ev->event.ack.seq);
561 break;
562 case GG_EVENT_IMAGE_REPLY: 339 case GG_EVENT_IMAGE_REPLY:
563 ggp_image_recv(gc, &ev->event.image_reply); 340 ggp_image_recv(gc, &ev->event.image_reply);
564 break; 341 break;
565 case GG_EVENT_IMAGE_REQUEST: 342 case GG_EVENT_IMAGE_REQUEST:
566 ggp_image_send(gc, &ev->event.image_request); 343 ggp_image_send(gc, &ev->event.image_request);
578 ggp_xml_event_handler(gc, ev->event.xml_event.data); 355 ggp_xml_event_handler(gc, ev->event.xml_event.data);
579 break; 356 break;
580 case GG_EVENT_USER_DATA: 357 case GG_EVENT_USER_DATA:
581 ggp_events_user_data(gc, &ev->event.user_data); 358 ggp_events_user_data(gc, &ev->event.user_data);
582 break; 359 break;
360 #if GGP_ENABLE_GG11
361 case GG_EVENT_JSON_EVENT:
362 ggp_events_json(gc, &ev->event.json_event);
363 break;
364 #endif
583 case GG_EVENT_USERLIST100_VERSION: 365 case GG_EVENT_USERLIST100_VERSION:
584 ggp_roster_version(gc, &ev->event.userlist100_version); 366 ggp_roster_version(gc, &ev->event.userlist100_version);
585 break; 367 break;
586 case GG_EVENT_USERLIST100_REPLY: 368 case GG_EVENT_USERLIST100_REPLY:
587 ggp_roster_reply(gc, &ev->event.userlist100_reply); 369 ggp_roster_reply(gc, &ev->event.userlist100_reply);
588 break; 370 break;
589 case GG_EVENT_MULTILOGON_MSG: 371 case GG_EVENT_MULTILOGON_MSG:
590 ggp_multilogon_msg(gc, &ev->event.multilogon_msg); 372 ggp_message_got_multilogon(gc, &ev->event.multilogon_msg);
591 break; 373 break;
592 case GG_EVENT_MULTILOGON_INFO: 374 case GG_EVENT_MULTILOGON_INFO:
593 ggp_multilogon_info(gc, &ev->event.multilogon_info); 375 ggp_multilogon_info(gc, &ev->event.multilogon_info);
594 break; 376 break;
377 #if GGP_ENABLE_GG11
378 case GG_EVENT_IMTOKEN:
379 purple_debug_info("gg", "gg11: got IMTOKEN\n");
380 g_free(info->imtoken);
381 info->imtoken = g_strdup(ev->event.imtoken.imtoken);
382 break;
383 case GG_EVENT_PONG110:
384 purple_debug_info("gg", "gg11: got PONG110 %lu\n", ev->event.pong110.time);
385 break;
386 case GG_EVENT_CHAT_INFO:
387 case GG_EVENT_CHAT_INFO_GOT_ALL:
388 case GG_EVENT_CHAT_INFO_UPDATE:
389 case GG_EVENT_CHAT_CREATED:
390 case GG_EVENT_CHAT_INVITE_ACK:
391 ggp_chat_got_event(gc, ev);
392 break;
393 #endif
595 default: 394 default:
596 purple_debug_error("gg", 395 purple_debug_warning("gg",
597 "unsupported event type=%d\n", ev->type); 396 "unsupported event type=%d\n", ev->type);
598 break; 397 break;
599 } 398 }
600 399
601 gg_free_event(ev); 400 gg_free_event(ev);
602 } 401 }
603 402
604 static void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition cond) 403 void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
605 { 404 {
606 PurpleConnection *gc = _gc; 405 PurpleConnection *gc = _gc;
607 GGPInfo *info; 406 GGPInfo *info;
608 struct gg_event *ev; 407 struct gg_event *ev;
609 408
637 purple_debug_info("gg", "GG_STATE_READING_REPLY\n"); 436 purple_debug_info("gg", "GG_STATE_READING_REPLY\n");
638 break; 437 break;
639 case GG_STATE_TLS_NEGOTIATION: 438 case GG_STATE_TLS_NEGOTIATION:
640 purple_debug_info("gg", "GG_STATE_TLS_NEGOTIATION\n"); 439 purple_debug_info("gg", "GG_STATE_TLS_NEGOTIATION\n");
641 break; 440 break;
441 #if GGP_ENABLE_GG11
442 case GG_STATE_RESOLVING_HUB:
443 purple_debug_info("gg", "GG_STATE_RESOLVING_HUB\n");
444 break;
445 case GG_STATE_READING_HUB:
446 purple_debug_info("gg", "GG_STATE_READING_HUB\n");
447 break;
448 #endif
642 default: 449 default:
643 purple_debug_error("gg", "unknown state = %d\n", 450 purple_debug_error("gg", "unknown state = %d\n",
644 info->session->state); 451 info->session->state);
645 break; 452 break;
646 } 453 }
671 /* Nothing happened. */ 478 /* Nothing happened. */
672 purple_debug_info("gg", "GG_EVENT_NONE\n"); 479 purple_debug_info("gg", "GG_EVENT_NONE\n");
673 break; 480 break;
674 case GG_EVENT_CONN_SUCCESS: 481 case GG_EVENT_CONN_SUCCESS:
675 { 482 {
676 const gchar * server_ip = ggp_ipv4_to_str( 483 #if GGP_ENABLE_GG11
677 info->session->server_addr);
678 purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS:" 484 purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS:"
679 " successfully connected to %s\n", 485 " successfully connected to %s\n",
680 server_ip); 486 info->session->connect_host);
681 ggp_servconn_add_server(server_ip); 487 ggp_servconn_add_server(info->session->
488 connect_host);
489 #endif
682 purple_input_remove(info->inpa); 490 purple_input_remove(info->inpa);
683 info->inpa = purple_input_add(info->session->fd, 491 info->inpa = purple_input_add(info->session->fd,
684 PURPLE_INPUT_READ, 492 PURPLE_INPUT_READ,
685 ggp_callback_recv, gc); 493 ggp_callback_recv, gc);
686 494
792 g_snprintf(normalized, sizeof(normalized), "%u", uin); 600 g_snprintf(normalized, sizeof(normalized), "%u", uin);
793 601
794 return normalized; 602 return normalized;
795 } 603 }
796 604
605 /* TODO:
606 * - move to status.c ?
607 * - add information about not adding to his buddy list (not_a_friend)
608 */
797 static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) 609 static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
798 { 610 {
799 PurpleStatus *status; 611 PurpleStatus *status;
800 char *tmp; 612 char *tmp;
801 const char *name, *alias; 613 const char *name, *alias;
823 } else if (PURPLE_BUDDY_IS_ONLINE(b)) { 635 } else if (PURPLE_BUDDY_IS_ONLINE(b)) {
824 purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), name); 636 purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), name);
825 } 637 }
826 } 638 }
827 639
828 static GList *ggp_blist_node_menu(PurpleBlistNode *node)
829 {
830 PurpleMenuAction *act;
831 GList *m = NULL;
832 PurpleAccount *account;
833 PurpleConnection *gc;
834 GGPInfo *info;
835
836 if (!PURPLE_IS_BUDDY(node))
837 return NULL;
838
839 account = purple_buddy_get_account((PurpleBuddy *) node);
840 gc = purple_account_get_connection(account);
841 info = purple_connection_get_protocol_data(gc);
842 if (info->chats) {
843 act = purple_menu_action_new(_("Add to chat"),
844 PURPLE_CALLBACK(ggp_bmenu_add_to_chat),
845 NULL, NULL);
846 m = g_list_append(m, act);
847 }
848
849 return m;
850 }
851
852 static GList *ggp_chat_info(PurpleConnection *gc)
853 {
854 GList *m = NULL;
855 struct proto_chat_entry *pce;
856
857 pce = g_new0(struct proto_chat_entry, 1);
858 pce->label = _("Chat _name:");
859 pce->identifier = "name";
860 pce->required = TRUE;
861 m = g_list_append(m, pce);
862
863 return m;
864 }
865
866 static void ggp_login(PurpleAccount *account) 640 static void ggp_login(PurpleAccount *account)
867 { 641 {
868 PurpleConnection *gc = purple_account_get_connection(account); 642 PurpleConnection *gc = purple_account_get_connection(account);
869 struct gg_login_params *glp; 643 struct gg_login_params *glp;
870 GGPInfo *info; 644 GGPInfo *info;
645 #if GGP_ENABLE_GG11
871 const char *address; 646 const char *address;
872 const gchar *encryption_type; 647 #endif
648 const gchar *encryption_type, *protocol_version;
873 649
874 if (!ggp_deprecated_setup_proxy(gc)) 650 if (!ggp_deprecated_setup_proxy(gc))
875 return; 651 return;
876 652
653 purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML |
654 PURPLE_CONNECTION_FLAG_NO_URLDESC);
655
877 glp = g_new0(struct gg_login_params, 1); 656 glp = g_new0(struct gg_login_params, 1);
657 #if GGP_ENABLE_GG11
658 glp->struct_size = sizeof(struct gg_login_params);
659 #endif
878 info = g_new0(GGPInfo, 1); 660 info = g_new0(GGPInfo, 1);
879 661
880 /* Probably this should be moved to *_new() function. */
881 info->session = NULL;
882 info->chats = NULL;
883 info->chats_count = 0;
884
885 purple_connection_set_protocol_data(gc, info); 662 purple_connection_set_protocol_data(gc, info);
886 663
887 664 ggp_tcpsocket_setup(gc, glp);
888 ggp_image_setup(gc); 665 ggp_image_setup(gc);
889 ggp_avatar_setup(gc); 666 ggp_avatar_setup(gc);
890 ggp_roster_setup(gc); 667 ggp_roster_setup(gc);
891 ggp_multilogon_setup(gc); 668 ggp_multilogon_setup(gc);
892 ggp_status_setup(gc); 669 ggp_status_setup(gc);
893 670 ggp_chat_setup(gc);
671 ggp_message_setup(gc);
672 ggp_edisc_setup(gc);
673
894 glp->uin = ggp_str_to_uin(purple_account_get_username(account)); 674 glp->uin = ggp_str_to_uin(purple_account_get_username(account));
895 glp->password = 675 glp->password =
896 ggp_convert_to_cp1250(purple_connection_get_password(gc)); 676 ggp_convert_to_cp1250(purple_connection_get_password(gc));
897 677
898 if (glp->uin == 0) { 678 if (glp->uin == 0) {
899 purple_connection_error(gc, 679 purple_connection_error(gc,
900 PURPLE_CONNECTION_ERROR_INVALID_USERNAME, 680 PURPLE_CONNECTION_ERROR_INVALID_USERNAME,
901 _("The username specified is invalid.")); 681 _("The username specified is invalid."));
682 purple_str_wipe(glp->password);
902 g_free(glp); 683 g_free(glp);
903 return; 684 return;
904 } 685 }
905 686
906 glp->image_size = 255; 687 glp->image_size = 255;
927 glp->tls = GG_SSL_REQUIRED; 708 glp->tls = GG_SSL_REQUIRED;
928 else { 709 else {
929 purple_connection_error(gc, 710 purple_connection_error(gc,
930 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, 711 PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
931 _("SSL support unavailable")); 712 _("SSL support unavailable"));
713 purple_str_wipe(glp->password);
932 g_free(glp); 714 g_free(glp);
933 return; 715 return;
934 } 716 }
935 } 717 }
936 else /* encryption_type == "none" */ 718 else /* encryption_type == "none" */
937 glp->tls = GG_SSL_DISABLED; 719 glp->tls = GG_SSL_DISABLED;
938 purple_debug_info("gg", "TLS mode: %d\n", glp->tls); 720 purple_debug_misc("gg", "TLS mode: %d\n", glp->tls);
721
722 protocol_version = purple_account_get_string(account,
723 "protocol_version", "default");
724 purple_debug_info("gg", "Requested protocol version: %s\n",
725 protocol_version);
726 #if GGP_ENABLE_GG11
727 if (g_strcmp0(protocol_version, "gg10") == 0)
728 glp->protocol_version = GG_PROTOCOL_VERSION_100;
729 else if (g_strcmp0(protocol_version, "gg11") == 0)
730 glp->protocol_version = GG_PROTOCOL_VERSION_110;
731 #else
732 glp->protocol_version = 0x2e;
733 #endif
939 734
940 ggp_status_set_initial(gc, glp); 735 ggp_status_set_initial(gc, glp);
941 736
737 #if GGP_ENABLE_GG11
942 address = purple_account_get_string(account, "gg_server", ""); 738 address = purple_account_get_string(account, "gg_server", "");
943 if (address && *address) 739 if (address && *address)
944 { 740 glp->connect_host = g_strdup(address);
945 glp->server_addr = inet_addr(address); 741 #endif
946 glp->server_port = 8074;
947
948 if (glp->server_addr == INADDR_NONE)
949 {
950 purple_connection_error(gc,
951 PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
952 _("Provided server IP address is not valid"));
953 g_free(glp);
954 return;
955 }
956 } else
957 purple_debug_info("gg", "Trying to retrieve address from gg appmsg service\n");
958 742
959 info->session = gg_login(glp); 743 info->session = gg_login(glp);
744 #if GGP_ENABLE_GG11
745 g_free(glp->connect_host);
746 #endif
747 purple_str_wipe(glp->password);
748 g_free(glp);
749
960 purple_connection_update_progress(gc, _("Connecting"), 0, 2); 750 purple_connection_update_progress(gc, _("Connecting"), 0, 2);
961 if (info->session == NULL) { 751 if (info->session == NULL) {
962 purple_connection_error (gc, 752 purple_connection_error (gc,
963 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 753 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
964 _("Connection failed")); 754 _("Connection failed"));
965 g_free(glp);
966 return; 755 return;
967 } 756 }
968 info->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ, 757
969 ggp_async_login_handler, gc); 758 if (info->session->fd > 0) {
759 info->inpa = purple_input_add(info->session->fd,
760 PURPLE_INPUT_READ, ggp_async_login_handler, gc);
761 }
970 } 762 }
971 763
972 static void ggp_close(PurpleConnection *gc) 764 static void ggp_close(PurpleConnection *gc)
973 { 765 {
974 PurpleAccount *account; 766 PurpleAccount *account;
975 GGPInfo *info;; 767 GGPInfo *info;;
976 768
977 if (gc == NULL) { 769 g_return_if_fail(gc != NULL);
978 purple_debug_info("gg", "gc == NULL\n");
979 return;
980 }
981 770
982 account = purple_connection_get_account(gc); 771 account = purple_connection_get_account(gc);
983 info = purple_connection_get_protocol_data(gc); 772 info = purple_connection_get_protocol_data(gc);
773
774 purple_notify_close_with_handle(gc);
984 775
985 if (info) { 776 if (info) {
986 if (info->session != NULL) 777 if (info->session != NULL)
987 { 778 {
988 ggp_status_set_disconnected(account); 779 ggp_status_set_disconnected(account);
989 gg_logoff(info->session); 780 gg_logoff(info->session);
990 gg_free_session(info->session); 781 gg_free_session(info->session);
991 } 782 }
992 783
993 /* Immediately close any notifications on this handle since that process depends
994 * upon the contents of info->searches, which we are about to destroy.
995 */
996 purple_notify_close_with_handle(gc);
997
998 ggp_image_cleanup(gc); 784 ggp_image_cleanup(gc);
999 ggp_avatar_cleanup(gc); 785 ggp_avatar_cleanup(gc);
1000 ggp_roster_cleanup(gc); 786 ggp_roster_cleanup(gc);
1001 ggp_multilogon_cleanup(gc); 787 ggp_multilogon_cleanup(gc);
1002 ggp_status_cleanup(gc); 788 ggp_status_cleanup(gc);
789 ggp_chat_cleanup(gc);
790 ggp_message_cleanup(gc);
791 ggp_edisc_cleanup(gc);
1003 792
1004 if (info->inpa > 0) 793 if (info->inpa > 0)
1005 purple_input_remove(info->inpa); 794 purple_input_remove(info->inpa);
795 g_free(info->imtoken);
1006 796
1007 purple_connection_set_protocol_data(gc, NULL); 797 purple_connection_set_protocol_data(gc, NULL);
1008 g_free(info); 798 g_free(info);
1009 } 799 }
1010 800
1011 purple_debug_info("gg", "Connection closed.\n"); 801 purple_debug_info("gg", "Connection closed.\n");
1012 }
1013
1014 static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg,
1015 PurpleMessageFlags flags)
1016 {
1017 GGPInfo *info = purple_connection_get_protocol_data(gc);
1018 char *tmp, *plain;
1019 int ret = 1;
1020 unsigned char format[1024];
1021 unsigned int format_length = sizeof(struct gg_msg_richtext);
1022 gint pos = 0;
1023 GData *attribs;
1024 const char *start, *end = NULL, *last;
1025 ggp_buddy_data *buddy_data = ggp_buddy_get_data(
1026 purple_blist_find_buddy(purple_connection_get_account(gc), who));
1027
1028 if (msg == NULL || *msg == '\0') {
1029 return 0;
1030 }
1031
1032 if (buddy_data->blocked)
1033 return -1;
1034
1035 last = msg;
1036
1037 /* Check if the message is richtext */
1038 /* TODO: Check formatting, too */
1039 if(purple_markup_find_tag("img", last, &start, &end, &attribs)) {
1040
1041 GString *string_buffer = g_string_new(NULL);
1042 struct gg_msg_richtext fmt;
1043
1044 do
1045 {
1046 const char *id = g_datalist_get_data(&attribs, "id");
1047 struct gg_msg_richtext_format actformat;
1048 struct gg_msg_richtext_image actimage;
1049 ggp_image_prepare_result prepare_result;
1050
1051 /* Add text before the image */
1052 if(start - last)
1053 {
1054 pos = pos + g_utf8_strlen(last, start - last);
1055 g_string_append_len(string_buffer, last,
1056 start - last);
1057 }
1058 last = end + 1;
1059
1060 if (id == NULL)
1061 {
1062 g_datalist_clear(&attribs);
1063 continue;
1064 }
1065
1066 /* add the image itself */
1067 prepare_result = ggp_image_prepare(
1068 gc, atoi(id), who, &actimage);
1069 if (prepare_result == GGP_IMAGE_PREPARE_OK)
1070 {
1071 actformat.font = GG_FONT_IMAGE;
1072 actformat.position = pos;
1073
1074 memcpy(format + format_length, &actformat,
1075 sizeof(actformat));
1076 format_length += sizeof(actformat);
1077 memcpy(format + format_length, &actimage,
1078 sizeof(actimage));
1079 format_length += sizeof(actimage);
1080 }
1081 else if (prepare_result == GGP_IMAGE_PREPARE_TOO_BIG)
1082 {
1083 PurpleIMConversation *im =
1084 purple_conversations_find_im_with_account(who,
1085 purple_connection_get_account(gc));
1086 purple_conversation_write(PURPLE_CONVERSATION(im), "",
1087 _("Image is too large, please try "
1088 "smaller one."), PURPLE_MESSAGE_ERROR,
1089 time(NULL));
1090 }
1091
1092 g_datalist_clear(&attribs);
1093 } while (purple_markup_find_tag("img", last, &start, &end,
1094 &attribs));
1095
1096 /* Add text after the images */
1097 if(last && *last) {
1098 pos = pos + g_utf8_strlen(last, -1);
1099 g_string_append(string_buffer, last);
1100 }
1101
1102 fmt.flag = 2;
1103 fmt.length = format_length - sizeof(fmt);
1104 memcpy(format, &fmt, sizeof(fmt));
1105
1106 purple_debug_info("gg", "ggp_send_im: richtext msg = %s\n", string_buffer->str);
1107 plain = purple_unescape_html(string_buffer->str);
1108 g_string_free(string_buffer, TRUE);
1109 } else {
1110 purple_debug_info("gg", "ggp_send_im: msg = %s\n", msg);
1111 plain = purple_unescape_html(msg);
1112 }
1113
1114 tmp = g_strdup(plain);
1115
1116 if (tmp && (format_length - sizeof(struct gg_msg_richtext))) {
1117 if(gg_send_message_richtext(info->session, GG_CLASS_CHAT, ggp_str_to_uin(who), (unsigned char *)tmp, format, format_length) < 0) {
1118 ret = -1;
1119 } else {
1120 ret = 1;
1121 }
1122 } else if (NULL == tmp || *tmp == 0) {
1123 ret = 0;
1124 } else if (strlen(tmp) > GG_MSG_MAXSIZE) {
1125 ret = -E2BIG;
1126 } else if (gg_send_message(info->session, GG_CLASS_CHAT,
1127 ggp_str_to_uin(who), (unsigned char *)tmp) < 0) {
1128 ret = -1;
1129 } else {
1130 ret = 1;
1131 }
1132
1133 g_free(plain);
1134 g_free(tmp);
1135
1136 return ret;
1137 } 802 }
1138 803
1139 static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state) 804 static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state)
1140 { 805 {
1141 GGPInfo *info = purple_connection_get_protocol_data(gc); 806 GGPInfo *info = purple_connection_get_protocol_data(gc);
1144 if (state == PURPLE_IM_TYPED) // not supported 809 if (state == PURPLE_IM_TYPED) // not supported
1145 return 1; 810 return 1;
1146 811
1147 if (state == PURPLE_IM_TYPING) 812 if (state == PURPLE_IM_TYPING)
1148 dummy_length = (int)g_random_int(); 813 dummy_length = (int)g_random_int();
1149 else // PURPLE_IM_NOT_TYPING 814 else // PURPLE_NOT_TYPING
1150 dummy_length = 0; 815 dummy_length = 0;
1151 816
1152 gg_typing_notification( 817 gg_typing_notification(
1153 info->session, 818 info->session,
1154 ggp_str_to_uin(name), 819 ggp_str_to_uin(name),
1180 845
1181 gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy))); 846 gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy)));
1182 ggp_roster_remove_buddy(gc, buddy, group); 847 ggp_roster_remove_buddy(gc, buddy, group);
1183 } 848 }
1184 849
1185 static void ggp_join_chat(PurpleConnection *gc, GHashTable *data)
1186 {
1187 GGPInfo *info = purple_connection_get_protocol_data(gc);
1188 GGPChat *chat;
1189 char *chat_name;
1190 GList *l;
1191 PurpleChatConversation *conv;
1192 PurpleAccount *account = purple_connection_get_account(gc);
1193
1194 chat_name = g_hash_table_lookup(data, "name");
1195
1196 if (chat_name == NULL)
1197 return;
1198
1199 purple_debug_info("gg", "joined %s chat\n", chat_name);
1200
1201 for (l = info->chats; l != NULL; l = l->next) {
1202 chat = l->data;
1203
1204 if (chat != NULL && g_utf8_collate(chat->name, chat_name) == 0) {
1205 purple_notify_error(gc, _("Chat error"),
1206 _("This chat name is already in use"), NULL);
1207 return;
1208 }
1209 }
1210
1211 ggp_confer_add_new(gc, chat_name);
1212 conv = serv_got_joined_chat(gc, info->chats_count, chat_name);
1213 purple_chat_conversation_add_user(conv, purple_account_get_username(account),
1214 NULL, PURPLE_CHAT_USER_NONE, TRUE);
1215 }
1216
1217 static char *ggp_get_chat_name(GHashTable *data) {
1218 return g_strdup(g_hash_table_lookup(data, "name"));
1219 }
1220
1221 static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
1222 {
1223 PurpleChatConversation *conv;
1224 GGPInfo *info = purple_connection_get_protocol_data(gc);
1225 GGPChat *chat = NULL;
1226 GList *l;
1227 /* char *msg, *plain; */
1228 gchar *msg;
1229 uin_t *uins;
1230 int count = 0;
1231
1232 if ((conv = purple_conversations_find_chat(gc, id)) == NULL)
1233 return -EINVAL;
1234
1235 for (l = info->chats; l != NULL; l = l->next) {
1236 chat = l->data;
1237
1238 if (g_utf8_collate(chat->name, purple_conversation_get_name(
1239 PURPLE_CONVERSATION(conv))) == 0) {
1240 break;
1241 }
1242
1243 chat = NULL;
1244 }
1245
1246 if (chat == NULL) {
1247 purple_debug_error("gg",
1248 "ggp_chat_send: Hm... that's strange. No such chat?\n");
1249 return -EINVAL;
1250 }
1251
1252 uins = g_new0(uin_t, g_list_length(chat->participants));
1253
1254 for (l = chat->participants; l != NULL; l = l->next) {
1255 uin_t uin = GPOINTER_TO_INT(l->data);
1256
1257 uins[count++] = uin;
1258 }
1259
1260 msg = purple_unescape_html(message);
1261 gg_send_message_confer(info->session, GG_CLASS_CHAT, count, uins,
1262 (unsigned char *)msg);
1263 g_free(msg);
1264 g_free(uins);
1265
1266 serv_got_chat_in(gc, id,
1267 purple_account_get_username(purple_connection_get_account(gc)),
1268 flags, message, time(NULL));
1269
1270 return 0;
1271 }
1272
1273 static void ggp_keepalive(PurpleConnection *gc) 850 static void ggp_keepalive(PurpleConnection *gc)
1274 { 851 {
1275 GGPInfo *info = purple_connection_get_protocol_data(gc); 852 GGPInfo *info = purple_connection_get_protocol_data(gc);
1276 853
1277 /* purple_debug_info("gg", "Keeping connection alive....\n"); */ 854 /* purple_debug_info("gg", "Keeping connection alive....\n"); */
1345 { 922 {
1346 ggp_buddy_data *buddy_data = ggp_buddy_get_data(buddy); 923 ggp_buddy_data *buddy_data = ggp_buddy_get_data(buddy);
1347 924
1348 if (buddy_data->blocked) 925 if (buddy_data->blocked)
1349 return "not-authorized"; 926 return "not-authorized";
927 if (buddy_data->not_a_friend)
928 return "unavailable";
1350 929
1351 return NULL; 930 return NULL;
1352 } 931 }
1353 932
1354 static gboolean ggp_offline_message(const PurpleBuddy *buddy) 933 static gboolean ggp_offline_message(const PurpleBuddy *buddy)
1381 ggp_list_icon, /* list_icon */ 960 ggp_list_icon, /* list_icon */
1382 ggp_list_emblem, /* list_emblem */ 961 ggp_list_emblem, /* list_emblem */
1383 ggp_status_buddy_text, /* status_text */ 962 ggp_status_buddy_text, /* status_text */
1384 ggp_tooltip_text, /* tooltip_text */ 963 ggp_tooltip_text, /* tooltip_text */
1385 ggp_status_types, /* status_types */ 964 ggp_status_types, /* status_types */
1386 ggp_blist_node_menu, /* blist_node_menu */ 965 NULL, /* blist_node_menu */
966 #if GGP_ENABLE_GG11
1387 ggp_chat_info, /* chat_info */ 967 ggp_chat_info, /* chat_info */
1388 NULL, /* chat_info_defaults */ 968 ggp_chat_info_defaults, /* chat_info_defaults */
969 #else
970 NULL, NULL,
971 #endif
1389 ggp_login, /* login */ 972 ggp_login, /* login */
1390 ggp_close, /* close */ 973 ggp_close, /* close */
1391 ggp_send_im, /* send_im */ 974 ggp_message_send_im, /* send_im */
1392 NULL, /* set_info */ 975 NULL, /* set_info */
1393 ggp_send_typing, /* send_typing */ 976 ggp_send_typing, /* send_typing */
1394 ggp_pubdir_get_info_prpl, /* get_info */ 977 ggp_pubdir_get_info_prpl, /* get_info */
1395 ggp_status_set_purplestatus, /* set_away */ 978 ggp_status_set_purplestatus, /* set_away */
1396 NULL, /* set_idle */ 979 NULL, /* set_idle */
1402 NULL, /* add_permit */ 985 NULL, /* add_permit */
1403 ggp_add_deny, /* add_deny */ 986 ggp_add_deny, /* add_deny */
1404 NULL, /* rem_permit */ 987 NULL, /* rem_permit */
1405 ggp_rem_deny, /* rem_deny */ 988 ggp_rem_deny, /* rem_deny */
1406 NULL, /* set_permit_deny */ 989 NULL, /* set_permit_deny */
1407 ggp_join_chat, /* join_chat */ 990 #if GGP_ENABLE_GG11
1408 NULL, /* reject_chat */ 991 ggp_chat_join, /* join_chat */
1409 ggp_get_chat_name, /* get_chat_name */ 992 NULL, /* TODO */ /* reject_chat */
1410 NULL, /* chat_invite */ 993 ggp_chat_get_name, /* get_chat_name */
1411 NULL, /* chat_leave */ 994 ggp_chat_invite, /* chat_invite */
995 ggp_chat_leave, /* chat_leave */
1412 NULL, /* chat_whisper */ 996 NULL, /* chat_whisper */
1413 ggp_chat_send, /* chat_send */ 997 ggp_chat_send, /* chat_send */
998 #else
999 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1000 #endif
1414 ggp_keepalive, /* keepalive */ 1001 ggp_keepalive, /* keepalive */
1415 ggp_account_register, /* register_user */ 1002 ggp_account_register, /* register_user */
1416 NULL, /* get_cb_info */ 1003 NULL, /* get_cb_info */
1417 ggp_roster_alias_buddy, /* alias_buddy */ 1004 ggp_roster_alias_buddy, /* alias_buddy */
1418 ggp_roster_group_buddy, /* group_buddy */ 1005 ggp_roster_group_buddy, /* group_buddy */
1423 ggp_avatar_own_set, /* set_buddy_icon */ 1010 ggp_avatar_own_set, /* set_buddy_icon */
1424 NULL, /* remove_group */ 1011 NULL, /* remove_group */
1425 NULL, /* get_cb_real_name */ 1012 NULL, /* get_cb_real_name */
1426 NULL, /* set_chat_topic */ 1013 NULL, /* set_chat_topic */
1427 NULL, /* find_blist_chat */ 1014 NULL, /* find_blist_chat */
1428 NULL, /* roomlist_get_list */ 1015 #if GGP_ENABLE_GG11
1016 ggp_chat_roomlist_get_list, /* roomlist_get_list */
1017 #else
1018 NULL,
1019 #endif
1429 NULL, /* roomlist_cancel */ 1020 NULL, /* roomlist_cancel */
1430 NULL, /* roomlist_expand_category */ 1021 NULL, /* roomlist_expand_category */
1431 NULL, /* can_receive_file */ 1022 ggp_edisc_xfer_can_receive_file,/* can_receive_file */
1432 NULL, /* send_file */ 1023 ggp_edisc_xfer_send_file, /* send_file */
1433 NULL, /* new_xfer */ 1024 ggp_edisc_xfer_send_new, /* new_xfer */
1434 ggp_offline_message, /* offline_message */ 1025 ggp_offline_message, /* offline_message */
1435 NULL, /* whiteboard_prpl_ops */ 1026 NULL, /* whiteboard_prpl_ops */
1436 NULL, /* send_raw */ 1027 NULL, /* send_raw */
1437 NULL, /* roomlist_room_serialize */ 1028 NULL, /* roomlist_room_serialize */
1438 NULL, /* unregister_user */ 1029 NULL, /* unregister_user */
1483 NULL, 1074 NULL,
1484 NULL, 1075 NULL,
1485 NULL 1076 NULL
1486 }; 1077 };
1487 1078
1488 static void purple_gg_debug_handler(int level, const char * format, va_list args) {
1489 PurpleDebugLevel purple_level;
1490 char *msg = g_strdup_vprintf(format, args);
1491
1492 /* This is pretty pointless since the GG_DEBUG levels don't correspond to
1493 * the purple ones */
1494 switch (level) {
1495 case GG_DEBUG_FUNCTION:
1496 purple_level = PURPLE_DEBUG_INFO;
1497 break;
1498 case GG_DEBUG_MISC:
1499 case GG_DEBUG_NET:
1500 case GG_DEBUG_DUMP:
1501 case GG_DEBUG_TRAFFIC:
1502 default:
1503 purple_level = PURPLE_DEBUG_MISC;
1504 break;
1505 }
1506
1507 purple_debug(purple_level, "gg", "%s", msg);
1508 g_free(msg);
1509 }
1510
1511 static PurpleAccountOption *ggp_server_option; 1079 static PurpleAccountOption *ggp_server_option;
1512 1080
1513 static void init_plugin(PurplePlugin *plugin) 1081 static void init_plugin(PurplePlugin *plugin)
1514 { 1082 {
1515 PurpleAccountOption *option; 1083 PurpleAccountOption *option;
1516 GList *encryption_options = NULL; 1084 GList *encryption_options = NULL;
1085 GList *protocol_version = NULL;
1517 1086
1518 purple_prefs_add_none("/plugins/prpl/gg"); 1087 purple_prefs_add_none("/plugins/prpl/gg");
1519 1088
1520 option = purple_account_option_string_new(_("GG server"), 1089 option = purple_account_option_string_new(_("GG server"),
1521 "gg_server", ""); 1090 "gg_server", "");
1538 option = purple_account_option_list_new(_("Connection security"), 1107 option = purple_account_option_list_new(_("Connection security"),
1539 "encryption", encryption_options); 1108 "encryption", encryption_options);
1540 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, 1109 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
1541 option); 1110 option);
1542 1111
1112 ADD_VALUE(protocol_version, _("Default"), "default");
1113 ADD_VALUE(protocol_version, "GG 10", "gg10");
1114 ADD_VALUE(protocol_version, "GG 11", "gg11");
1115
1116 option = purple_account_option_list_new(_("Protocol version"),
1117 "protocol_version", protocol_version);
1118 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
1119 option);
1120
1543 option = purple_account_option_bool_new(_("Show links from strangers"), 1121 option = purple_account_option_bool_new(_("Show links from strangers"),
1544 "show_links_from_strangers", 1); 1122 "show_links_from_strangers", 1);
1545 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, 1123 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
1546 option); 1124 option);
1547
1548 gg_debug_handler = purple_gg_debug_handler;
1549 } 1125 }
1550 1126
1551 static gboolean ggp_load(PurplePlugin *plugin) 1127 static gboolean ggp_load(PurplePlugin *plugin)
1552 { 1128 {
1553 purple_debug_info("gg", "Loading Gadu-Gadu protocol plugin with " 1129 purple_debug_info("gg", "Loading Gadu-Gadu protocol plugin with "
1554 "libgadu %s...\n", gg_libgadu_version()); 1130 "libgadu %s...\n", gg_libgadu_version());
1555 1131
1132 ggp_libgaduw_setup();
1556 ggp_resolver_purple_setup(); 1133 ggp_resolver_purple_setup();
1557 ggp_servconn_setup(ggp_server_option); 1134 ggp_servconn_setup(ggp_server_option);
1558 1135 ggp_html_setup();
1136 ggp_message_setup_global();
1137
1559 return TRUE; 1138 return TRUE;
1560 } 1139 }
1561 1140
1562 static gboolean ggp_unload(PurplePlugin *plugin) 1141 static gboolean ggp_unload(PurplePlugin *plugin)
1563 { 1142 {
1564 ggp_servconn_cleanup(); 1143 ggp_servconn_cleanup();
1144 ggp_html_cleanup();
1145 ggp_message_cleanup_global();
1146 ggp_libgaduw_cleanup();
1147
1565 return TRUE; 1148 return TRUE;
1566 } 1149 }
1567 1150
1568 PURPLE_INIT_PLUGIN(gg, init_plugin, info); 1151 PURPLE_INIT_PLUGIN(gg, init_plugin, info);
1569 1152

mercurial