Mercurial > pidgin
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 { |