--- a/configure.ac Thu May 22 18:35:00 2014 -0500
+++ b/configure.ac Mon Jun 16 23:01:47 2014 +0200
@@ -1035,7 +1035,7 @@
if test "x$gadu_manual_check" = "xno"; then
- PKG_CHECK_MODULES(GADU, [libgadu >= 1.11.0], [
+ PKG_CHECK_MODULES(GADU, [libgadu >= 1.12.0], [ @@ -1069,7 +1069,7 @@
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libgadu.h>]], [[
#if GG_DEFAULT_PROTOCOL_VERSION < 0x2e
-#error "Your libgadu version is too old. libpurple requires 1.11.0 or higher."
+#error "Your libgadu version is too old. libpurple requires 1.12.0 or higher." @@ -1080,7 +1080,7 @@
echo "Your supplied copy of libgadu is too old."
- echo "Install version 1.11.0 or newer."
+ echo "Install version 1.12.0 or newer." echo "Then rerun this ./configure"
echo "Falling back to using our own copy of libgadu"
--- a/libpurple/protocols/gg/lib/config.h Thu May 22 18:35:00 2014 -0500
+++ b/libpurple/protocols/gg/lib/config.h Mon Jun 16 23:01:47 2014 +0200
@@ -5,7 +5,7 @@
-#define GG_LIBGADU_VERSION "1.12.0-rc2"
+#define GG_LIBGADU_VERSION "1.12.0" /* Defined if libgadu was compiled for bigendian machine. */
#undef GG_CONFIG_BIGENDIAN
@@ -87,3 +87,7 @@
/* Defined if libgadu uses system defalt trusted CAs. */
#define GG_CONFIG_SSL_SYSTEM_TRUST
+/* Defined if libgadu is GPL compliant (was not linked with OpenSSL or any + other non-GPL compliant library support). */ +#define GG_CONFIG_IS_GPL_COMPLIANT --- a/libpurple/protocols/gg/lib/dcc7.c Thu May 22 18:35:00 2014 -0500
+++ b/libpurple/protocols/gg/lib/dcc7.c Mon Jun 16 23:01:47 2014 +0200
@@ -1540,7 +1540,7 @@
if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY ||
gg_fix32(pkt->rcount) < 1 ||
- gg_fix32(pkt->rcount > 256) ||
+ gg_fix32(pkt->rcount) > 256 || gg_fix32(pkt->len) < sizeof(*pkt) +
gg_fix32(pkt->rcount) * sizeof(srv))
--- a/libpurple/protocols/gg/lib/handlers.c Thu May 22 18:35:00 2014 -0500
+++ b/libpurple/protocols/gg/lib/handlers.c Mon Jun 16 23:01:47 2014 +0200
@@ -405,6 +405,7 @@
static int gg_session_handle_send_msg_ack(struct gg_session *gs, uint32_t type,
const char *ptr, size_t len, struct gg_event *ge)
+ struct gg_session_private *p = gs->private_data; const struct gg_send_msg_ack *s = (const struct gg_send_msg_ack*) ptr;
gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a message ack\n");
@@ -414,6 +415,10 @@
ge->event.ack.recipient = gg_fix32(s->recipient);
ge->event.ack.seq = gg_fix32(s->seq);
+ if (ge->event.ack.seq == 0 && p->imgout_waiting_ack > 0) + p->imgout_waiting_ack--; @@ -423,6 +428,7 @@
static int gg_session_handle_send_msg_ack_110(struct gg_session *gs,
uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+ struct gg_session_private *p = gs->private_data; GG110MessageAck *msg = gg110_message_ack__unpack(NULL, len, (uint8_t*)ptr);
@@ -435,11 +441,11 @@
gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_WARNING,
"// gg_session_handle_send_msg_ack_110() magic dummy1 "
} else if (msg->dummy1 != 0) {
gg_debug_session(gs, GG_DEBUG_MISC | GG_DEBUG_WARNING,
"// gg_session_handle_send_msg_ack_110() unknown dummy1 "
- "value: %x", msg->dummy1);
+ "value: %x\n", msg->dummy1); gg_debug_session(gs, GG_DEBUG_VERBOSE,
@@ -466,6 +472,10 @@
gg110_message_ack__free_unpacked(msg, NULL);
+ if (msg->seq == 0 && p->imgout_waiting_ack > 0) + p->imgout_waiting_ack--; @@ -1388,13 +1398,13 @@
if (msg->data.len < sizeof(struct gg_msg_image_reply)) {
gg_debug_session(gs, GG_DEBUG_ERROR,
"// gg_session_handle_recv_msg_110() "
+ "packet too small (%" GG_SIZE_FMT " < %" + GG_SIZE_FMT ")\n", msg->data.len, + sizeof(struct gg_msg_image_reply)); + gg_image_queue_parse(ge, (char *)msg->data.data, + msg->data.len, gs, sender, type);
- gg_image_queue_parse(ge, (char *)msg->data.data, msg->data.len,
gg110_recv_message__free_unpacked(msg, NULL);
return gg_ack_110(gs, GG110_ACK__TYPE__MSG, seq, ge);
--- a/libpurple/protocols/gg/lib/internal.h Thu May 22 18:35:00 2014 -0500
+++ b/libpurple/protocols/gg/lib/internal.h Mon Jun 16 23:01:47 2014 +0200
@@ -27,8 +27,16 @@
#define GG_DEFAULT_CLIENT_VERSION_110 "11.3.45.10771"
-# define GG_SIZE_FMT "Iu"
-# define _GG_INT64_MODIFIER "I64"
+# define GG_SIZE_FMT "lu" +# define _GG_INT64_MODIFIER "ll" +# define GG_SIZE_FMT "Iu" +# define _GG_INT64_MODIFIER "I64" # define GG_SIZE_FMT "zu"
# define _GG_INT64_MODIFIER "l"
@@ -66,6 +74,8 @@
[(condition) ? 1 : -1]; static_assertion_failed_ ## message dummy; \
+#define GG_IMGOUT_WAITING_MAX 4 @@ -98,6 +108,15 @@
+typedef struct _gg_imgout_queue_t gg_imgout_queue_t; +struct _gg_imgout_queue_t { + struct gg_send_msg msg_hdr; + gg_imgout_queue_t *next; struct gg_session_private {
gg_compat_t compatibility;
@@ -108,6 +127,9 @@
+ gg_imgout_queue_t *imgout_queue; + int imgout_waiting_ack; gg_socket_manager_type_t socket_manager_type;
gg_socket_manager_t socket_manager;
@@ -164,6 +186,8 @@
void gg_compat_message_ack(struct gg_session *sess, int seq);
+void gg_image_sendout(struct gg_session *sess); void gg_strarr_free(char **strarr);
char ** gg_strarr_dup(char **strarr);
--- a/libpurple/protocols/gg/lib/libgadu.c Thu May 22 18:35:00 2014 -0500
+++ b/libpurple/protocols/gg/lib/libgadu.c Mon Jun 16 23:01:47 2014 +0200
@@ -530,6 +530,12 @@
+ while (p->imgout_queue) { + gg_imgout_queue_t *next = p->imgout_queue->next; + p->imgout_queue = next; if (p->dummyfds_created) {
@@ -985,7 +991,8 @@
sess->protocol_version = p->protocol_version;
- sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL;
+ if (p->client_version && strcmp(p->client_version, "-") != 0) + sess->client_version = strdup(p->client_version); sess->last_sysmsg = p->last_sysmsg;
sess->image_size = p->image_size;
@@ -1510,6 +1517,32 @@
+gg_message_legacy_text_to_html(const char *src, gg_encoding_t encoding, + const unsigned char *format, size_t format_len) + if (format == NULL || format_len <= 3) { + len = gg_message_text_to_html(NULL, src, encoding, format, format_len); + gg_message_text_to_html(dst, src, encoding, format, format_len); * \internal Wysyła wiadomość.
@@ -1567,6 +1600,21 @@
int is_html = (html_message != NULL);
+ char *formatted_msg = NULL; + if (formatlen > 3 && !is_html) { + gg_debug_session(sess, GG_DEBUG_MISC | GG_DEBUG_WARNING, + "// gg_send_message_common() using legacy " + "formatting with new protocol\n"); + formatted_msg = gg_message_legacy_text_to_html( + (const char *)message, sess->encoding, + if (formatted_msg == NULL) + html_message = (unsigned char*)formatted_msg; seq_no = gg_send_message_110(sess, recipients[0], 0,
(const char*)(is_html ? html_message : message),
@@ -1617,7 +1665,7 @@
- if (sess->encoding == GG_ENCODING_UTF8) {
+ if (sess->encoding != GG_ENCODING_CP1250) { cp_msg = recoded_msg = gg_encoding_convert(tmp_msg, sess->encoding, GG_ENCODING_CP1250, -1, -1);
@@ -1627,7 +1675,7 @@
cp_msg = recoded_msg = tmp_msg;
- if (sess->encoding == GG_ENCODING_UTF8) {
+ if (sess->encoding != GG_ENCODING_CP1250) { cp_msg = recoded_msg = gg_encoding_convert(
(const char*)message, sess->encoding,
GG_ENCODING_CP1250, -1, -1);
@@ -1640,38 +1688,24 @@
if (html_message == NULL) {
- const unsigned char *format_ = NULL;
+ formatted_msg = gg_message_legacy_text_to_html( + (const char*)message, sess->encoding, format, formatlen); + if (formatted_msg == NULL) if (sess->encoding == GG_ENCODING_UTF8) {
- utf_msg = (const char*) message;
+ utf_html_msg = recoded_html_msg = formatted_msg; - utf_msg = recoded_msg = gg_encoding_convert(
- (const char*)message, sess->encoding,
+ utf_html_msg = recoded_html_msg = gg_encoding_convert( + formatted_msg, sess->encoding, GG_ENCODING_UTF8, -1, -1);
+ if (utf_html_msg == NULL)
- if (format != NULL && formatlen >= 3) {
- formatlen_ = formatlen - 3;
- len = gg_message_text_to_html(NULL, utf_msg, GG_ENCODING_UTF8, format_, formatlen_);
- gg_message_text_to_html(tmp, utf_msg, GG_ENCODING_UTF8, format_, formatlen_);
- utf_html_msg = recoded_html_msg = tmp;
if (sess->encoding == GG_ENCODING_UTF8) {
utf_html_msg = (const char*) html_message;
@@ -1783,6 +1817,17 @@
gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, "
"%u, %p)\n", sess, msgclass, recipient, message);
+ if (sess->protocol_version >= GG_PROTOCOL_VERSION_110) { + seq_no = gg_send_message_110(sess, recipient, 0, (const char*)message, 0); + gg_compat_message_sent(sess, seq_no, 1, &recipient); return gg_send_message_common(sess, msgclass, 1, &recipient, message,
(const unsigned char*)"\x02\x06\x00\x00\x00\x08\x00\x00\x00",
@@ -2073,11 +2118,13 @@
int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size)
+ struct gg_session_private *p; struct gg_msg_image_reply *r;
+ gg_imgout_queue_t *queue = NULL, *queue_end = NULL; gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, "
"\"%s\", %p, %d);\n", sess, recipient, filename, image, size);
@@ -2087,6 +2134,8 @@
+ p = sess->private_data; if (sess->state != GG_STATE_CONNECTED) {
@@ -2118,6 +2167,7 @@
r->crc32 = gg_fix32(gg_crc32(0, (const unsigned char*) image, size));
/* \0 + struct gg_msg_image_reply */
@@ -2135,15 +2185,57 @@
- res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL);
+ it = gg_new0(sizeof(gg_imgout_queue_t)); + queue = queue_end = it; + memcpy(&it->msg_hdr, &s, sizeof(s)); + memcpy(it->buf, buf, buflen + chunklen); + it->buf_len = buflen + chunklen; + r->flag = GG_MSG_OPTION_IMAGE_REPLY_MORE; + queue_end = p->imgout_queue; + while (queue_end->next) + queue_end = queue_end->next; + queue_end->next = queue; + p->imgout_queue = queue; + gg_image_sendout(sess); +void gg_image_sendout(struct gg_session *sess) + struct gg_session_private *p = sess->private_data; + while (p->imgout_waiting_ack < GG_IMGOUT_WAITING_MAX && p->imgout_queue) { + gg_imgout_queue_t *it = p->imgout_queue; + p->imgout_queue = p->imgout_queue->next; + p->imgout_waiting_ack++; + res = gg_send_packet(sess, GG_SEND_MSG, + &it->msg_hdr, sizeof(it->msg_hdr),
- r->flag = GG_MSG_OPTION_IMAGE_REPLY_MORE;
static int gg_notify105_ex(struct gg_session *sess, uin_t *userlist, char *types, int count)
--- a/libpurple/protocols/gg/lib/resolver.h Thu May 22 18:35:00 2014 -0500
+++ b/libpurple/protocols/gg/lib/resolver.h Mon Jun 16 23:01:47 2014 +0200
@@ -23,5 +23,6 @@
int gg_gethostbyname_real(const char *hostname, struct in_addr **result, unsigned int *count, int pthread);
int gg_resolver_recv(int fd, void *buf, size_t len);
+void gg_resolver_cleaner(void *data); #endif /* LIBGADU_RESOLVER_H */