libpurple/protocols/gg/lib/handlers.c

changeset 37181
06b74c255e95
parent 36119
b2ad25dfbd57
parent 37180
cf498d4b54bb
equal deleted inserted replaced
37179:128e4ac12c7b 37181:06b74c255e95
45 45
46 #include <errno.h> 46 #include <errno.h>
47 #include <stdlib.h> 47 #include <stdlib.h>
48 #include <string.h> 48 #include <string.h>
49 #include <time.h> 49 #include <time.h>
50
51 /* Ograniczenie długości listy kontaktów
52 * z pakietów GG_USERLIST_REPLY do 10MB. */
53 #define GG_USERLIST_REPLY_MAX_LENGTH 10485760
50 54
51 /** 55 /**
52 * \internal Struktura opisująca funkcję obsługi pakietu. 56 * \internal Struktura opisująca funkcję obsługi pakietu.
53 */ 57 */
54 typedef struct { 58 typedef struct {
628 unsigned int reply_len = (gs->userlist_reply != NULL) ? strlen(gs->userlist_reply) : 0; 632 unsigned int reply_len = (gs->userlist_reply != NULL) ? strlen(gs->userlist_reply) : 0;
629 char *tmp; 633 char *tmp;
630 634
631 gg_debug_session(gs, GG_DEBUG_MISC, "userlist_reply=%p, len=%" 635 gg_debug_session(gs, GG_DEBUG_MISC, "userlist_reply=%p, len=%"
632 GG_SIZE_FMT "\n", gs->userlist_reply, len); 636 GG_SIZE_FMT "\n", gs->userlist_reply, len);
637
638 if (reply_len + len > GG_USERLIST_REPLY_MAX_LENGTH) {
639 gg_debug_session(gs, GG_DEBUG_MISC,
640 "// gg_session_handle_userlist_reply() "
641 "too many userlist replies\n");
642 return -1;
643 }
633 644
634 tmp = realloc(gs->userlist_reply, reply_len + len); 645 tmp = realloc(gs->userlist_reply, reply_len + len);
635 646
636 if (tmp == NULL) { 647 if (tmp == NULL) {
637 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n"); 648 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
1735 ge->event.notify60[0].uin = 0; 1746 ge->event.notify60[0].uin = 0;
1736 1747
1737 while (length >= sizeof(struct gg_notify_reply80)) { 1748 while (length >= sizeof(struct gg_notify_reply80)) {
1738 uin_t uin = gg_fix32(n->uin); 1749 uin_t uin = gg_fix32(n->uin);
1739 int descr_len; 1750 int descr_len;
1740 char *tmp; 1751 void *tmp;
1741 1752
1742 ge->event.notify60[i].uin = uin; 1753 ge->event.notify60[i].uin = uin;
1743 ge->event.notify60[i].status = gg_fix32(n->status); 1754 ge->event.notify60[i].status = gg_fix32(n->status);
1744 ge->event.notify60[i].remote_ip = n->remote_ip; 1755 ge->event.notify60[i].remote_ip = n->remote_ip;
1745 ge->event.notify60[i].remote_port = gg_fix16(n->remote_port); 1756 ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
1780 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n"); 1791 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
1781 free(ge->event.notify60); 1792 free(ge->event.notify60);
1782 return -1; 1793 return -1;
1783 } 1794 }
1784 1795
1785 ge->event.notify60 = (void*) tmp; 1796 ge->event.notify60 = tmp;
1786 ge->event.notify60[++i].uin = 0; 1797 ge->event.notify60[++i].uin = 0;
1787 } 1798 }
1788 1799
1789 return 0; 1800 return 0;
1790 } 1801 }
1812 1823
1813 ge->event.notify60[0].uin = 0; 1824 ge->event.notify60[0].uin = 0;
1814 1825
1815 while (length >= sizeof(struct gg_notify_reply77)) { 1826 while (length >= sizeof(struct gg_notify_reply77)) {
1816 uin_t uin = gg_fix32(n->uin); 1827 uin_t uin = gg_fix32(n->uin);
1817 char *tmp; 1828 void *tmp;
1818 1829
1819 ge->event.notify60[i].uin = uin & 0x00ffffff; 1830 ge->event.notify60[i].uin = uin & 0x00ffffff;
1820 ge->event.notify60[i].status = n->status; 1831 ge->event.notify60[i].status = n->status;
1821 ge->event.notify60[i].remote_ip = n->remote_ip; 1832 ge->event.notify60[i].remote_ip = n->remote_ip;
1822 ge->event.notify60[i].remote_port = gg_fix16(n->remote_port); 1833 ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
1865 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n"); 1876 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
1866 free(ge->event.notify60); 1877 free(ge->event.notify60);
1867 return -1; 1878 return -1;
1868 } 1879 }
1869 1880
1870 ge->event.notify60 = (void*) tmp; 1881 ge->event.notify60 = tmp;
1871 ge->event.notify60[++i].uin = 0; 1882 ge->event.notify60[++i].uin = 0;
1872 } 1883 }
1873 1884
1874 return 0; 1885 return 0;
1875 } 1886 }
1897 1908
1898 ge->event.notify60[0].uin = 0; 1909 ge->event.notify60[0].uin = 0;
1899 1910
1900 while (length >= sizeof(struct gg_notify_reply60)) { 1911 while (length >= sizeof(struct gg_notify_reply60)) {
1901 uin_t uin = gg_fix32(n->uin); 1912 uin_t uin = gg_fix32(n->uin);
1902 char *tmp; 1913 void *tmp;
1903 1914
1904 ge->event.notify60[i].uin = uin & 0x00ffffff; 1915 ge->event.notify60[i].uin = uin & 0x00ffffff;
1905 ge->event.notify60[i].status = n->status; 1916 ge->event.notify60[i].status = n->status;
1906 ge->event.notify60[i].remote_ip = n->remote_ip; 1917 ge->event.notify60[i].remote_ip = n->remote_ip;
1907 ge->event.notify60[i].remote_port = gg_fix16(n->remote_port); 1918 ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
1952 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n"); 1963 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
1953 free(ge->event.notify60); 1964 free(ge->event.notify60);
1954 return -1; 1965 return -1;
1955 } 1966 }
1956 1967
1957 ge->event.notify60 = (void*) tmp; 1968 ge->event.notify60 = tmp;
1958 ge->event.notify60[++i].uin = 0; 1969 ge->event.notify60[++i].uin = 0;
1959 } 1970 }
1960 1971
1961 return 0; 1972 return 0;
1962 } 1973 }
2358 } 2369 }
2359 2370
2360 static int gg_session_handle_pong_110(struct gg_session *gs, uint32_t type, 2371 static int gg_session_handle_pong_110(struct gg_session *gs, uint32_t type,
2361 const char *ptr, size_t len, struct gg_event *ge) 2372 const char *ptr, size_t len, struct gg_event *ge)
2362 { 2373 {
2363 const struct gg_pong110 *pong = (const struct gg_pong110*)ptr; 2374 GG110Pong *msg = gg110_pong__unpack(NULL, len, (uint8_t*)ptr);
2364 uint32_t server_time; 2375
2376 if (!GG_PROTOBUF_VALID(gs, "GG110Pong", msg))
2377 return -1;
2365 2378
2366 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() " 2379 gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() "
2367 "received pong110\n"); 2380 "received pong110\n");
2368 2381
2369 server_time = gg_fix32(pong->time);
2370
2371 ge->type = GG_EVENT_PONG110; 2382 ge->type = GG_EVENT_PONG110;
2372 ge->event.pong110.time = server_time; 2383 ge->event.pong110.time = msg->server_time;
2373 2384
2374 gg_sync_time(gs, server_time); 2385 gg_sync_time(gs, msg->server_time);
2386
2387 gg110_pong__free_unpacked(msg, NULL);
2375 2388
2376 return 0; 2389 return 0;
2377 } 2390 }
2378 2391
2379 static int gg_session_handle_chat_info(struct gg_session *gs, uint32_t type, 2392 static int gg_session_handle_chat_info(struct gg_session *gs, uint32_t type,
2651 uin_t peer = 0, sender = 0; 2664 uin_t peer = 0, sender = 0;
2652 2665
2653 if (!GG_PROTOBUF_VALID(gs, "GG112TransferInfo", msg)) 2666 if (!GG_PROTOBUF_VALID(gs, "GG112TransferInfo", msg))
2654 return -1; 2667 return -1;
2655 2668
2656 gg_protobuf_expected(gs, "GG112TransferInfo.dummy1", msg->dummy1, 6); 2669 /* see packets.proto */
2670 if (msg->dummy1 != 5 && msg->dummy1 != 6) {
2671 gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_WARNING,
2672 "// gg_session_handle_transfer_info: "
2673 "unknown dummy1 value: %d\n", msg->dummy1);
2674 }
2657 2675
2658 if (GG_PROTOBUF_VALID(gs, "GG112TransferInfoUin", msg->peer)) { 2676 if (GG_PROTOBUF_VALID(gs, "GG112TransferInfoUin", msg->peer)) {
2659 gg_protobuf_expected(gs, "GG112TransferInfoUin.dummy1", 2677 gg_protobuf_expected(gs, "GG112TransferInfoUin.dummy1",
2660 msg->peer->dummy1, 1); 2678 msg->peer->dummy1, 1);
2661 peer = gg_protobuf_get_uin(msg->peer->uin); 2679 peer = gg_protobuf_get_uin(msg->peer->uin);
2680 gg_debug_session(gs, GG_DEBUG_MISC, 2698 gg_debug_session(gs, GG_DEBUG_MISC,
2681 "// gg_session_handle_transfer_info[%s] = \"%s\"\n", 2699 "// gg_session_handle_transfer_info[%s] = \"%s\"\n",
2682 kvp->key, kvp->value); 2700 kvp->key, kvp->value);
2683 } 2701 }
2684 2702
2685 if (GG_PROTOBUF_VALID(gs, "GG112TransferInfoFile", msg->file)) { 2703 if (msg->file && GG_PROTOBUF_VALID(gs, "GG112TransferInfoFile", msg->file)) {
2686 GG112TransferInfoFile *file = msg->file; 2704 GG112TransferInfoFile *file = msg->file;
2687 gg_debug_session(gs, GG_DEBUG_MISC, 2705 gg_debug_session(gs, GG_DEBUG_MISC,
2688 "// gg_session_handle_transfer_info file: " 2706 "// gg_session_handle_transfer_info file: "
2689 "type=\"%s\", content_type=\"%s\", filename=\"%s\", " 2707 "type=\"%s\", content_type=\"%s\", filename=\"%s\", "
2690 "filesize=%u, msg_id=%#016" PRIx64 " url=\"%s\"\n", 2708 "filesize=%u, msg_id=%#016" PRIx64 " url=\"%s\"\n",
2694 2712
2695 succ = (gg_ack_110(gs, GG110_ACK__TYPE__TRANSFER_INFO, 2713 succ = (gg_ack_110(gs, GG110_ACK__TYPE__TRANSFER_INFO,
2696 msg->seq, ge) == 0); 2714 msg->seq, ge) == 0);
2697 2715
2698 gg112_transfer_info__free_unpacked(msg, NULL); 2716 gg112_transfer_info__free_unpacked(msg, NULL);
2717
2718 return succ ? 0 : -1;
2719 }
2720
2721 static int gg_session_handle_magic_notification(struct gg_session *gs, uint32_t type,
2722 const char *ptr, size_t len, struct gg_event *ge)
2723 {
2724 GG110MagicNotification *msg = gg110_magic_notification__unpack(NULL, len, (uint8_t*)ptr);
2725 int succ = 1;
2726
2727 if (!GG_PROTOBUF_VALID(gs, "GG110MagicNotification", msg))
2728 return -1;
2729
2730 gg_debug_session(gs, GG_DEBUG_MISC,
2731 "// gg_session_handle_magic_notification \n");
2732
2733 gg_protobuf_expected(gs, "GG110MagicNotification.dummy1", msg->dummy1, 2);
2734 gg_protobuf_expected(gs, "GG110MagicNotification.dummy2", msg->dummy2, 1);
2735 gg_protobuf_expected(gs, "GG110MagicNotification.dummy3", msg->dummy3, 1);
2736
2737 succ = (gg_ack_110(gs, GG110_ACK__TYPE__MAGIC_NOTIFICATION, msg->seq, ge) == 0);
2738
2739 gg110_magic_notification__free_unpacked(msg, NULL);
2699 2740
2700 return succ ? 0 : -1; 2741 return succ ? 0 : -1;
2701 } 2742 }
2702 2743
2703 /** 2744 /**
2747 { GG_XML_ACTION, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event }, 2788 { GG_XML_ACTION, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
2748 { GG_RECV_OWN_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 }, 2789 { GG_RECV_OWN_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
2749 { GG_USERLIST100_VERSION, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_version), gg_session_handle_userlist_100_version }, 2790 { GG_USERLIST100_VERSION, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_version), gg_session_handle_userlist_100_version },
2750 { GG_USERLIST100_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_reply), gg_session_handle_userlist_100_reply }, 2791 { GG_USERLIST100_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_reply), gg_session_handle_userlist_100_reply },
2751 { GG_IMTOKEN, GG_STATE_CONNECTED, 0, gg_session_handle_imtoken }, 2792 { GG_IMTOKEN, GG_STATE_CONNECTED, 0, gg_session_handle_imtoken },
2752 { GG_PONG110, GG_STATE_CONNECTED, sizeof(struct gg_pong110), gg_session_handle_pong_110 }, 2793 { GG_PONG110, GG_STATE_CONNECTED, 0, gg_session_handle_pong_110 },
2753 { GG_CHAT_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_chat_info }, 2794 { GG_CHAT_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_chat_info },
2754 { GG_CHAT_INFO_UPDATE, GG_STATE_CONNECTED, 0, gg_session_handle_chat_info_update }, 2795 { GG_CHAT_INFO_UPDATE, GG_STATE_CONNECTED, 0, gg_session_handle_chat_info_update },
2755 { GG_CHAT_CREATED, GG_STATE_CONNECTED, sizeof(struct gg_chat_created), gg_session_handle_chat_created }, 2796 { GG_CHAT_CREATED, GG_STATE_CONNECTED, sizeof(struct gg_chat_created), gg_session_handle_chat_created },
2756 { GG_CHAT_INVITE_ACK, GG_STATE_CONNECTED, sizeof(struct gg_chat_invite_ack), gg_session_handle_chat_invite_ack }, 2797 { GG_CHAT_INVITE_ACK, GG_STATE_CONNECTED, sizeof(struct gg_chat_invite_ack), gg_session_handle_chat_invite_ack },
2757 { GG_CHAT_RECV_MSG, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 }, 2798 { GG_CHAT_RECV_MSG, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
2758 { GG_CHAT_RECV_OWN_MSG, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 }, 2799 { GG_CHAT_RECV_OWN_MSG, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
2759 { GG_CHAT_LEFT, GG_STATE_CONNECTED, sizeof(struct gg_chat_left), gg_session_handle_chat_left }, 2800 { GG_CHAT_LEFT, GG_STATE_CONNECTED, sizeof(struct gg_chat_left), gg_session_handle_chat_left },
2760 { GG_OPTIONS, GG_STATE_CONNECTED, 0, gg_session_handle_options }, 2801 { GG_OPTIONS, GG_STATE_CONNECTED, 0, gg_session_handle_options },
2761 { GG_ACCESS_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_access_info }, 2802 { GG_ACCESS_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_access_info },
2762 { GG_UIN_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_uin_info }, 2803 { GG_UIN_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_uin_info },
2763 { GG_TRANSFER_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_transfer_info } 2804 { GG_TRANSFER_INFO, GG_STATE_CONNECTED, 0, gg_session_handle_transfer_info },
2805 { GG_MAGIC_NOTIFICATION, GG_STATE_CONNECTED, 0, gg_session_handle_magic_notification }
2764 /* style:maxlinelength:end-ignore */ 2806 /* style:maxlinelength:end-ignore */
2765 }; 2807 };
2766 2808
2767 /** 2809 /**
2768 * \internal Obsługuje przychodzący pakiet danych. 2810 * \internal Obsługuje przychodzący pakiet danych.

mercurial