Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: include/libgadu.h.in
- ===================================================================
- --- include/libgadu.h.in (wersja 1314)
- +++ include/libgadu.h.in (kopia robocza)
- @@ -676,6 +676,9 @@
- int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length);
- uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len);
- +uin_t gg_str_to_uin(const char *str, int len);
- +int gg_packed_int_read(const char *data, uint16_t *dst);
- +int gg_packed_int_write(uint8_t dst[2], uint16_t val);
- int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type);
- gg_resolver_t gg_session_get_resolver(struct gg_session *gs);
- @@ -746,6 +749,9 @@
- GG_EVENT_USERLIST100_VERSION, /**< Otrzymano numer wersji listy kontaktów na serwerze (10.0) */
- GG_EVENT_USERLIST100_REPLY, /**< Wynik importu lub eksportu listy kontaktów (10.0) */
- +
- + GG_EVENT_IMTOKEN,
- + GG_EVENT_PONG110,
- };
- #define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY
- @@ -1071,6 +1077,14 @@
- char *reply; /**< Treść listy kontaktów w przesyłanej wersji i formacie */
- };
- +struct gg_event_imtoken {
- + char *imtoken;
- +};
- +
- +struct gg_event_pong110 {
- + time_t time;
- +};
- +
- /**
- * Unia wszystkich zdarzeń zwracanych przez funkcje \c gg_watch_fd(),
- * \c gg_dcc_watch_fd() i \c gg_dcc7_watch_fd().
- @@ -1107,6 +1121,8 @@
- struct gg_event_multilogon_info multilogon_info; /**< Informacja o innych sesjach multilogowania (\c GG_EVENT_MULTILOGON_INFO) */
- struct gg_event_userlist100_version userlist100_version; /**< Informacja o numerze wersji listy kontaktów na serwerze (\c GG_EVENT_USERLIST100_VERSION) */
- struct gg_event_userlist100_reply userlist100_reply; /**< Odpowiedź listy kontaktów (10.0) (\c GG_EVENT_USERLIST100_REPLY) */
- + struct gg_event_imtoken imtoken;
- + struct gg_event_pong110 pong110;
- };
- /**
- @@ -1573,8 +1589,8 @@
- #define GG_HTTPS_PORT 443
- #define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)"
- -#define GG_DEFAULT_CLIENT_VERSION "10.1.0.11070"
- -#define GG_DEFAULT_PROTOCOL_VERSION 0x2e
- +#define GG_DEFAULT_CLIENT_VERSION "11.0.0.8255"
- +#define GG_DEFAULT_PROTOCOL_VERSION 0x2f
- #define GG_DEFAULT_TIMEOUT 30
- #define GG_HAS_AUDIO_MASK 0x40000000
- #define GG_HAS_AUDIO7_MASK 0x20000000
- @@ -1944,6 +1960,8 @@
- #define GG_ADD_NOTIFY 0x000d
- #define GG_REMOVE_NOTIFY 0x000e
- +#define GG_ADD_NOTIFY105 0x007b
- +#define GG_REMOVE_NOTIFY105 0x007c
- struct gg_add_remove {
- uint32_t uin; /* numerek */
- @@ -2137,6 +2155,7 @@
- #define GG_USERLIST_REQUEST 0x0016
- #define GG_XML_EVENT 0x0027
- +#define GG_XML_EVENT110 0x0084
- #ifndef DOXYGEN
- @@ -2355,6 +2374,12 @@
- #define GG_DCC7_TIMEOUT_FILE_ACK 300 /* 5 minut */
- #define GG_DCC7_TIMEOUT_VOICE_ACK 300 /* 5 minut */
- +#define GG_IMTOKEN 0x008c
- +#define GG_NOTIFY105_FIRST 0x0077
- +#define GG_NOTIFY105_LAST 0x0078
- +#define GG_NOTIFY105_LIST_EMPTY 0x0079
- +#define GG_PONG110 0x00a1
- +
- #ifdef __cplusplus
- }
- #endif
- Index: include/protocol.h
- ===================================================================
- --- include/protocol.h (wersja 1314)
- +++ include/protocol.h (kopia robocza)
- @@ -32,6 +32,7 @@
- #define GG_LOGIN80BETA 0x0029
- #define GG_LOGIN80 0x0031
- +#define GG_LOGIN105 0x0083
- #undef GG_FEATURE_STATUS80BETA
- #undef GG_FEATURE_MSG80
- @@ -42,6 +43,8 @@
- #define GG8_LANG "pl"
- #define GG8_VERSION "Gadu-Gadu Client Build "
- +#define GG11_VERSION "GG "
- +#define GG11_TARGET " WINNT"
- struct gg_login80 {
- uint32_t uin; /* mój numerek */
- @@ -63,6 +66,8 @@
- #define GG_LOGIN80_OK 0x0035
- +#define GG_LOGIN110_OK 0x009d
- +
- /**
- * Logowanie powiodło się (pakiet \c GG_LOGIN80_OK)
- */
- @@ -92,6 +97,8 @@
- uint32_t description_size; /**< rozmiar opisu */
- } GG_PACKED;
- +#define GG_NEW_STATUS105 0x0063
- +
- #define GG_STATUS80BETA 0x002a
- #define GG_NOTIFY_REPLY80BETA 0x002b
- @@ -131,6 +138,8 @@
- uint32_t offset_attr;
- } GG_PACKED;
- +#define GG_SEND_MSG110 0x007d
- +
- #define GG_DISCONNECT_ACK 0x000d
- #define GG_RECV_MSG_ACK 0x0046
- @@ -319,6 +328,20 @@
- /* char reply[]; */
- } GG_PACKED;
- +struct gg_pong110 {
- + uint8_t dummy;
- + uint32_t time;
- +} GG_PACKED;
- +
- +#define GG_RECV_MSG110 0x007e
- +#define GG_RECV_CHAT110 0x0088
- +#define GG_RECV_OWN_MSG110 0x0082
- +#define GG_ACK110 0x0086
- +
- +#define GG_ACK110_MSG 0x01
- +#define GG_ACK110_CHAT 0x02
- +#define GG_ACK110_MPA 0x06
- +
- #ifdef _WIN32
- #pragma pack(pop)
- #endif
- Index: src/handlers.c
- ===================================================================
- --- src/handlers.c (wersja 1314)
- +++ src/handlers.c (kopia robocza)
- @@ -61,6 +61,247 @@
- int (*handler)(struct gg_session *, uint32_t, const char *, size_t, struct gg_event *);
- } gg_packet_handler_t;
- +static int gg_ack_gg11(struct gg_session *gs, uint8_t type, uint16_t seq, struct gg_event *ge)
- +{
- + uint8_t dunno1 = 0x08;
- + uint8_t dunno2 = 0x10;
- + uint8_t seq_b[2];
- + int seq_len;
- + uint8_t dunno3[2] = { 0x18, 0x01 };
- + int ret;
- +
- + seq_len = gg_packed_int_write(seq_b, seq);
- +
- + ret = gg_send_packet(gs,
- + GG_ACK110,
- + &dunno1, sizeof(dunno1),
- + &type, sizeof(type),
- + &dunno2, sizeof(dunno2),
- + seq_b, seq_len,
- + dunno3, sizeof(dunno3),
- + NULL);
- +
- + if (ret == -1) {
- + int errno_copy;
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending packet failed. (errno=%d, %s)\n", errno, strerror(errno));
- + errno_copy = errno;
- + close(gs->fd);
- + errno = errno_copy;
- + gs->fd = -1;
- + ge->type = GG_EVENT_CONN_FAILED;
- + ge->event.failure = GG_FAILURE_WRITING;
- + gs->state = GG_STATE_IDLE;
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static int gg_session_handle_welcome_gg11(struct gg_session *gs, uint32_t seed, struct gg_event *ge)
- +{
- + const uint8_t section_headers[6] = {0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a};
- + const uint8_t lang_length = 2;
- + const char *lang = GG8_LANG;
- + const uint8_t dunno1 = 0x12;
- + uint8_t uin_block_len;
- + const uint8_t dunno2 = 0x00; /* uin type? */
- + uint8_t uin_len;
- + char *uin;
- + uint8_t hash_len = 20;
- + uint8_t hash[64];
- + const uint8_t dunno3[9] = {0x20, 0x02, 0x2d, 0x77, 0xff, 0xae, 0x01, 0x35, 0x14};
- + uint8_t privacy;
- + const uint8_t dunno4[2] = {0x03, 0x00};
- + uint8_t client_len;
- + const char *client_name = GG11_VERSION;
- + const char *client_version = GG_DEFAULT_CLIENT_VERSION;
- + const char *client_target = GG11_TARGET;
- + const uint8_t dunno5 = 0x45;
- + uint32_t status;
- + uint8_t descr_len;
- + const char *descr;
- + const uint8_t dunno6[6] = {0x52, 0x04, 0x00, 0x00, 0x00, 0x00};
- + uint8_t userdata_len;
- + const char *userdata;
- + const uint8_t dunno7[15] = {0x60, 0xff, 0x01, 0x68, 0x64, 0x75, 0x7f,
- + 0x00, 0x00, 0x00, 0x78, 0x00, 0x88, 0x01, 0x00};
- +
- + uint8_t client_name_len;
- + uint8_t client_version_len;
- + uint8_t client_target_len;
- + int ret;
- +
- + if (gs->hash_type != GG_LOGIN_HASH_SHA1) {
- + gg_debug_session(gs, GG_DEBUG_MISC, "// Unsupported hash type for this protocol version\n");
- + return -1;
- + }
- +
- + if (gg_login_hash_sha1_2(gs->password, seed, hash) == -1) {
- + int errno_copy;
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() gg_login_hash_sha1_2() failed, probably out of memory\n");
- + errno_copy = errno;
- + close(gs->fd);
- + errno = errno_copy;
- + gs->fd = -1;
- + ge->type = GG_EVENT_CONN_FAILED;
- + ge->event.failure = GG_FAILURE_INTERNAL;
- + gs->state = GG_STATE_IDLE;
- + return -1;
- + }
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending GG_LOGIN105 packet\n");
- +
- + /*
- + zmienia format pakietu
- + dunno2[3] == 0x37 dla gg10.5
- + dunno2[3] == 0x77 dla gg11.0
- + */
- +
- + uin = gg_saprintf("%u", gs->uin);
- + uin_len = strlen(uin);
- + uin_block_len = uin_len + 2;
- +
- + privacy = 0x00; /* 0x06 - pokazuj kamerkę znajomym */
- +
- + /* flagi gg8 są różne od tych dla gg11 */
- + status = gg_fix32(gs->initial_status ? (gs->initial_status & 0xFF) : GG_STATUS_AVAIL);
- +
- + if (gs->client_version != NULL && !isdigit(gs->client_version[0])) {
- + client_name = "";
- + client_target = "";
- + }
- + if (gs->client_version != NULL)
- + client_version = gs->client_version;
- + client_name_len = strlen(client_name);
- + client_version_len = strlen(client_version);
- + client_target_len = strlen(client_target);
- + client_len = client_name_len + client_version_len + client_target_len;
- +
- + descr = (gs->initial_descr != NULL) ? gs->initial_descr : "";
- + descr_len = (gs->initial_descr != NULL) ? strlen(gs->initial_descr) : 0;
- +
- + userdata = "avatar,StatusComments,gg_account_sdp,edisc,bot,fanpage,"
- + "pubdir,botCaps";
- + userdata_len = strlen(userdata);
- +
- + ret = gg_send_packet(gs,
- + GG_LOGIN105,
- + §ion_headers[0], 1,
- + &lang_length, sizeof(lang_length),
- + lang, lang_length,
- + &dunno1, sizeof(dunno1),
- + &uin_block_len, sizeof(uin_block_len),
- + &dunno2, sizeof(dunno2),
- + &uin_len, sizeof(uin_len),
- + uin, uin_len,
- +
- + §ion_headers[1], 1,
- + &hash_len, sizeof(hash_len),
- + hash, hash_len,
- + dunno3, sizeof(dunno3),
- + &privacy, sizeof(privacy),
- + dunno4, sizeof(dunno4),
- +
- + §ion_headers[3], 1,
- + &client_len, sizeof(client_len),
- + client_name, client_name_len,
- + client_version, client_version_len,
- + client_target, client_target_len,
- + &dunno5, sizeof(dunno5),
- + &status, sizeof(status),
- +
- + §ion_headers[4], 1,
- + &descr_len, sizeof(descr_len),
- + descr, descr_len,
- + dunno6, sizeof(dunno6),
- +
- + §ion_headers[5], 1,
- + &userdata_len, sizeof(userdata_len),
- + userdata, userdata_len,
- +
- + dunno7, sizeof(dunno7),
- + NULL);
- + free(uin);
- +
- + if (ret == -1) {
- + int errno_copy;
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending packet failed. (errno=%d, %s)\n", errno, strerror(errno));
- + errno_copy = errno;
- + close(gs->fd);
- + errno = errno_copy;
- + gs->fd = -1;
- + ge->type = GG_EVENT_CONN_FAILED;
- + ge->event.failure = GG_FAILURE_WRITING;
- + gs->state = GG_STATE_IDLE;
- + return -1;
- + }
- +
- + gs->state = GG_STATE_READING_REPLY;
- + gs->check = GG_CHECK_READ;
- +
- + return 0;
- +}
- +
- +static int gg_session_handle_login110_ok(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- +{
- + uint8_t somehash_len;
- + char *somehash = NULL;
- + uint32_t server_time;
- + int offset = 0;
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() login succeded\n");
- + ge->type = GG_EVENT_CONN_SUCCESS;
- + gs->state = GG_STATE_CONNECTED;
- + gs->check = GG_CHECK_READ;
- + gs->timeout = -1;
- + gs->status = (gs->initial_status) ? gs->initial_status : GG_STATUS_AVAIL;
- +#if 0
- + free(gs->status_descr);
- + gs->status_descr = gs->initial_descr;
- +#else
- + free(gs->initial_descr);
- +#endif
- + gs->initial_descr = NULL;
- +
- + if (offset + 3 > len)
- + goto fail;
- + /* 0x08 01 12 */
- + offset += 3;
- +
- + if (offset + 1 > len)
- + goto fail;
- + somehash_len = ptr[offset];
- + offset++;
- + if (offset + somehash_len > len)
- + goto fail;
- + somehash = malloc(somehash_len + 1);
- + if (somehash == NULL)
- + goto fail;
- + memcpy(somehash, ptr + offset, somehash_len);
- + somehash[somehash_len] = '\0';
- + offset += somehash_len;
- +
- + if (offset + 6 > len)
- + goto fail;
- + /* 0x18 _f __ __ __ 25 */
- + offset += 6;
- +
- + if (offset + 4 > len)
- + goto fail;
- + server_time = gg_fix32(*((uint32_t*)(ptr + offset)));
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// login110_ok: some hash=%s, server time=%u\n", somehash, server_time);
- + free(somehash);
- +
- + return 0;
- +fail:
- + free(somehash);
- + return -1;
- +}
- +
- /**
- * \internal Obsługuje pakiet GG_WELCOME.
- *
- @@ -92,6 +333,9 @@
- w = (const struct gg_welcome*) ptr;
- seed = gg_fix32(w->key);
- + if (gs->protocol_version >= 0x2f)
- + return gg_session_handle_welcome_gg11(gs, seed, ge);
- +
- memset(hash_buf, 0, sizeof(hash_buf));
- switch (gs->hash_type) {
- @@ -347,6 +591,47 @@
- return 0;
- }
- +static int gg_session_handle_xml_event110(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- +{
- + int offset = 0;
- + uint16_t seq, data_len;
- + char *data;
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received GG11 XML event\n");
- +
- + if (offset + 3 > len)
- + goto fail;
- + /* 0x08 00 10 */
- + offset += 3;
- +
- + if (offset + 2 > len)
- + goto fail;
- + offset += gg_packed_int_read(ptr + offset, &seq);
- +
- + if (offset + 1 > len)
- + goto fail;
- + /* 0x1a */
- + offset++;
- +
- + if (offset + 2 > len)
- + goto fail;
- + offset += gg_packed_int_read(ptr + offset, &data_len);
- +
- + data = malloc(data_len + 1);
- + if (data == NULL)
- + goto fail;
- + memcpy(data, ptr + offset, data_len);
- + data[data_len] = '\0';
- +
- + ge->type = GG_EVENT_XML_EVENT;
- + ge->event.xml_event.data = data;
- +
- + return gg_ack_gg11(gs, GG_ACK110_MPA, seq, ge);
- +fail:
- + free(data);
- + return -1;
- +}
- +
- /**
- * \internal Obsługuje pakiet GG_PUBDIR50_REPLY.
- *
- @@ -990,6 +1275,156 @@
- return 0;
- }
- +static int gg_session_handle_recv_msg_110(struct gg_session *sess, uint32_t type, const char *packet, size_t length, struct gg_event *e)
- +{
- + int offset = 0;
- + uint8_t uin_len;
- + uint16_t seq = 0;
- + uint16_t msg_len;
- +
- + uint32_t dummy_time1, dummy_time2;
- +
- + gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_handle_recv_msg110(%p, %d, %p);\n", packet, length, e);
- +
- + if (offset + 3 > length)
- + goto fail;
- + /* 0x0a 0a 00 */
- + offset += 3;
- +
- + if (offset + 1 > length)
- + goto fail;
- + uin_len = packet[offset++];
- + if (offset + uin_len > length)
- + goto fail;
- + e->event.msg.sender = gg_str_to_uin(packet + offset, uin_len);
- + offset += uin_len;
- + if (e->event.msg.sender == 0)
- + goto fail;
- +
- + if (offset + 3 > length)
- + goto fail;
- + /* 0x10 08 18 -> ustawiany przez nadawcę? */
- + /* 0x10 09 18 -> archiwalna wiadomość? */
- + offset += 3;
- +
- + if (offset + 2 > length)
- + goto fail;
- + offset += gg_packed_int_read(packet + offset, &seq);
- + e->event.msg.seq = seq;
- +
- + if (offset + 1 > length)
- + goto fail;
- + /* 0x25 */
- + offset++;
- +
- + if (offset + 4 > length)
- + goto fail;
- + e->event.msg.time = gg_fix32(*((uint32_t*)(packet + offset)));
- + offset += 4;
- +
- + if (offset + 1 > length)
- + goto fail;
- + /* 0x2a */
- + offset++;
- +
- + if (offset + 2 > length)
- + goto fail;
- + offset += gg_packed_int_read(packet + offset, &msg_len);
- + if (offset + msg_len > length)
- + goto fail;
- + e->event.msg.message = malloc(msg_len + 1);
- + if (e->event.msg.message == NULL)
- + goto fail;
- + /* TODO: kodowanie */
- + memcpy(e->event.msg.message, packet + offset, msg_len);
- + e->event.msg.message[msg_len] = '\0';
- + offset += msg_len;
- +
- + if (offset + 1 > length)
- + goto fail;
- + /* 0x32 */
- + offset++;
- +
- + if (offset + 2 > length)
- + goto fail;
- + offset += gg_packed_int_read(packet + offset, &msg_len);
- + if (offset + msg_len > length)
- + goto fail;
- + e->event.msg.xhtml_message = malloc(msg_len + 1);
- + if (e->event.msg.xhtml_message == NULL)
- + goto fail;
- + /* TODO: kodowanie */
- + memcpy(e->event.msg.xhtml_message, packet + offset, msg_len);
- + e->event.msg.xhtml_message[msg_len] = '\0';
- + offset += msg_len;
- +
- + if (offset + 1 > length)
- + goto fail;
- + /* otrzymywane tylko od gg <= 10.5 */
- + if (packet[offset] == 0x3a)
- + {
- + uint8_t formats_length;
- +
- + offset++;
- + if (offset + 1 > length)
- + goto fail;
- + formats_length = packet[offset++];
- + if (offset + formats_length > length)
- + goto fail;
- + e->event.msg.formats_length = formats_length;
- +
- + e->event.msg.formats = malloc(formats_length);
- + if (e->event.msg.formats == NULL)
- + goto fail;
- + memcpy(e->event.msg.formats, packet + offset, formats_length);
- + offset += formats_length;
- + }
- +
- + if (type == GG_RECV_CHAT110) {
- + /* 49 02 10 __ 00 __ 8_ 3a 50 51 8c 31 01 01 */
- + if (offset + 14 > length)
- + goto fail;
- + offset += 14;
- + } else {
- + /* 49 __ 02 __ 00 */
- + if (offset + 5 > length)
- + goto fail;
- + offset += 5;
- + }
- +
- + if (offset + 4 > length)
- + goto fail;
- + /* taki sam czas jak czas wiadomości lub o jeden mniej */
- + dummy_time1 = gg_fix32(*((uint32_t*)(packet + offset)));
- + offset += 4;
- +
- + if (offset + 5 > length)
- + goto fail;
- + /* id rozmówcy? konwersacji? */
- + /* 0x59 __ __ 0_ 00 */
- + offset += 5;
- +
- + if (offset + 4 > length)
- + goto fail;
- + /* czas początku konwersacji? */
- + dummy_time2 = gg_fix32(*((uint32_t*)(packet + offset)));
- +
- + e->type = (type != GG_RECV_OWN_MSG110) ? GG_EVENT_MSG : GG_EVENT_MULTILOGON_MSG;
- + e->event.msg.msgclass = GG_CLASS_CHAT;
- + e->event.msg.seq = seq;
- +
- + return gg_ack_gg11(sess, (type != GG_RECV_CHAT110) ? GG_ACK110_MSG : GG_ACK110_CHAT, seq, e);
- +
- +fail:
- + free(e->event.msg.message);
- + free(e->event.msg.xhtml_message);
- + free(e->event.msg.recipients);
- + free(e->event.msg.formats);
- + if (seq)
- + gg_ack_gg11(sess, (type != GG_RECV_CHAT110) ? GG_ACK110_MSG : GG_ACK110_CHAT, seq, e);
- + return -1;
- +}
- +
- /**
- * \internal Obsługuje pakiet GG_STATUS.
- *
- @@ -1764,6 +2199,54 @@
- return 0;
- }
- +static int gg_session_handle_imtoken(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- +{
- + uint8_t imtoken_len;
- + char *imtoken = NULL;
- + int offset = 0;
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received imtoken\n");
- +
- + if (offset + 1 > len)
- + goto fail;
- + /* 0x0a */
- + offset++;
- +
- + if (offset + 1 > len)
- + goto fail;
- + imtoken_len = ptr[offset];
- + offset++;
- + if (offset + imtoken_len > len)
- + goto fail;
- + if (imtoken_len > 0) {
- + imtoken = malloc(imtoken_len + 1);
- + if (imtoken == NULL)
- + goto fail;
- + memcpy(imtoken, ptr + offset, imtoken_len);
- + imtoken[imtoken_len] = '\0';
- + }
- +
- + ge->type = GG_EVENT_IMTOKEN;
- + ge->event.imtoken.imtoken = imtoken;
- +
- + return 0;
- +fail:
- + free(imtoken);
- + return -1;
- +}
- +
- +static int gg_session_handle_pong110(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
- +{
- + const struct gg_pong110 *pong = (const struct gg_pong110*)ptr;
- +
- + gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received pong110\n");
- +
- + ge->type = GG_EVENT_PONG110;
- + ge->event.pong110.time = gg_fix32(pong->time);
- +
- + return 0;
- +}
- +
- /**
- * \internal Tablica obsługiwanych pakietów
- */
- @@ -1772,6 +2255,7 @@
- { GG_WELCOME, GG_STATE_READING_KEY, 0, gg_session_handle_welcome },
- { GG_LOGIN_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
- { GG_LOGIN80_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
- + { GG_LOGIN110_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login110_ok },
- { GG_NEED_EMAIL, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
- { GG_LOGIN_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
- { GG_LOGIN80_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
- @@ -1780,6 +2264,7 @@
- { GG_DISCONNECTING, GG_STATE_CONNECTED, 0, gg_session_handle_disconnecting },
- { GG_DISCONNECT_ACK, GG_STATE_DISCONNECTING, 0, gg_session_handle_disconnect_ack },
- { GG_XML_EVENT, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
- + { GG_XML_EVENT110, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event110 },
- { GG_PUBDIR50_REPLY, GG_STATE_CONNECTED, 0, gg_session_handle_pubdir50_reply },
- { GG_USERLIST_REPLY, GG_STATE_CONNECTED, 0, gg_session_handle_userlist_reply },
- { GG_DCC7_ID_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_id_reply), gg_session_handle_dcc7_id_reply },
- @@ -1789,6 +2274,9 @@
- { GG_DCC7_INFO, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_info), gg_session_handle_dcc7_info },
- { GG_RECV_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg), gg_session_handle_recv_msg },
- { GG_RECV_MSG80, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
- + { GG_RECV_MSG110, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
- + { GG_RECV_CHAT110, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
- + { GG_RECV_OWN_MSG110, GG_STATE_CONNECTED, 0, gg_session_handle_recv_msg_110 },
- { GG_STATUS, GG_STATE_CONNECTED, sizeof(struct gg_status), gg_session_handle_status },
- { GG_STATUS60, GG_STATE_CONNECTED, sizeof(struct gg_status60), gg_session_handle_status_60_77_80beta },
- { GG_STATUS77, GG_STATE_CONNECTED, sizeof(struct gg_status77), gg_session_handle_status_60_77_80beta },
- @@ -1806,6 +2294,8 @@
- { GG_RECV_OWN_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
- { GG_USERLIST100_VERSION, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_version), gg_session_handle_userlist_100_version },
- { GG_USERLIST100_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_reply), gg_session_handle_userlist_100_reply },
- + { GG_IMTOKEN, GG_STATE_CONNECTED, 0, gg_session_handle_imtoken },
- + { GG_PONG110, GG_STATE_CONNECTED, sizeof(struct gg_pong110), gg_session_handle_pong110 },
- };
- /**
- Index: src/events.c
- ===================================================================
- --- src/events.c (wersja 1314)
- +++ src/events.c (kopia robocza)
- @@ -166,6 +166,10 @@
- case GG_EVENT_USERLIST100_REPLY:
- free(e->event.userlist100_reply.reply);
- break;
- +
- + case GG_EVENT_IMTOKEN:
- + free(e->event.imtoken.imtoken);
- + break;
- }
- free(e);
- Index: src/libgadu.c
- ===================================================================
- --- src/libgadu.c (wersja 1314)
- +++ src/libgadu.c (kopia robocza)
- @@ -1074,10 +1074,28 @@
- p.status = gg_fix32(status);
- p.flags = gg_fix32(sess->status_flags);
- p.description_size = gg_fix32(descr_len);
- - res = gg_send_packet(sess, GG_NEW_STATUS80,
- - &p, sizeof(p),
- - (new_descr) ? new_descr : descr, descr_len,
- +
- + if (sess->protocol_version >= 0x2f) {
- + uint8_t dummy1[4] = { 0x00, 0x00, 0x00, 0x00 };
- + const char *set_descr = "";
- +
- + if (new_descr)
- + set_descr = new_descr;
- + else if (descr)
- + set_descr = descr;
- +
- + p.flags = gg_fix32(0x00000014);
- + res = gg_send_packet(sess, GG_NEW_STATUS105,
- + &p, sizeof(p),
- + set_descr, descr_len,
- + dummy1, sizeof(dummy1),
- NULL);
- + } else {
- + res = gg_send_packet(sess, GG_NEW_STATUS80,
- + &p, sizeof(p),
- + new_descr ? new_descr : descr, descr_len,
- + NULL);
- + }
- free(new_descr);
- @@ -1137,6 +1155,54 @@
- #ifndef DOXYGEN
- +static int gg_send_message_gg11(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const char *message, const char *html_message)
- +{
- + uint8_t dummy1[3] = { 0x0a, 0x0a, 0x00 };
- + uint8_t uin_len;
- + char uin_s[15];
- + uint8_t dummy2[3] = { 0x10, 0x08, 0x18 };
- + uint8_t seq_b[2];
- + int seq_len;
- + uint8_t dummy3 = 0x2a;
- + uint8_t message_len_b[2];
- + int message_len_len;
- + uint8_t dummy4 = 0x32;
- + uint8_t html_message_len_b[2];
- + int html_message_len_len;
- +
- + int message_len, html_message_len;
- + int seq = ++sess->seq;
- +
- + sprintf(uin_s, "%u", recipients[0]);
- + uin_len = strlen(uin_s);
- +
- + message_len = strlen(message);
- + html_message_len = strlen(html_message);
- + seq_len = gg_packed_int_write(seq_b, seq);
- + message_len_len = gg_packed_int_write(message_len_b, message_len);
- + html_message_len_len = gg_packed_int_write(html_message_len_b, html_message_len);
- +
- + if (gg_send_packet(sess,
- + GG_SEND_MSG110,
- + dummy1, sizeof(dummy1),
- + &uin_len, sizeof(uin_len),
- + uin_s, uin_len,
- + dummy2, sizeof(dummy2),
- + seq_b, seq_len,
- + &dummy3, sizeof(dummy3),
- + message_len_b, message_len_len,
- + message, message_len,
- + &dummy4, sizeof(dummy4),
- + html_message_len_b, html_message_len_len,
- + html_message, html_message_len,
- + NULL) == -1)
- + {
- + return -1;
- + }
- +
- + return seq;
- +}
- +
- /**
- * \internal Wysyła wiadomość.
- *
- @@ -1235,6 +1301,7 @@
- }
- }
- + //TODO: dla gg11, domyślne formatowanie to <span></span>
- if (html_message == NULL) {
- size_t len;
- char *tmp;
- @@ -1277,6 +1344,12 @@
- }
- }
- + if (sess->protocol_version >= 0x2f)
- + {
- + seq_no = gg_send_message_gg11(sess, msgclass, recipients_count, recipients, recoded_msg, recoded_html_msg);
- + goto cleanup;
- + }
- +
- /* Drobne odchylenie od protokołu. Jeśli wysyłamy kilka
- * wiadomości w ciągu jednej sekundy, zwiększamy poprzednią
- * wartość, żeby każda wiadomość miała unikalny numer.
- @@ -1697,6 +1770,46 @@
- return res;
- }
- +static int gg_notify105_ex(struct gg_session *sess, uin_t *userlist, char *types, int count)
- +{
- + int res = 0;
- +
- + if (!userlist || !count)
- + return gg_send_packet(sess, GG_NOTIFY105_LIST_EMPTY, NULL);
- +
- + while (count > 0) {
- + uint8_t buff[2048];
- + int offset = 0;
- + char uin_s[15];
- + uint8_t uin_len;
- + int packet_type;
- +
- + while (count > 0) {
- + sprintf(uin_s, "%u", *userlist);
- + uin_len = strlen(uin_s);
- + if (offset + uin_len + 3 >= 2048)
- + break;
- + buff[offset++] = 0x00;
- + buff[offset++] = uin_len;
- + memcpy(buff + offset, uin_s, uin_len);
- + offset += uin_len;
- + buff[offset++] = *types;
- +
- + userlist++;
- + types++;
- + count--;
- + }
- +
- + packet_type = (count > 0) ? GG_NOTIFY105_FIRST : GG_NOTIFY105_LAST;
- + if (gg_send_packet(sess, packet_type, buff, offset, NULL) == -1) {
- + res = -1;
- + break;
- + }
- + }
- +
- + return res;
- +}
- +
- /**
- * Wysyła do serwera listę kontaktów.
- *
- @@ -1736,6 +1849,9 @@
- return -1;
- }
- + if (sess->protocol_version >= 0x2f)
- + return gg_notify105_ex(sess, userlist, types, count);
- +
- if (!userlist || !count)
- return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
- @@ -1790,57 +1906,19 @@
- */
- int gg_notify(struct gg_session *sess, uin_t *userlist, int count)
- {
- - struct gg_notify *n;
- - uin_t *u;
- - int i, res = 0;
- + char *types;
- + int ret;
- - gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count);
- -
- - if (!sess) {
- - errno = EFAULT;
- + types = malloc(count);
- + memset(types, GG_USER_NORMAL, count);
- + if (sess->recv_buf == NULL)
- return -1;
- - }
- - if (sess->state != GG_STATE_CONNECTED) {
- - errno = ENOTCONN;
- - return -1;
- - }
- + ret = gg_notify_ex(sess, userlist, types, count);
- - if (!userlist || !count)
- - return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
- + free(types);
- - while (count > 0) {
- - int part_count, packet_type;
- -
- - if (count > 400) {
- - part_count = 400;
- - packet_type = GG_NOTIFY_FIRST;
- - } else {
- - part_count = count;
- - packet_type = GG_NOTIFY_LAST;
- - }
- -
- - if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
- - return -1;
- -
- - for (u = userlist, i = 0; i < part_count; u++, i++) {
- - n[i].uin = gg_fix32(*u);
- - n[i].dunno1 = GG_USER_NORMAL;
- - }
- -
- - if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
- - res = -1;
- - free(n);
- - break;
- - }
- -
- - free(n);
- -
- - userlist += part_count;
- - count -= part_count;
- - }
- -
- - return res;
- + return ret;
- }
- /**
- @@ -1860,8 +1938,6 @@
- */
- int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type)
- {
- - struct gg_add_remove a;
- -
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type);
- if (!sess) {
- @@ -1874,10 +1950,28 @@
- return -1;
- }
- - a.uin = gg_fix32(uin);
- - a.dunno1 = type;
- + if (sess->protocol_version >= 0x2f) {
- + uint8_t dunno1 = 0x00;
- + uint8_t uin_len;
- + char uin_s[15];
- - return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL);
- + sprintf(uin_s, "%u", uin);
- + uin_len = strlen(uin_s);
- +
- + return gg_send_packet(sess, GG_ADD_NOTIFY105,
- + &dunno1, sizeof(dunno1),
- + &uin_len, sizeof(uin_len),
- + uin_s, uin_len,
- + &type, sizeof(type),
- + NULL);
- + } else {
- + struct gg_add_remove a;
- +
- + a.uin = gg_fix32(uin);
- + a.dunno1 = type;
- +
- + return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL);
- + }
- }
- /**
- @@ -1913,8 +2007,6 @@
- */
- int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type)
- {
- - struct gg_add_remove a;
- -
- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type);
- if (!sess) {
- @@ -1927,10 +2019,28 @@
- return -1;
- }
- - a.uin = gg_fix32(uin);
- - a.dunno1 = type;
- + if (sess->protocol_version >= 0x2f) {
- + uint8_t dunno1 = 0x00;
- + uint8_t uin_len;
- + char uin_s[15];
- - return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL);
- + sprintf(uin_s, "%u", uin);
- + uin_len = strlen(uin_s);
- +
- + return gg_send_packet(sess, GG_ADD_NOTIFY105,
- + &dunno1, sizeof(dunno1),
- + &uin_len, sizeof(uin_len),
- + uin_s, uin_len,
- + &type, sizeof(type),
- + NULL);
- + } else {
- + struct gg_add_remove a;
- +
- + a.uin = gg_fix32(uin);
- + a.dunno1 = type;
- +
- + return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL);
- + }
- }
- /**
- Index: src/debug.c
- ===================================================================
- --- src/debug.c (wersja 1314)
- +++ src/debug.c (kopia robocza)
- @@ -356,6 +356,8 @@
- GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_INFO)
- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_VERSION)
- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_REPLY)
- + GG_DEBUG_EVENT(GG_EVENT_IMTOKEN)
- + GG_DEBUG_EVENT(GG_EVENT_PONG110)
- #undef GG_DEBUG_EVENT
- /* Celowo nie ma default, żeby kompilator wyłapał brakujące zdarzenia */
- Index: src/common.c
- ===================================================================
- --- src/common.c (wersja 1314)
- +++ src/common.c (kopia robocza)
- @@ -679,6 +679,60 @@
- return crc ^ 0xffffffffL;
- }
- +uin_t gg_str_to_uin(const char *str, int len)
- +{
- + char buff[11];
- + char *endptr;
- + uin_t uin;
- +
- + if (len < 0)
- + len = strlen(str);
- + if (len > 10)
- + return 0;
- + memcpy(buff, str, len);
- + buff[len] = '\0';
- +
- + errno = 0;
- + uin = strtoul(buff, &endptr, 10);
- + if (errno == ERANGE || endptr[0] != '\0')
- + return 0;
- +
- + return uin;
- +}
- +
- +int gg_packed_int_read(const char *data, uint16_t *dst)
- +{
- + uint16_t val;
- + uint8_t raw;
- +
- + raw = *data;
- + data++;
- + if (!(raw & 0x80))
- + {
- + *dst = raw;
- + return 1;
- + }
- +
- + val = raw & ~0x80;
- + raw = *data;
- + val |= (uint16_t)raw << 7;
- + *dst = val;
- + return 2;
- +}
- +
- +int gg_packed_int_write(uint8_t dst[2], uint16_t val)
- +{
- + if (val < 0x80)
- + {
- + dst[0] = val;
- + return 1;
- + }
- +
- + dst[0] = (val & 0x7F) | 0x80;
- + dst[1] = (val >> 7);
- + return 2;
- +}
- +
- /*
- * Local variables:
- * c-indentation-style: k&r
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement