comparison libpurple/protocols/gg/gg.c @ 27590:a08e84032814

merge of '2348ff22f0ff3453774b8b25b36238465580c609' and 'e76f11543c2a4aa05bdf584f087cbe3439029661'
author Paul Aurich <paul@darkrain42.org>
date Sun, 12 Jul 2009 05:43:38 +0000
parents ac299d029823
children 737b75b5a888
comparison
equal deleted inserted replaced
27104:048bcf41deef 27590:a08e84032814
5 * 5 *
6 * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us> 6 * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
7 * 7 *
8 * Some parts of the code are adapted or taken from the previous implementation 8 * Some parts of the code are adapted or taken from the previous implementation
9 * of this plugin written by Arkadiusz Miskiewicz <misiek@pld.org.pl> 9 * of this plugin written by Arkadiusz Miskiewicz <misiek@pld.org.pl>
10 * Some parts Copyright (C) 2009 Krzysztof Klinikowski <grommasher@gmail.com>
10 * 11 *
11 * Thanks to Google's Summer of Code Program. 12 * Thanks to Google's Summer of Code Program.
12 * 13 *
13 * This program is free software; you can redistribute it and/or modify 14 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by 15 * it under the terms of the GNU General Public License as published by
34 #include "blist.h" 35 #include "blist.h"
35 #include "accountopt.h" 36 #include "accountopt.h"
36 #include "debug.h" 37 #include "debug.h"
37 #include "util.h" 38 #include "util.h"
38 #include "request.h" 39 #include "request.h"
40 #include "xmlnode.h"
39 41
40 #include <libgadu.h> 42 #include <libgadu.h>
41 43
42 #include "gg.h" 44 #include "gg.h"
43 #include "confer.h" 45 #include "confer.h"
348 350
349 if (email == NULL || p1 == NULL || p2 == NULL || t == NULL || 351 if (email == NULL || p1 == NULL || p2 == NULL || t == NULL ||
350 *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') { 352 *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') {
351 purple_connection_error_reason (gc, 353 purple_connection_error_reason (gc,
352 PURPLE_CONNECTION_ERROR_OTHER_ERROR, 354 PURPLE_CONNECTION_ERROR_OTHER_ERROR,
353 _("Fill in the registration fields.")); 355 _("You must fill in all registration fields"));
354 goto exit_err; 356 goto exit_err;
355 } 357 }
356 358
357 if (g_utf8_collate(p1, p2) != 0) { 359 if (g_utf8_collate(p1, p2) != 0) {
358 purple_connection_error_reason (gc, 360 purple_connection_error_reason (gc,
359 PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, 361 PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
360 _("Passwords do not match.")); 362 _("Passwords do not match"));
361 goto exit_err; 363 goto exit_err;
362 } 364 }
363 365
364 purple_debug_info("gg", "register_account_ok: token_id = %s; t = %s\n", 366 purple_debug_info("gg", "register_account_ok: token_id = %s; t = %s\n",
365 token->id, t); 367 token->id, t);
366 h = gg_register3(email, p1, token->id, t, 0); 368 h = gg_register3(email, p1, token->id, t, 0);
367 if (h == NULL || !(s = h->data) || !s->success) { 369 if (h == NULL || !(s = h->data) || !s->success) {
368 purple_connection_error_reason (gc, 370 purple_connection_error_reason (gc,
369 PURPLE_CONNECTION_ERROR_OTHER_ERROR, 371 PURPLE_CONNECTION_ERROR_OTHER_ERROR,
370 _("Unable to register new account. Error occurred.\n")); 372 _("Unable to register new account. An unknown error occurred."));
371 goto exit_err; 373 goto exit_err;
372 } 374 }
373 375
374 uin = s->uin; 376 uin = s->uin;
375 purple_debug_info("gg", "registered uin: %d\n", uin); 377 purple_debug_info("gg", "registered uin: %d\n", uin);
446 _("Password"), "", FALSE); 448 _("Password"), "", FALSE);
447 purple_request_field_string_set_masked(field, TRUE); 449 purple_request_field_string_set_masked(field, TRUE);
448 purple_request_field_group_add_field(group, field); 450 purple_request_field_group_add_field(group, field);
449 451
450 field = purple_request_field_string_new("password2", 452 field = purple_request_field_string_new("password2",
451 _("Password (retype)"), "", FALSE); 453 _("Password (again)"), "", FALSE);
452 purple_request_field_string_set_masked(field, TRUE); 454 purple_request_field_string_set_masked(field, TRUE);
453 purple_request_field_group_add_field(group, field); 455 purple_request_field_group_add_field(group, field);
454 456
455 field = purple_request_field_string_new("token", 457 field = purple_request_field_string_new("token",
456 _("Enter current token"), "", FALSE); 458 _("Enter captcha text"), "", FALSE);
457 purple_request_field_string_set_masked(field, FALSE); 459 purple_request_field_string_set_masked(field, FALSE);
458 purple_request_field_group_add_field(group, field); 460 purple_request_field_group_add_field(group, field);
459 461
460 /* original size: 60x24 */ 462 /* original size: 60x24 */
461 field = purple_request_field_image_new("token_img", 463 field = purple_request_field_image_new("token_img",
462 _("Current token"), token->data, token->size); 464 _("Captcha"), token->data, token->size);
463 purple_request_field_group_add_field(group, field); 465 purple_request_field_group_add_field(group, field);
464 466
465 purple_request_fields(account, 467 purple_request_fields(account,
466 _("Register New Gadu-Gadu Account"), 468 _("Register New Gadu-Gadu Account"),
467 _("Register New Gadu-Gadu Account"), 469 _("Register New Gadu-Gadu Account"),
856 858
857 /* Prototypes */ 859 /* Prototypes */
858 static void ggp_set_status(PurpleAccount *account, PurpleStatus *status); 860 static void ggp_set_status(PurpleAccount *account, PurpleStatus *status);
859 static int ggp_to_gg_status(PurpleStatus *status, char **msg); 861 static int ggp_to_gg_status(PurpleStatus *status, char **msg);
860 862
863 struct gg_fetch_avatar_data
864 {
865 PurpleConnection *gc;
866 gchar *uin;
867 gchar *avatar_url;
868 };
869
870
871 static void gg_fetch_avatar_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
872 const gchar *data, size_t len, const gchar *error_message) {
873 struct gg_fetch_avatar_data *d = user_data;
874 PurpleAccount *account;
875 PurpleBuddy *buddy;
876 gpointer buddy_icon_data;
877
878 /* FIXME: This shouldn't be necessary */
879 if (!PURPLE_CONNECTION_IS_VALID(d->gc)) {
880 g_free(d->uin);
881 g_free(d->avatar_url);
882 g_free(d);
883 g_return_if_reached();
884 }
885
886 account = purple_connection_get_account(d->gc);
887 buddy = purple_find_buddy(account, d->uin);
888
889 if (buddy == NULL)
890 goto out;
891
892 buddy_icon_data = g_memdup(data, len);
893
894 purple_buddy_icons_set_for_user(account, purple_buddy_get_name(buddy),
895 buddy_icon_data, len, d->avatar_url);
896 purple_debug_info("gg", "UIN: %s should have avatar now\n", d->uin);
897
898 out:
899 g_free(d->uin);
900 g_free(d->avatar_url);
901 g_free(d);
902 }
903
904 static void gg_get_avatar_url_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
905 const gchar *url_text, size_t len, const gchar *error_message) {
906 struct gg_fetch_avatar_data *data;
907 PurpleConnection *gc = user_data;
908 PurpleAccount *account;
909 PurpleBuddy *buddy;
910 const char *uin;
911 const char *is_blank;
912 const char *checksum;
913
914 gchar *bigavatar = NULL;
915 xmlnode *xml = NULL;
916 xmlnode *xmlnode_users;
917 xmlnode *xmlnode_user;
918 xmlnode *xmlnode_avatars;
919 xmlnode *xmlnode_avatar;
920 xmlnode *xmlnode_bigavatar;
921
922 g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
923 account = purple_connection_get_account(gc);
924
925 if (error_message != NULL)
926 purple_debug_error("gg", "gg_get_avatars_cb error: %s\n", error_message);
927 else if (len > 0 && url_text && *url_text) {
928 xml = xmlnode_from_str(url_text, -1);
929 if (xml == NULL)
930 goto out;
931
932 xmlnode_users = xmlnode_get_child(xml, "users");
933 if (xmlnode_users == NULL)
934 goto out;
935
936 xmlnode_user = xmlnode_get_child(xmlnode_users, "user");
937 if (xmlnode_user == NULL)
938 goto out;
939
940 uin = xmlnode_get_attrib(xmlnode_user, "uin");
941
942 xmlnode_avatars = xmlnode_get_child(xmlnode_user, "avatars");
943 if (xmlnode_avatars == NULL)
944 goto out;
945
946 xmlnode_avatar = xmlnode_get_child(xmlnode_avatars, "avatar");
947 if (xmlnode_avatar == NULL)
948 goto out;
949
950 xmlnode_bigavatar = xmlnode_get_child(xmlnode_avatar, "bigAvatar");
951 if (xmlnode_bigavatar == NULL)
952 goto out;
953
954 is_blank = xmlnode_get_attrib(xmlnode_avatar, "blank");
955 bigavatar = xmlnode_get_data(xmlnode_bigavatar);
956
957 purple_debug_info("gg", "gg_get_avatar_url_cb: UIN %s, IS_BLANK %s, "
958 "URL %s\n",
959 uin ? uin : "(null)", is_blank ? is_blank : "(null)",
960 bigavatar ? bigavatar : "(null)");
961
962 if (uin != NULL && bigavatar != NULL) {
963 buddy = purple_find_buddy(account, uin);
964 if (buddy == NULL)
965 goto out;
966
967 checksum = purple_buddy_icons_get_checksum_for_user(buddy);
968
969 if (purple_strequal(is_blank, "1")) {
970 purple_buddy_icons_set_for_user(account,
971 purple_buddy_get_name(buddy), NULL, 0, NULL);
972 } else if (!purple_strequal(checksum, bigavatar)) {
973 data = g_new0(struct gg_fetch_avatar_data, 1);
974 data->gc = gc;
975 data->uin = g_strdup(uin);
976 data->avatar_url = g_strdup(bigavatar);
977
978 url_data = purple_util_fetch_url_request_len_with_account(account,
979 bigavatar, TRUE, "Mozilla/4.0 (compatible; MSIE 5.0)",
980 FALSE, NULL, FALSE, -1, gg_fetch_avatar_cb, data);
981 }
982 }
983 }
984
985 out:
986 if (xml)
987 xmlnode_free(xml);
988 g_free(bigavatar);
989 }
861 990
862 /** 991 /**
863 * Handle change of the status of the buddy. 992 * Handle change of the status of the buddy.
864 * 993 *
865 * @param gc PurpleConnection 994 * @param gc PurpleConnection
871 int status, const char *descr) 1000 int status, const char *descr)
872 { 1001 {
873 gchar *from; 1002 gchar *from;
874 const char *st; 1003 const char *st;
875 gchar *msg; 1004 gchar *msg;
876 1005 gchar *avatarurl;
877 from = g_strdup_printf("%ld", (unsigned long int)uin); 1006 PurpleUtilFetchUrlData *url_data;
1007
1008 from = g_strdup_printf("%u", uin);
1009 avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%s/0.xml", from);
1010
1011 url_data = purple_util_fetch_url_request_len_with_account(
1012 purple_connection_get_account(gc), avatarurl, TRUE,
1013 "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
1014 gg_get_avatar_url_cb, gc);
1015
1016 g_free(avatarurl);
1017
878 switch (status) { 1018 switch (status) {
879 case GG_STATUS_NOT_AVAIL: 1019 case GG_STATUS_NOT_AVAIL:
880 case GG_STATUS_NOT_AVAIL_DESCR: 1020 case GG_STATUS_NOT_AVAIL_DESCR:
881 st = "offline"; 1021 st = "offline";
882 break; 1022 break;
929 const char *st; 1069 const char *st;
930 1070
931 purple_debug_info("gg", "ggp_status_by_id: %d\n", id); 1071 purple_debug_info("gg", "ggp_status_by_id: %d\n", id);
932 switch (id) { 1072 switch (id) {
933 case GG_STATUS_NOT_AVAIL: 1073 case GG_STATUS_NOT_AVAIL:
1074 case GG_STATUS_NOT_AVAIL_DESCR:
934 st = _("Offline"); 1075 st = _("Offline");
935 break; 1076 break;
936 case GG_STATUS_AVAIL: 1077 case GG_STATUS_AVAIL:
1078 case GG_STATUS_AVAIL_DESCR:
937 st = _("Available"); 1079 st = _("Available");
938 break; 1080 break;
939 case GG_STATUS_BUSY: 1081 case GG_STATUS_BUSY:
1082 case GG_STATUS_BUSY_DESCR:
940 st = _("Away"); 1083 st = _("Away");
941 break; 1084 break;
942 default: 1085 default:
943 st = _("Unknown"); 1086 st = _("Unknown");
944 break; 1087 break;
1385 if (!(ev = gg_watch_fd(info->session))) { 1528 if (!(ev = gg_watch_fd(info->session))) {
1386 purple_debug_error("gg", 1529 purple_debug_error("gg",
1387 "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n"); 1530 "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n");
1388 purple_connection_error_reason (gc, 1531 purple_connection_error_reason (gc,
1389 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 1532 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1390 _("Unable to read socket")); 1533 _("Unable to read from socket"));
1391 return; 1534 return;
1392 } 1535 }
1393 gc->last_received = time(NULL); 1536 gc->last_received = time(NULL);
1394 switch (ev->type) { 1537 switch (ev->type) {
1395 case GG_EVENT_NONE: 1538 case GG_EVENT_NONE:
1543 1686
1544 if (!(ev = gg_watch_fd(info->session))) { 1687 if (!(ev = gg_watch_fd(info->session))) {
1545 purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n"); 1688 purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n");
1546 purple_connection_error_reason (gc, 1689 purple_connection_error_reason (gc,
1547 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 1690 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1548 _("Unable to read socket")); 1691 _("Unable to read from socket"));
1549 return; 1692 return;
1550 } 1693 }
1551 purple_debug_info("gg", "login_handler: session->fd = %d\n", info->session->fd); 1694 purple_debug_info("gg", "login_handler: session->fd = %d\n", info->session->fd);
1552 purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n", 1695 purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
1553 info->session->check, info->session->state); 1696 info->session->check, info->session->state);
1570 purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n"); 1713 purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n");
1571 purple_input_remove(gc->inpa); 1714 purple_input_remove(gc->inpa);
1572 gc->inpa = purple_input_add(info->session->fd, 1715 gc->inpa = purple_input_add(info->session->fd,
1573 PURPLE_INPUT_READ, 1716 PURPLE_INPUT_READ,
1574 ggp_callback_recv, gc); 1717 ggp_callback_recv, gc);
1575 1718
1719 ggp_buddylist_send(gc);
1720 purple_connection_update_progress(gc, _("Connected"), 2, 2);
1576 purple_connection_set_state(gc, PURPLE_CONNECTED); 1721 purple_connection_set_state(gc, PURPLE_CONNECTED);
1577 ggp_buddylist_send(gc);
1578 } 1722 }
1579 break; 1723 break;
1580 case GG_EVENT_CONN_FAILED: 1724 case GG_EVENT_CONN_FAILED:
1581 purple_input_remove(gc->inpa); 1725 purple_input_remove(gc->inpa);
1582 gc->inpa = 0; 1726 gc->inpa = 0;
1583 purple_connection_error_reason (gc, 1727 purple_connection_error_reason (gc,
1584 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 1728 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1585 _("Connection failed.")); 1729 _("Connection failed"));
1586 break; 1730 break;
1587 default: 1731 default:
1588 purple_debug_error("gg", "strange event: %d\n", ev->type); 1732 purple_debug_error("gg", "strange event: %d\n", ev->type);
1589 break; 1733 break;
1590 } 1734 }
1790 glp->status = ggp_to_gg_status(status, &glp->status_descr); 1934 glp->status = ggp_to_gg_status(status, &glp->status_descr);
1791 glp->tls = 0; 1935 glp->tls = 0;
1792 1936
1793 address = purple_account_get_string(account, "gg_server", ""); 1937 address = purple_account_get_string(account, "gg_server", "");
1794 if (address && *address) { 1938 if (address && *address) {
1939 /* TODO: Make this non-blocking */
1795 struct in_addr *addr = gg_gethostbyname(address); 1940 struct in_addr *addr = gg_gethostbyname(address);
1796 1941
1797 purple_debug_info("gg", "Using gg server given by user (%s)\n", address); 1942 purple_debug_info("gg", "Using gg server given by user (%s)\n", address);
1798 1943
1799 if (addr == NULL) { 1944 if (addr == NULL) {
1800 purple_debug_error("gg", "gg_gethostbyname returned error (%d): %s\n", 1945 gchar *tmp = g_strdup_printf(_("Unable to resolve hostname '%s': %s"),
1801 errno, g_strerror(errno)); 1946 address, g_strerror(errno));
1802 purple_connection_error_reason(gc, 1947 purple_connection_error_reason(gc,
1803 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, /* should this be a settings error? */ 1948 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, /* should this be a settings error? */
1804 _("Unable to resolve server")); 1949 tmp);
1950 g_free(tmp);
1805 return; 1951 return;
1806 } 1952 }
1807 1953
1808 glp->server_addr = inet_addr(inet_ntoa(*addr)); 1954 glp->server_addr = inet_addr(inet_ntoa(*addr));
1809 glp->server_port = 8074; 1955 glp->server_port = 8074;
1810 } else 1956 } else
1811 purple_debug_info("gg", "Trying to retrieve address from gg appmsg service\n"); 1957 purple_debug_info("gg", "Trying to retrieve address from gg appmsg service\n");
1812 1958
1813 info->session = gg_login(glp); 1959 info->session = gg_login(glp);
1960 purple_connection_update_progress(gc, _("Connecting"), 1, 2);
1814 if (info->session == NULL) { 1961 if (info->session == NULL) {
1815 purple_connection_error_reason (gc, 1962 purple_connection_error_reason (gc,
1816 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 1963 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1817 _("Connection failed.")); 1964 _("Connection failed"));
1818 g_free(glp); 1965 g_free(glp);
1819 return; 1966 return;
1820 } 1967 }
1821 gc->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ, 1968 gc->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ,
1822 ggp_async_login_handler, gc); 1969 ggp_async_login_handler, gc);
2187 if (gg_ping(info->session) < 0) { 2334 if (gg_ping(info->session) < 0) {
2188 purple_debug_info("gg", "Not connected to the server " 2335 purple_debug_info("gg", "Not connected to the server "
2189 "or gg_session is not correct\n"); 2336 "or gg_session is not correct\n");
2190 purple_connection_error_reason (gc, 2337 purple_connection_error_reason (gc,
2191 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, 2338 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
2192 _("Not connected to the server.")); 2339 _("Not connected to the server"));
2193 } 2340 }
2194 } 2341 }
2195 2342
2196 static void ggp_register_user(PurpleAccount *account) 2343 static void ggp_register_user(PurpleAccount *account)
2197 { 2344 {