| 1 /* $Id$ */ |
1 /* $Id$ */ |
| 2 |
2 |
| 3 /* |
3 /* |
| 4 * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl> |
4 * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl> |
| 5 * Robert J. Woźny <speedy@ziew.org> |
5 * Robert J. Woźny <speedy@ziew.org> |
| 6 * Arkadiusz Miśkiewicz <arekm@pld-linux.org> |
6 * Arkadiusz Miśkiewicz <arekm@pld-linux.org> |
| 7 * Tomasz Chiliński <chilek@chilan.com> |
7 * Tomasz Chiliński <chilek@chilan.com> |
| 8 * Adam Wysocki <gophi@ekg.chmurka.net> |
8 * Adam Wysocki <gophi@ekg.chmurka.net> |
| 9 * |
9 * |
| 10 * This program is free software; you can redistribute it and/or modify |
10 * This program is free software; you can redistribute it and/or modify |
| 11 * it under the terms of the GNU Lesser General Public License Version |
11 * it under the terms of the GNU Lesser General Public License Version |
| 12 * 2.1 as published by the Free Software Foundation. |
12 * 2.1 as published by the Free Software Foundation. |
| 13 * |
13 * |
| 173 void *ptr; |
167 void *ptr; |
| 174 |
168 |
| 175 ptr = malloc(size); |
169 ptr = malloc(size); |
| 176 if (ptr == NULL) { |
170 if (ptr == NULL) { |
| 177 gg_debug(GG_DEBUG_MISC | GG_DEBUG_ERROR, |
171 gg_debug(GG_DEBUG_MISC | GG_DEBUG_ERROR, |
| 178 "//gg_new0(%zd) not enough memory\n", size); |
172 "//gg_new0(%" GG_SIZE_FMT |
| |
173 ") not enough memory\n", size); |
| 179 return NULL; |
174 return NULL; |
| 180 } |
175 } |
| 181 |
176 |
| 182 memset(ptr, 0, size); |
177 memset(ptr, 0, size); |
| 183 return ptr; |
178 return ptr; |
| 588 |
582 |
| 589 gh = (struct gg_header*) sess->recv_buf; |
583 gh = (struct gg_header*) sess->recv_buf; |
| 590 |
584 |
| 591 if ((size_t) sess->recv_done < sizeof(struct gg_header)) { |
585 if ((size_t) sess->recv_done < sizeof(struct gg_header)) { |
| 592 len = sizeof(struct gg_header) - sess->recv_done; |
586 len = sizeof(struct gg_header) - sess->recv_done; |
| 593 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() header: %d done, %d to go\n", sess->recv_done, len); |
587 gg_debug_session(sess, GG_DEBUG_NET, |
| |
588 "// gg_recv_packet() header: %d done, " |
| |
589 "%" GG_SIZE_FMT " to go\n", |
| |
590 sess->recv_done, len); |
| 594 } else { |
591 } else { |
| 595 uint32_t ghlen = gh ? gg_fix32(gh->length) : 0; |
592 ghlen = gh ? gg_fix32(gh->length) : 0; |
| |
593 |
| |
594 if (ghlen > 65535) { |
| |
595 gg_debug_session(sess, GG_DEBUG_ERROR, |
| |
596 "// gg_recv_packet() invalid packet " |
| |
597 "length (%d)\n", ghlen); |
| |
598 errno = ERANGE; |
| |
599 goto fail; |
| |
600 } |
| |
601 |
| 596 if ((size_t) sess->recv_done >= sizeof(struct gg_header) + ghlen) { |
602 if ((size_t) sess->recv_done >= sizeof(struct gg_header) + ghlen) { |
| 597 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() and that's it\n"); |
603 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() and that's it\n"); |
| 598 break; |
604 break; |
| 599 } |
605 } |
| 600 |
606 |
| 601 len = sizeof(struct gg_header) + ghlen - sess->recv_done; |
607 len = sizeof(struct gg_header) + ghlen - sess->recv_done; |
| 602 |
608 |
| 603 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() payload: %d done, %d length, %d to go\n", sess->recv_done, ghlen, len); |
609 gg_debug_session(sess, GG_DEBUG_NET, |
| |
610 "// gg_recv_packet() payload: %d done, " |
| |
611 "%u length, %" GG_SIZE_FMT " to go\n", |
| |
612 sess->recv_done, ghlen, len); |
| 604 } |
613 } |
| 605 |
614 |
| 606 res = gg_read(sess, sess->recv_buf + sess->recv_done, len); |
615 res = gg_read(sess, sess->recv_buf + sess->recv_done, len); |
| 607 |
616 |
| 608 if (res == 0) { |
617 if (res == 0) { |
| 615 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() resource temporarily unavailable\n"); |
624 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() resource temporarily unavailable\n"); |
| 616 goto eagain; |
625 goto eagain; |
| 617 } |
626 } |
| 618 |
627 |
| 619 if (res == -1) { |
628 if (res == -1) { |
| 620 gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_recv_packet() read failed: errno=%d, %s\n", errno, strerror(errno)); |
629 gg_debug_session(sess, GG_DEBUG_ERROR, |
| |
630 "// gg_recv_packet() read failed: errno=%d, " |
| |
631 "%s\n", errno, strerror(errno)); |
| 621 goto fail; |
632 goto fail; |
| 622 } |
633 } |
| 623 |
634 |
| 624 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() read %d bytes\n", res); |
635 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() read %d bytes\n", res); |
| 625 |
636 |
| 626 if (sess->recv_done + res == sizeof(struct gg_header)) { |
637 if (sess->recv_done + res == sizeof(struct gg_header)) { |
| 627 char *tmp; |
638 char *tmp; |
| 628 uint32_t ghlen = gh ? gg_fix32(gh->length) : 0; |
639 ghlen = gh ? gg_fix32(gh->length) : 0; |
| 629 |
640 |
| 630 gg_debug_session(sess, GG_DEBUG_NET, "// gg_recv_packet() header complete, payload %d bytes\n", ghlen); |
641 gg_debug_session(sess, GG_DEBUG_NET, |
| |
642 "// gg_recv_packet() header complete, " |
| |
643 "payload %d bytes\n", ghlen); |
| 631 |
644 |
| 632 if (ghlen == 0) |
645 if (ghlen == 0) |
| 633 break; |
646 break; |
| 634 |
647 |
| 635 if (ghlen > 65535) { |
648 if (ghlen > 65535) { |
| 636 gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_recv_packet() invalid packet length (%d)\n", ghlen); |
649 gg_debug_session(sess, GG_DEBUG_ERROR, |
| |
650 "// gg_recv_packet() invalid packet " |
| |
651 "length (%d)\n", ghlen); |
| 637 errno = ERANGE; |
652 errno = ERANGE; |
| 638 goto fail; |
653 goto fail; |
| 639 } |
654 } |
| 640 |
655 |
| 641 tmp = realloc(sess->recv_buf, sizeof(struct gg_header) + ghlen + 1); |
656 tmp = realloc(sess->recv_buf, sizeof(struct gg_header) + ghlen + 1); |
| 657 |
672 |
| 658 if (gh == NULL) |
673 if (gh == NULL) |
| 659 goto fail; |
674 goto fail; |
| 660 |
675 |
| 661 /* Czasami zakładamy, że teksty w pakietach są zakończone zerem */ |
676 /* Czasami zakładamy, że teksty w pakietach są zakończone zerem */ |
| 662 packet[sizeof(struct gg_header) + gg_fix32(gh->length)] = 0; |
677 packet[sizeof(struct gg_header) + ghlen] = 0; |
| 663 |
678 |
| 664 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet(type=0x%.2x, length=%d)\n", gg_fix32(gh->type), gg_fix32(gh->length)); |
679 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet(type=0x%.2x, " |
| 665 gg_debug_dump(sess, GG_DEBUG_DUMP, packet, sizeof(struct gg_header) + gg_fix32(gh->length)); |
680 "length=%d)\n", gg_fix32(gh->type), ghlen); |
| |
681 gg_debug_dump(sess, GG_DEBUG_DUMP, packet, sizeof(struct gg_header) + ghlen); |
| 666 |
682 |
| 667 gh->type = gg_fix32(gh->type); |
683 gh->type = gg_fix32(gh->type); |
| 668 gh->length = gg_fix32(gh->length); |
684 gh->length = ghlen; |
| 669 |
685 |
| 670 return packet; |
686 return packet; |
| 671 |
687 |
| 672 fail: |
688 fail: |
| 673 free(sess->recv_buf); |
689 free(sess->recv_buf); |
| 686 * część zostanie zakolejkowana i wysłana, gdy będzie to możliwe. |
702 * część zostanie zakolejkowana i wysłana, gdy będzie to możliwe. |
| 687 * |
703 * |
| 688 * \param sess Struktura sesji |
704 * \param sess Struktura sesji |
| 689 * \param type Rodzaj pakietu |
705 * \param type Rodzaj pakietu |
| 690 * \param ... Lista kolejnych części pakietu (wskaźnik na bufor i długość |
706 * \param ... Lista kolejnych części pakietu (wskaźnik na bufor i długość |
| 691 * typu \c int) zakończona \c NULL |
707 * typu \c int) zakończona \c NULL |
| 692 * |
708 * |
| 693 * \return 0 jeśli się powiodło, -1 w przypadku błędu |
709 * \return 0 jeśli się powiodło, -1 w przypadku błędu |
| 694 */ |
710 */ |
| 695 int gg_send_packet(struct gg_session *sess, int type, ...) |
711 int gg_send_packet(struct gg_session *sess, int type, ...) |
| 696 { |
712 { |
| 739 |
755 |
| 740 h = (struct gg_header*) tmp; |
756 h = (struct gg_header*) tmp; |
| 741 h->type = gg_fix32(type); |
757 h->type = gg_fix32(type); |
| 742 h->length = gg_fix32(tmp_length - sizeof(struct gg_header)); |
758 h->length = gg_fix32(tmp_length - sizeof(struct gg_header)); |
| 743 |
759 |
| 744 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet(type=0x%.2x, length=%d)\n", gg_fix32(h->type), gg_fix32(h->length)); |
760 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet(type=0x%.2x, " |
| |
761 "length=%d)\n", gg_fix32(h->type), gg_fix32(h->length)); |
| 745 gg_debug_dump(sess, GG_DEBUG_DUMP, tmp, tmp_length); |
762 gg_debug_dump(sess, GG_DEBUG_DUMP, tmp, tmp_length); |
| 746 |
763 |
| 747 res = gg_write(sess, tmp, tmp_length); |
764 res = gg_write(sess, tmp, tmp_length); |
| 748 |
765 |
| 749 free(tmp); |
766 free(tmp); |
| 750 |
767 |
| 751 if (res == -1) { |
768 if (res == -1) { |
| 752 gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); |
769 gg_debug_session(sess, GG_DEBUG_ERROR, "// gg_send_packet() " |
| 753 return -1; |
770 "write() failed. res = %d, errno = %d (%s)\n", |
| 754 } |
771 res, errno, strerror(errno)); |
| 755 |
772 return -1; |
| 756 if (sess->async) |
773 } |
| 757 gg_debug_session(sess, GG_DEBUG_NET, "// gg_send_packet() partial write(), %d sent, %d left, %d total left\n", res, tmp_length - res, sess->send_left); |
774 |
| |
775 if (sess->async) { |
| |
776 gg_debug_session(sess, GG_DEBUG_NET, "// gg_send_packet() " |
| |
777 "partial write(), %d sent, %d left, %d total left\n", |
| |
778 res, tmp_length - res, sess->send_left); |
| |
779 } |
| 758 |
780 |
| 759 if (sess->send_buf) |
781 if (sess->send_buf) |
| 760 sess->check |= GG_CHECK_WRITE; |
782 sess->check |= GG_CHECK_WRITE; |
| 761 |
783 |
| 762 return 0; |
784 return 0; |
| 808 * |
830 * |
| 809 * \note Funkcja zwróci błąd ENOSYS jeśli połączenie SSL było wymagane, ale |
831 * \note Funkcja zwróci błąd ENOSYS jeśli połączenie SSL było wymagane, ale |
| 810 * obsługa SSL nie jest wkompilowana. |
832 * obsługa SSL nie jest wkompilowana. |
| 811 * |
833 * |
| 812 * \param p Struktura opisująca parametry połączenia. Wymagane pola: uin, |
834 * \param p Struktura opisująca parametry połączenia. Wymagane pola: uin, |
| 813 * password, async. |
835 * password, async. |
| 814 * |
836 * |
| 815 * \return Wskaźnik do zaalokowanej struktury sesji \c gg_session lub NULL |
837 * \return Wskaźnik do zaalokowanej struktury sesji \c gg_session lub NULL |
| 816 * w przypadku błędu. |
838 * w przypadku błędu. |
| 817 * |
839 * |
| 818 * \ingroup login |
840 * \ingroup login |
| 819 */ |
841 */ |
| 820 struct gg_session *gg_login(const struct gg_login_params *p) |
842 struct gg_session *gg_login(const struct gg_login_params *p) |
| 821 { |
843 { |
| 926 sess_private->socket_manager_type = |
948 sess_private->socket_manager_type = |
| 927 GG_SOCKET_MANAGER_TYPE_INTERNAL; |
949 GG_SOCKET_MANAGER_TYPE_INTERNAL; |
| 928 } |
950 } |
| 929 |
951 |
| 930 if (GG_LOGIN_PARAMS_HAS_FIELD(p, host_white_list) && |
952 if (GG_LOGIN_PARAMS_HAS_FIELD(p, host_white_list) && |
| 931 p->host_white_list != NULL) { |
953 p->host_white_list != NULL) |
| |
954 { |
| 932 sess_private->host_white_list = |
955 sess_private->host_white_list = |
| 933 gg_strarr_dup(p->host_white_list); |
956 gg_strarr_dup(p->host_white_list); |
| 934 if (sess_private->host_white_list == NULL) |
957 if (sess_private->host_white_list == NULL) |
| 935 goto fail; |
958 goto fail; |
| 936 } |
959 } |
| 937 |
960 |
| 938 if (p->protocol_features == 0) { |
961 if (p->protocol_features == 0) { |
| 939 sess->protocol_features = GG_FEATURE_MSG80 | GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC | GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 | GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | GG_FEATURE_TYPING_NOTIFICATION; |
962 sess->protocol_features = GG_FEATURE_MSG80 | |
| |
963 GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC | |
| |
964 GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 | |
| |
965 GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | |
| |
966 GG_FEATURE_TYPING_NOTIFICATION; |
| 940 } else { |
967 } else { |
| 941 sess->protocol_features = (p->protocol_features & ~(GG_FEATURE_STATUS77 | GG_FEATURE_MSG77)); |
968 sess->protocol_features = (p->protocol_features & ~(GG_FEATURE_STATUS77 | GG_FEATURE_MSG77)); |
| 942 |
969 |
| 943 if (!(p->protocol_features & GG_FEATURE_STATUS77)) |
970 if (!(p->protocol_features & GG_FEATURE_STATUS77)) |
| 944 sess->protocol_features |= GG_FEATURE_STATUS80; |
971 sess->protocol_features |= GG_FEATURE_STATUS80; |
| 963 sess->image_size = p->image_size; |
990 sess->image_size = p->image_size; |
| 964 sess->pid = -1; |
991 sess->pid = -1; |
| 965 sess->encoding = p->encoding; |
992 sess->encoding = p->encoding; |
| 966 |
993 |
| 967 if (gg_session_set_resolver(sess, p->resolver) == -1) { |
994 if (gg_session_set_resolver(sess, p->resolver) == -1) { |
| 968 gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unsupported resolver type (%d)\n", p->resolver); |
995 gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. " |
| |
996 "unsupported resolver type (%d)\n", p->resolver); |
| 969 errno = EFAULT; |
997 errno = EFAULT; |
| 970 goto fail; |
998 goto fail; |
| 971 } |
999 } |
| 972 |
1000 |
| 973 if (p->status_descr) { |
1001 if (p->status_descr) { |
| 975 |
1003 |
| 976 if (!sess->initial_descr) { |
1004 if (!sess->initial_descr) { |
| 977 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n"); |
1005 gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n"); |
| 978 goto fail; |
1006 goto fail; |
| 979 } |
1007 } |
| 980 |
1008 |
| 981 /* XXX pamiętać, żeby nie ciąć w środku znaku utf-8 */ |
1009 /* XXX pamiętać, żeby nie ciąć w środku znaku utf-8 */ |
| 982 |
1010 |
| 983 if (strlen(sess->initial_descr) > GG_STATUS_DESCR_MAXSIZE) |
1011 if (strlen(sess->initial_descr) > GG_STATUS_DESCR_MAXSIZE) |
| 984 sess->initial_descr[GG_STATUS_DESCR_MAXSIZE] = 0; |
1012 sess->initial_descr[GG_STATUS_DESCR_MAXSIZE] = 0; |
| 985 } |
1013 } |
| 986 |
1014 |
| 987 if (p->tls != GG_SSL_DISABLED) { |
1015 if (p->tls != GG_SSL_DISABLED) { |
| 1004 |
1032 |
| 1005 if (sess->server_addr == 0 && sess->connect_host == NULL) { |
1033 if (sess->server_addr == 0 && sess->connect_host == NULL) { |
| 1006 if (gg_proxy_enabled) { |
1034 if (gg_proxy_enabled) { |
| 1007 sess->resolver_host = gg_proxy_host; |
1035 sess->resolver_host = gg_proxy_host; |
| 1008 sess->proxy_port = gg_proxy_port; |
1036 sess->proxy_port = gg_proxy_port; |
| 1009 sess->state = (sess->async) ? GG_STATE_RESOLVE_PROXY_HUB_ASYNC : GG_STATE_RESOLVE_PROXY_HUB_SYNC; |
1037 sess->state = (sess->async) ? |
| |
1038 GG_STATE_RESOLVE_PROXY_HUB_ASYNC : |
| |
1039 GG_STATE_RESOLVE_PROXY_HUB_SYNC; |
| 1010 } else { |
1040 } else { |
| 1011 sess->resolver_host = GG_APPMSG_HOST; |
1041 sess->resolver_host = GG_APPMSG_HOST; |
| 1012 sess->proxy_port = 0; |
1042 sess->proxy_port = 0; |
| 1013 sess->state = (sess->async) ? GG_STATE_RESOLVE_HUB_ASYNC : GG_STATE_RESOLVE_HUB_SYNC; |
1043 sess->state = (sess->async) ? GG_STATE_RESOLVE_HUB_ASYNC : GG_STATE_RESOLVE_HUB_SYNC; |
| 1014 } |
1044 } |
| 1015 } else { |
1045 } else { |
| 1016 if (sess->connect_host != NULL) |
1046 if (sess->connect_host != NULL) |
| 1017 sess->server_addr = 0; |
1047 sess->server_addr = 0; |
| 1018 else { |
1048 else { |
| 1019 // XXX inet_ntoa i wielowątkowość |
1049 /* XXX inet_ntoa i wielowątkowość */ |
| 1020 sess->connect_host = strdup(inet_ntoa(*(struct in_addr*) &sess->server_addr)); |
1050 sess->connect_host = strdup(inet_ntoa(*(struct in_addr*) &sess->server_addr)); |
| 1021 if (sess->connect_host == NULL) |
1051 if (sess->connect_host == NULL) |
| 1022 goto fail; |
1052 goto fail; |
| 1023 } |
1053 } |
| 1024 sess->connect_index = 0; |
1054 sess->connect_index = 0; |
| 1048 } |
1078 } |
| 1049 sess->state = (sess->async) ? GG_STATE_RESOLVE_GG_ASYNC : GG_STATE_RESOLVE_GG_SYNC; |
1079 sess->state = (sess->async) ? GG_STATE_RESOLVE_GG_ASYNC : GG_STATE_RESOLVE_GG_SYNC; |
| 1050 } |
1080 } |
| 1051 } |
1081 } |
| 1052 |
1082 |
| 1053 // XXX inaczej gg_watch_fd() wyjdzie z timeoutem |
1083 /* XXX inaczej gg_watch_fd() wyjdzie z timeoutem */ |
| 1054 sess->timeout = GG_DEFAULT_TIMEOUT; |
1084 sess->timeout = GG_DEFAULT_TIMEOUT; |
| 1055 |
1085 |
| 1056 if (!sess->async) { |
1086 if (!sess->async) { |
| 1057 while (!GG_SESSION_IS_CONNECTED(sess)) { |
1087 while (!GG_SESSION_IS_CONNECTED(sess)) { |
| 1058 struct gg_event *ge; |
1088 struct gg_event *ge; |
| 1220 |
1248 |
| 1221 if (sess->ssl_ctx) |
1249 if (sess->ssl_ctx) |
| 1222 SSL_CTX_free(sess->ssl_ctx); |
1250 SSL_CTX_free(sess->ssl_ctx); |
| 1223 #endif |
1251 #endif |
| 1224 |
1252 |
| 1225 sess->resolver_cleanup(&sess->resolver, 1); |
1253 if (sess->resolver_cleanup != NULL) |
| |
1254 sess->resolver_cleanup(&sess->resolver, 1); |
| 1226 |
1255 |
| 1227 gg_close(sess); |
1256 gg_close(sess); |
| 1228 |
1257 |
| 1229 while (sess->images) |
1258 while (sess->images) { |
| |
1259 struct gg_image_queue *next = sess->images->next; |
| |
1260 |
| 1230 gg_image_queue_remove(sess, sess->images, 1); |
1261 gg_image_queue_remove(sess, sess->images, 1); |
| |
1262 |
| |
1263 /* a fix for false-positive NULL-dereference */ |
| |
1264 sess->images = next; |
| |
1265 } |
| 1231 |
1266 |
| 1232 free(sess->send_buf); |
1267 free(sess->send_buf); |
| 1233 |
1268 |
| 1234 for (dcc = sess->dcc7_list; dcc; dcc = dcc->next) |
1269 for (dcc = sess->dcc7_list; dcc; dcc = dcc->next) |
| 1235 dcc->sess = NULL; |
1270 dcc->sess = NULL; |
| 1324 if (sess->protocol_version >= GG_PROTOCOL_VERSION_110) { |
1359 if (sess->protocol_version >= GG_PROTOCOL_VERSION_110) { |
| 1325 p.flags = gg_fix32(0x00000014); |
1360 p.flags = gg_fix32(0x00000014); |
| 1326 descr_null_len = 1; |
1361 descr_null_len = 1; |
| 1327 } |
1362 } |
| 1328 |
1363 |
| 1329 res = gg_send_packet(sess, GG_NEW_STATUS80, |
1364 res = gg_send_packet(sess, GG_NEW_STATUS80, |
| 1330 &p, sizeof(p), |
1365 &p, sizeof(p), descr, descr_len, |
| 1331 descr, descr_len, |
1366 "\x00", descr_null_len, NULL); |
| 1332 "\x00", descr_null_len, |
|
| 1333 NULL); |
|
| 1334 |
1367 |
| 1335 free(gen_descr); |
1368 free(gen_descr); |
| 1336 |
1369 |
| 1337 if (GG_S_NA(status)) { |
1370 if (GG_S_NA(status)) { |
| 1338 sess->state = GG_STATE_DISCONNECTING; |
1371 sess->state = GG_STATE_DISCONNECTING; |
| 1354 * |
1387 * |
| 1355 * \ingroup status |
1388 * \ingroup status |
| 1356 */ |
1389 */ |
| 1357 int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int ts) |
1390 int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int ts) |
| 1358 { |
1391 { |
| 1359 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, ts); |
1392 gg_debug_session(sess, GG_DEBUG_FUNCTION, |
| |
1393 "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", |
| |
1394 sess, status, descr, ts); |
| 1360 |
1395 |
| 1361 return gg_change_status_descr(sess, status, descr); |
1396 return gg_change_status_descr(sess, status, descr); |
| 1362 } |
1397 } |
| 1363 |
1398 |
| 1364 /** |
1399 /** |
| 1400 char *html_message_gen = NULL, *plain_message_gen = NULL; |
1435 char *html_message_gen = NULL, *plain_message_gen = NULL; |
| 1401 const char *html_message, *plain_message; |
1436 const char *html_message, *plain_message; |
| 1402 int succ = 1; |
1437 int succ = 1; |
| 1403 |
1438 |
| 1404 gg_debug_session(sess, GG_DEBUG_FUNCTION, |
1439 gg_debug_session(sess, GG_DEBUG_FUNCTION, |
| 1405 "** gg_send_message_110(%p, %u, %llu, %p, %d);\n", |
1440 "** gg_send_message_110(%p, %u, %" PRIu64 ", %p, %d);\n", |
| 1406 sess, recipient, chat_id, message, is_html); |
1441 sess, recipient, chat_id, message, is_html); |
| 1407 |
1442 |
| 1408 if (message == NULL) |
1443 if (message == NULL) |
| 1409 return -1; |
1444 return -1; |
| 1410 |
1445 |
| 1436 plain_message, sess->encoding, GG_ENCODING_UTF8, |
1471 plain_message, sess->encoding, GG_ENCODING_UTF8, |
| 1437 -1, -1); |
1472 -1, -1); |
| 1438 if (plain_message_gen == NULL) |
1473 if (plain_message_gen == NULL) |
| 1439 return -1; |
1474 return -1; |
| 1440 } |
1475 } |
| 1441 |
1476 |
| 1442 html_message = html_message_gen = |
1477 html_message = html_message_gen = |
| 1443 gg_message_text_to_html_110(plain_message, -1); |
1478 gg_message_text_to_html_110(plain_message, -1); |
| 1444 if (html_message_gen == NULL) { |
1479 if (html_message_gen == NULL) { |
| 1445 free(plain_message_gen); |
1480 free(plain_message_gen); |
| 1446 return -1; |
1481 return -1; |
| 1492 * |
1527 * |
| 1493 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
1528 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
| 1494 * |
1529 * |
| 1495 * \ingroup messages |
1530 * \ingroup messages |
| 1496 */ |
1531 */ |
| 1497 static int gg_send_message_common(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen, const unsigned char *html_message) |
1532 static int gg_send_message_common(struct gg_session *sess, int msgclass, |
| |
1533 int recipients_count, uin_t *recipients, const unsigned char *message, |
| |
1534 const unsigned char *format, int formatlen, |
| |
1535 const unsigned char *html_message) |
| 1498 { |
1536 { |
| 1499 struct gg_send_msg80 s80; |
1537 struct gg_send_msg80 s80; |
| 1500 const char *cp_msg = NULL, *utf_html_msg = NULL; |
1538 const char *cp_msg = NULL, *utf_html_msg = NULL; |
| 1501 char *recoded_msg = NULL, *recoded_html_msg = NULL; |
1539 char *recoded_msg = NULL, *recoded_html_msg = NULL; |
| 1502 unsigned char *generated_format = NULL; |
1540 unsigned char *generated_format = NULL; |
| 1503 int seq_no = -1; |
1541 int seq_no = -1; |
| 1504 |
1542 |
| 1505 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_common(%p, %d, %d, %p, %p, %p, %d, %p);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen, html_message); |
1543 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_common(" |
| |
1544 "%p, %d, %d, %p, %p, %p, %d, %p);\n", sess, msgclass, |
| |
1545 recipients_count, recipients, message, format, |
| |
1546 formatlen, html_message); |
| 1506 |
1547 |
| 1507 if (!sess) { |
1548 if (!sess) { |
| 1508 errno = EFAULT; |
1549 errno = EFAULT; |
| 1509 return -1; |
1550 return -1; |
| 1510 } |
1551 } |
| 1512 if (sess->state != GG_STATE_CONNECTED) { |
1553 if (sess->state != GG_STATE_CONNECTED) { |
| 1513 errno = ENOTCONN; |
1554 errno = ENOTCONN; |
| 1514 return -1; |
1555 return -1; |
| 1515 } |
1556 } |
| 1516 |
1557 |
| 1517 if ((message == NULL && html_message == NULL) || recipients_count <= 0 || recipients_count > 0xffff || recipients == NULL || (format == NULL && formatlen != 0)) { |
1558 if ((message == NULL && html_message == NULL) || |
| |
1559 recipients_count <= 0 || recipients_count > 0xffff || |
| |
1560 recipients == NULL || (format == NULL && formatlen != 0)) |
| |
1561 { |
| 1518 errno = EINVAL; |
1562 errno = EINVAL; |
| 1519 return -1; |
1563 return -1; |
| 1520 } |
1564 } |
| 1521 |
1565 |
| 1522 if (sess->protocol_version >= GG_PROTOCOL_VERSION_110 && recipients_count == 1) |
1566 if (sess->protocol_version >= GG_PROTOCOL_VERSION_110 && |
| |
1567 recipients_count == 1) |
| 1523 { |
1568 { |
| 1524 int is_html = (html_message != NULL); |
1569 int is_html = (html_message != NULL); |
| 1525 seq_no = gg_send_message_110(sess, recipients[0], 0, |
1570 seq_no = gg_send_message_110(sess, recipients[0], 0, |
| 1526 (const char*)(is_html ? html_message : message), |
1571 (const char*)(is_html ? html_message : message), |
| 1527 is_html); |
1572 is_html); |
| 1528 goto cleanup; |
1573 goto cleanup; |
| 1529 } |
1574 } |
| 1530 |
1575 |
| 1531 if (sess->protocol_version >= GG_PROTOCOL_VERSION_110 && !gg_compat_feature_is_enabled(sess, GG_COMPAT_FEATURE_LEGACY_CONFER)) { |
1576 if (sess->protocol_version >= GG_PROTOCOL_VERSION_110 && |
| 1532 gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR, "// gg_send_message_common() legacy conferences disabled\n"); |
1577 !gg_compat_feature_is_enabled(sess, GG_COMPAT_FEATURE_LEGACY_CONFER)) |
| |
1578 { |
| |
1579 gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_ERROR, |
| |
1580 "// gg_send_message_common() legacy conferences disabled\n"); |
| 1533 errno = EINVAL; |
1581 errno = EINVAL; |
| 1534 return -1; |
1582 return -1; |
| 1535 } |
1583 } |
| 1536 |
1584 |
| 1537 if (message == NULL) { |
1585 if (message == NULL) { |
| 1555 } |
1603 } |
| 1556 |
1604 |
| 1557 generated_format[0] = '\x02'; |
1605 generated_format[0] = '\x02'; |
| 1558 fixed_fmt_len = gg_fix16(fmt_len); |
1606 fixed_fmt_len = gg_fix16(fmt_len); |
| 1559 memcpy(generated_format + 1, &fixed_fmt_len, sizeof(fixed_fmt_len)); |
1607 memcpy(generated_format + 1, &fixed_fmt_len, sizeof(fixed_fmt_len)); |
| 1560 gg_message_html_to_text(tmp_msg, generated_format + 3, NULL, (const char*) html_message, sess->encoding); |
1608 gg_message_html_to_text(tmp_msg, generated_format + 3, |
| |
1609 NULL, (const char*)html_message, sess->encoding); |
| 1561 |
1610 |
| 1562 format = generated_format; |
1611 format = generated_format; |
| 1563 formatlen = fmt_len + 3; |
1612 formatlen = fmt_len + 3; |
| 1564 } else { |
1613 } else { |
| 1565 gg_message_html_to_text(tmp_msg, NULL, NULL, (const char*) html_message, sess->encoding); |
1614 gg_message_html_to_text(tmp_msg, NULL, NULL, (const char*) html_message, sess->encoding); |
| 1577 } else { |
1626 } else { |
| 1578 cp_msg = recoded_msg = tmp_msg; |
1627 cp_msg = recoded_msg = tmp_msg; |
| 1579 } |
1628 } |
| 1580 } else { |
1629 } else { |
| 1581 if (sess->encoding == GG_ENCODING_UTF8) { |
1630 if (sess->encoding == GG_ENCODING_UTF8) { |
| 1582 cp_msg = recoded_msg = gg_encoding_convert((const char*) message, sess->encoding, GG_ENCODING_CP1250, -1, -1); |
1631 cp_msg = recoded_msg = gg_encoding_convert( |
| |
1632 (const char*)message, sess->encoding, |
| |
1633 GG_ENCODING_CP1250, -1, -1); |
| 1583 |
1634 |
| 1584 if (cp_msg == NULL) |
1635 if (cp_msg == NULL) |
| 1585 goto cleanup; |
1636 goto cleanup; |
| 1586 } else { |
1637 } else { |
| 1587 cp_msg = (const char*) message; |
1638 cp_msg = (const char*) message; |
| 1596 size_t formatlen_ = 0; |
1647 size_t formatlen_ = 0; |
| 1597 |
1648 |
| 1598 if (sess->encoding == GG_ENCODING_UTF8) { |
1649 if (sess->encoding == GG_ENCODING_UTF8) { |
| 1599 utf_msg = (const char*) message; |
1650 utf_msg = (const char*) message; |
| 1600 } else { |
1651 } else { |
| 1601 utf_msg = recoded_msg = gg_encoding_convert((const char*) message, sess->encoding, GG_ENCODING_UTF8, -1, -1); |
1652 utf_msg = recoded_msg = gg_encoding_convert( |
| |
1653 (const char*)message, sess->encoding, |
| |
1654 GG_ENCODING_UTF8, -1, -1); |
| 1602 |
1655 |
| 1603 if (utf_msg == NULL) |
1656 if (utf_msg == NULL) |
| 1604 goto cleanup; |
1657 goto cleanup; |
| 1605 } |
1658 } |
| 1606 |
1659 |
| 1621 utf_html_msg = recoded_html_msg = tmp; |
1674 utf_html_msg = recoded_html_msg = tmp; |
| 1622 } else { |
1675 } else { |
| 1623 if (sess->encoding == GG_ENCODING_UTF8) { |
1676 if (sess->encoding == GG_ENCODING_UTF8) { |
| 1624 utf_html_msg = (const char*) html_message; |
1677 utf_html_msg = (const char*) html_message; |
| 1625 } else { |
1678 } else { |
| 1626 utf_html_msg = recoded_html_msg = gg_encoding_convert((const char*) html_message, sess->encoding, GG_ENCODING_UTF8, -1, -1); |
1679 utf_html_msg = recoded_html_msg = gg_encoding_convert( |
| |
1680 (const char*)html_message, sess->encoding, |
| |
1681 GG_ENCODING_UTF8, -1, -1); |
| 1627 |
1682 |
| 1628 if (utf_html_msg == NULL) |
1683 if (utf_html_msg == NULL) |
| 1629 goto cleanup; |
1684 goto cleanup; |
| 1630 } |
1685 } |
| 1631 } |
1686 } |
| 1670 } |
1725 } |
| 1671 } |
1726 } |
| 1672 |
1727 |
| 1673 s80.recipient = gg_fix32(recipients[i]); |
1728 s80.recipient = gg_fix32(recipients[i]); |
| 1674 |
1729 |
| 1675 if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), utf_html_msg, strlen(utf_html_msg) + 1, cp_msg, strlen(cp_msg) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1) |
1730 if (gg_send_packet(sess, GG_SEND_MSG80, &s80, |
| |
1731 sizeof(s80), utf_html_msg, |
| |
1732 strlen(utf_html_msg) + 1, cp_msg, |
| |
1733 strlen(cp_msg) + 1, &r, sizeof(r), recps, |
| |
1734 (recipients_count - 1) * sizeof(uin_t), format, |
| |
1735 formatlen, NULL) == -1) |
| |
1736 { |
| 1676 seq_no = -1; |
1737 seq_no = -1; |
| |
1738 } |
| 1677 } |
1739 } |
| 1678 |
1740 |
| 1679 free(recps); |
1741 free(recps); |
| 1680 } else { |
1742 } else { |
| 1681 s80.recipient = gg_fix32(recipients[0]); |
1743 s80.recipient = gg_fix32(recipients[0]); |
| 1682 |
1744 |
| 1683 if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), utf_html_msg, strlen(utf_html_msg) + 1, cp_msg, strlen(cp_msg) + 1, format, formatlen, NULL) == -1) |
1745 if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), |
| |
1746 utf_html_msg, strlen(utf_html_msg) + 1, cp_msg, |
| |
1747 strlen(cp_msg) + 1, format, formatlen, NULL) == -1) |
| |
1748 { |
| 1684 seq_no = -1; |
1749 seq_no = -1; |
| |
1750 } |
| 1685 } |
1751 } |
| 1686 |
1752 |
| 1687 cleanup: |
1753 cleanup: |
| 1688 free(recoded_msg); |
1754 free(recoded_msg); |
| 1689 free(recoded_html_msg); |
1755 free(recoded_html_msg); |
| 1712 * |
1778 * |
| 1713 * \ingroup messages |
1779 * \ingroup messages |
| 1714 */ |
1780 */ |
| 1715 int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message) |
1781 int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message) |
| 1716 { |
1782 { |
| 1717 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message); |
1783 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, " |
| 1718 |
1784 "%u, %p)\n", sess, msgclass, recipient, message); |
| 1719 return gg_send_message_common(sess, msgclass, 1, &recipient, message, (const unsigned char*) "\x02\x06\x00\x00\x00\x08\x00\x00\x00", 9, NULL); |
1785 |
| |
1786 return gg_send_message_common(sess, msgclass, 1, &recipient, message, |
| |
1787 (const unsigned char*)"\x02\x06\x00\x00\x00\x08\x00\x00\x00", |
| |
1788 9, NULL); |
| 1720 } |
1789 } |
| 1721 |
1790 |
| 1722 /** |
1791 /** |
| 1723 * Wysyła wiadomość formatowaną. |
1792 * Wysyła wiadomość formatowaną. |
| 1724 * |
1793 * |
| 1734 * |
1803 * |
| 1735 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
1804 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
| 1736 * |
1805 * |
| 1737 * \ingroup messages |
1806 * \ingroup messages |
| 1738 */ |
1807 */ |
| 1739 int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen) |
1808 int gg_send_message_richtext(struct gg_session *sess, int msgclass, |
| 1740 { |
1809 uin_t recipient, const unsigned char *message, |
| 1741 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen); |
1810 const unsigned char *format, int formatlen) |
| |
1811 { |
| |
1812 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_richtext(" |
| |
1813 "%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, |
| |
1814 message, format, formatlen); |
| 1742 |
1815 |
| 1743 return gg_send_message_common(sess, msgclass, 1, &recipient, message, format, formatlen, NULL); |
1816 return gg_send_message_common(sess, msgclass, 1, &recipient, message, format, formatlen, NULL); |
| 1744 } |
1817 } |
| 1745 |
1818 |
| 1746 /** |
1819 /** |
| 1758 * |
1831 * |
| 1759 * \ingroup messages |
1832 * \ingroup messages |
| 1760 */ |
1833 */ |
| 1761 int gg_send_message_html(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *html_message) |
1834 int gg_send_message_html(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *html_message) |
| 1762 { |
1835 { |
| 1763 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_html(%p, %d, %u, %p);\n", sess, msgclass, recipient, html_message); |
1836 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_html(%p, " |
| |
1837 "%d, %u, %p);\n", sess, msgclass, recipient, html_message); |
| 1764 |
1838 |
| 1765 return gg_send_message_common(sess, msgclass, 1, &recipient, NULL, NULL, 0, html_message); |
1839 return gg_send_message_common(sess, msgclass, 1, &recipient, NULL, NULL, 0, html_message); |
| 1766 } |
1840 } |
| 1767 |
1841 |
| 1768 /** |
1842 /** |
| 1779 * |
1853 * |
| 1780 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
1854 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
| 1781 * |
1855 * |
| 1782 * \ingroup messages |
1856 * \ingroup messages |
| 1783 */ |
1857 */ |
| 1784 int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message) |
1858 int gg_send_message_confer(struct gg_session *sess, int msgclass, |
| 1785 { |
1859 int recipients_count, uin_t *recipients, const unsigned char *message) |
| 1786 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message); |
1860 { |
| 1787 |
1861 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer(" |
| 1788 return gg_send_message_common(sess, msgclass, recipients_count, recipients, message, (const unsigned char*) "\x02\x06\x00\x00\x00\x08\x00\x00\x00", 9, NULL); |
1862 "%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, |
| |
1863 recipients, message); |
| |
1864 |
| |
1865 return gg_send_message_common(sess, msgclass, recipients_count, |
| |
1866 recipients, message, |
| |
1867 (const unsigned char*)"\x02\x06\x00\x00\x00\x08\x00\x00\x00", |
| |
1868 9, NULL); |
| 1789 } |
1869 } |
| 1790 |
1870 |
| 1791 /** |
1871 /** |
| 1792 * Wysyła wiadomość formatowaną w ramach konferencji. |
1872 * Wysyła wiadomość formatowaną w ramach konferencji. |
| 1793 * |
1873 * |
| 1804 * |
1884 * |
| 1805 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
1885 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
| 1806 * |
1886 * |
| 1807 * \ingroup messages |
1887 * \ingroup messages |
| 1808 */ |
1888 */ |
| 1809 int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen) |
1889 int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, |
| 1810 { |
1890 int recipients_count, uin_t *recipients, const unsigned char *message, |
| 1811 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen); |
1891 const unsigned char *format, int formatlen) |
| |
1892 { |
| |
1893 gg_debug_session(sess, GG_DEBUG_FUNCTION, |
| |
1894 "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, " |
| |
1895 "%d);\n", sess, msgclass, recipients_count, recipients, message, |
| |
1896 format, formatlen); |
| 1812 |
1897 |
| 1813 return gg_send_message_common(sess, msgclass, recipients_count, recipients, message, format, formatlen, NULL); |
1898 return gg_send_message_common(sess, msgclass, recipients_count, recipients, message, format, formatlen, NULL); |
| 1814 } |
1899 } |
| 1815 |
1900 |
| 1816 /** |
1901 /** |
| 1827 * |
1912 * |
| 1828 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
1913 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
| 1829 * |
1914 * |
| 1830 * \ingroup messages |
1915 * \ingroup messages |
| 1831 */ |
1916 */ |
| 1832 int gg_send_message_confer_html(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *html_message) |
1917 int gg_send_message_confer_html(struct gg_session *sess, int msgclass, |
| 1833 { |
1918 int recipients_count, uin_t *recipients, |
| 1834 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer_html(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, html_message); |
1919 const unsigned char *html_message) |
| |
1920 { |
| |
1921 gg_debug_session(sess, GG_DEBUG_FUNCTION, |
| |
1922 "** gg_send_message_confer_html(%p, %d, %d, %p, %p);\n", sess, |
| |
1923 msgclass, recipients_count, recipients, html_message); |
| 1835 |
1924 |
| 1836 return gg_send_message_common(sess, msgclass, recipients_count, recipients, NULL, NULL, 0, html_message); |
1925 return gg_send_message_common(sess, msgclass, recipients_count, recipients, NULL, NULL, 0, html_message); |
| 1837 } |
1926 } |
| 1838 |
1927 |
| 1839 /** |
1928 /** |
| 1851 * |
1940 * |
| 1852 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
1941 * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu. |
| 1853 * |
1942 * |
| 1854 * \ingroup messages |
1943 * \ingroup messages |
| 1855 */ |
1944 */ |
| 1856 int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len) |
1945 int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, |
| |
1946 const unsigned char *message, int message_len) |
| 1857 { |
1947 { |
| 1858 struct gg_send_msg s; |
1948 struct gg_send_msg s; |
| 1859 |
1949 |
| 1860 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient); |
1950 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, " |
| |
1951 "%d, %u, ...);\n", sess, msgclass, recipient); |
| 1861 |
1952 |
| 1862 if (!sess) { |
1953 if (!sess) { |
| 1863 errno = EFAULT; |
1954 errno = EFAULT; |
| 1864 return -1; |
1955 return -1; |
| 1865 } |
1956 } |
| 1898 struct gg_send_msg s; |
1989 struct gg_send_msg s; |
| 1899 struct gg_msg_image_request r; |
1990 struct gg_msg_image_request r; |
| 1900 char dummy = 0; |
1991 char dummy = 0; |
| 1901 int res; |
1992 int res; |
| 1902 |
1993 |
| 1903 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32); |
1994 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, " |
| |
1995 "%u, 0x%.4x);\n", sess, recipient, size, crc32); |
| 1904 |
1996 |
| 1905 if (!sess) { |
1997 if (!sess) { |
| 1906 errno = EFAULT; |
1998 errno = EFAULT; |
| 1907 return -1; |
1999 return -1; |
| 1908 } |
2000 } |
| 1930 if (!res) { |
2022 if (!res) { |
| 1931 struct gg_image_queue *q = malloc(sizeof(*q)); |
2023 struct gg_image_queue *q = malloc(sizeof(*q)); |
| 1932 char *buf; |
2024 char *buf; |
| 1933 |
2025 |
| 1934 if (!q) { |
2026 if (!q) { |
| 1935 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n"); |
2027 gg_debug_session(sess, GG_DEBUG_MISC, |
| |
2028 "// gg_image_request() not enough memory for " |
| |
2029 "image queue\n"); |
| 1936 return -1; |
2030 return -1; |
| 1937 } |
2031 } |
| 1938 |
2032 |
| 1939 buf = malloc(size); |
2033 buf = malloc(size); |
| 1940 if (size && !buf) |
2034 if (size && !buf) { |
| 1941 { |
|
| 1942 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n"); |
2035 gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n"); |
| 1943 free(q); |
2036 free(q); |
| 1944 return -1; |
2037 return -1; |
| 1945 } |
2038 } |
| 1946 |
2039 |
| 1985 struct gg_send_msg s; |
2077 struct gg_send_msg s; |
| 1986 const char *tmp; |
2078 const char *tmp; |
| 1987 char buf[1910]; |
2079 char buf[1910]; |
| 1988 int res = -1; |
2080 int res = -1; |
| 1989 |
2081 |
| 1990 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size); |
2082 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, " |
| |
2083 "\"%s\", %p, %d);\n", sess, recipient, filename, image, size); |
| 1991 |
2084 |
| 1992 if (!sess || !filename || !image) { |
2085 if (!sess || !filename || !image) { |
| 1993 errno = EFAULT; |
2086 errno = EFAULT; |
| 1994 return -1; |
2087 return -1; |
| 1995 } |
2088 } |
| 2068 size_t prev_size = gg_tvbuilder_get_size(tvb); |
2161 size_t prev_size = gg_tvbuilder_get_size(tvb); |
| 2069 gg_tvbuilder_write_uin(tvb, userlist[i]); |
2162 gg_tvbuilder_write_uin(tvb, userlist[i]); |
| 2070 gg_tvbuilder_write_uint8(tvb, |
2163 gg_tvbuilder_write_uint8(tvb, |
| 2071 (types == NULL) ? GG_USER_NORMAL : types[i]); |
2164 (types == NULL) ? GG_USER_NORMAL : types[i]); |
| 2072 |
2165 |
| 2073 /* Oryginalny klient wysyła maksymalnie 2048 bajtów |
2166 /* Oryginalny klient wysyła maksymalnie 2048 bajtów |
| 2074 * danych w każdym pakiecie tego typu. |
2167 * danych w każdym pakiecie tego typu. |
| 2075 */ |
2168 */ |
| 2076 if (gg_tvbuilder_get_size(tvb) > 2048) { |
2169 if (gg_tvbuilder_get_size(tvb) > 2048) { |
| 2077 gg_tvbuilder_strip(tvb, prev_size); |
2170 gg_tvbuilder_strip(tvb, prev_size); |
| 2078 break; |
2171 break; |
| 2079 } |
2172 } |
| 2080 i++; |
2173 i++; |
| 2081 } |
2174 } |
| 2082 |
2175 |
| 2083 if (!gg_tvbuilder_send(tvb, (i < count) ? |
2176 if (!gg_tvbuilder_send(tvb, (i < count) ? |
| 2084 GG_NOTIFY105_FIRST : GG_NOTIFY105_LAST)) { |
2177 GG_NOTIFY105_FIRST : GG_NOTIFY105_LAST)) |
| |
2178 { |
| 2085 return -1; |
2179 return -1; |
| 2086 } |
2180 } |
| 2087 } |
2181 } |
| 2088 |
2182 |
| 2089 return 0; |
2183 return 0; |
| 2110 * \ingroup contacts |
2204 * \ingroup contacts |
| 2111 */ |
2205 */ |
| 2112 int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count) |
2206 int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count) |
| 2113 { |
2207 { |
| 2114 struct gg_notify *n; |
2208 struct gg_notify *n; |
| 2115 uin_t *u; |
|
| 2116 char *t; |
|
| 2117 int i, res = 0; |
2209 int i, res = 0; |
| 2118 |
2210 |
| 2119 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count); |
2211 gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count); |
| 2120 |
2212 |
| 2121 if (!sess) { |
2213 if (!sess) { |
| 2146 } |
2238 } |
| 2147 |
2239 |
| 2148 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) |
2240 if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) |
| 2149 return -1; |
2241 return -1; |
| 2150 |
2242 |
| 2151 for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) { |
2243 for (i = 0; i < part_count; i++) { |
| 2152 n[i].uin = gg_fix32(*u); |
2244 n[i].uin = gg_fix32(userlist[i]); |
| 2153 if (types == NULL) |
2245 if (types == NULL) |
| 2154 n[i].dunno1 = GG_USER_NORMAL; |
2246 n[i].dunno1 = GG_USER_NORMAL; |
| 2155 else |
2247 else |
| 2156 n[i].dunno1 = *t; |
2248 n[i].dunno1 = types[i]; |
| 2157 } |
2249 } |
| 2158 |
2250 |
| 2159 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { |
2251 if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { |
| 2160 free(n); |
2252 free(n); |
| 2161 res = -1; |
2253 res = -1; |
| 2409 * |
2501 * |
| 2410 * \return 0 jeśli się powiodło, -1 w przypadku błędu |
2502 * \return 0 jeśli się powiodło, -1 w przypadku błędu |
| 2411 * |
2503 * |
| 2412 * \ingroup importexport |
2504 * \ingroup importexport |
| 2413 */ |
2505 */ |
| 2414 int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request) |
2506 int gg_userlist100_request(struct gg_session *sess, char type, |
| |
2507 unsigned int version, char format_type, const char *request) |
| 2415 { |
2508 { |
| 2416 struct gg_userlist100_request pkt; |
2509 struct gg_userlist100_request pkt; |
| 2417 unsigned char *zrequest; |
2510 unsigned char *zrequest; |
| 2418 size_t zrequest_len; |
2511 size_t zrequest_len; |
| 2419 int ret; |
2512 int ret; |
| 2565 seq = ++gs->seq; |
2658 seq = ++gs->seq; |
| 2566 pkt.id = gg_fix64(id); |
2659 pkt.id = gg_fix64(id); |
| 2567 pkt.seq = gg_fix32(seq); |
2660 pkt.seq = gg_fix32(seq); |
| 2568 pkt.participants_count = gg_fix32(participants_count); |
2661 pkt.participants_count = gg_fix32(participants_count); |
| 2569 |
2662 |
| 2570 for (i = 0; i < participants_count; i++) |
2663 for (i = 0; i < participants_count; i++) { |
| 2571 { |
|
| 2572 participants_list[i].uin = gg_fix32(participants[i]); |
2664 participants_list[i].uin = gg_fix32(participants[i]); |
| 2573 participants_list[i].dummy = gg_fix32(0x1e); |
2665 participants_list[i].dummy = gg_fix32(0x1e); |
| 2574 } |
2666 } |
| 2575 |
2667 |
| 2576 ret = gg_send_packet(gs, GG_CHAT_INVITE, |
2668 ret = gg_send_packet(gs, GG_CHAT_INVITE, |
| 2693 |
2785 |
| 2694 p->socket_is_external = 0; |
2786 p->socket_is_external = 0; |
| 2695 sess->fd = pipes[1]; |
2787 sess->fd = pipes[1]; |
| 2696 sess->check = GG_CHECK_READ; |
2788 sess->check = GG_CHECK_READ; |
| 2697 sess->state = GG_STATE_ERROR; |
2789 sess->state = GG_STATE_ERROR; |
| 2698 send(pipes[0], &dummy, sizeof(dummy), 0); |
2790 if (send(pipes[0], &dummy, sizeof(dummy), 0) != sizeof(dummy)) { |
| |
2791 gg_debug(GG_DEBUG_MISC, "// gg_socket_manager_error() unable to" |
| |
2792 " send via pipe (errno=%d, %s)\n", errno, |
| |
2793 strerror(errno)); |
| |
2794 return; |
| |
2795 } |
| 2699 close(pipes[0]); |
2796 close(pipes[0]); |
| 2700 } |
2797 } |
| 2701 |
2798 |
| 2702 int gg_compat_feature_is_enabled(struct gg_session *sess, gg_compat_feature_t feature) |
2799 int gg_compat_feature_is_enabled(struct gg_session *sess, gg_compat_feature_t feature) |
| 2703 { |
2800 { |