Zmiany względem v1:
- Przesunięcie jednej deklaracji z libgadu.h do internal.h.
- Usunięcie zapomnianego gg_debug_session z funkcji
  gg_session_handle_userlist_100_reply.
---
 include/internal.h   |    1 +
 include/libgadu.h.in |   33 +++++++++++++++++++
 include/protocol.h   |   10 ++++++
 src/common.c         |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/debug.c          |    1 +
 src/events.c         |    4 ++
 src/handlers.c       |   31 ++++++++++++++++++
 7 files changed, 167 insertions(+), 0 deletions(-)

diff --git a/include/internal.h b/include/internal.h
index dc753e0..8f0848f 100644
--- a/include/internal.h
+++ b/include/internal.h
@@ -38,6 +38,7 @@ int gg_resolve_pthread(int *fd, void **resolver, const char 
*hostname);
 void gg_resolve_pthread_cleanup(void *resolver, int kill);
 
 unsigned char *gg_deflate(const char *in, size_t *out_lenp);
+char *gg_inflate(const unsigned char *in, size_t length);
 
 #ifdef HAVE_UINT64_T
 uint64_t gg_fix64(uint64_t x);
diff --git a/include/libgadu.h.in b/include/libgadu.h.in
index ee231f4..7ba3286 100644
--- a/include/libgadu.h.in
+++ b/include/libgadu.h.in
@@ -698,6 +698,7 @@ enum gg_event_t {
        GG_EVENT_MULTILOGON_INFO,       /**< Informacja o innych sesjach 
multilogowania */
 
        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) */
 };
 
 #define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY
@@ -995,6 +996,16 @@ struct gg_event_userlist100_version {
 };
 
 /**
+ * Opis zdarzenia \c GG_EVENT_USERLIST100_REPLY.
+ */
+struct gg_event_userlist100_reply {
+       char type;                      /**< Rodzaj odpowiedzi */
+       uint32_t version;               /**< Aktualna wersja listy kontaktów na 
serwerze */
+       char format_type;               /**< Typ formatu listy kontaktów 
(żądany w \c gg_userlist100_request.format_type) */
+       char *reply;                    /**< Treść listy kontaktów w 
przesyłanej wersji i formacie */
+};
+
+/**
  * Unia wszystkich zdarzeń zwracanych przez funkcje \c gg_watch_fd(), 
  * \c gg_dcc_watch_fd() i \c gg_dcc7_watch_fd().
  *
@@ -1029,6 +1040,7 @@ union gg_event_union {
        struct gg_event_msg multilogon_msg;     /**< Inna sesja wysłała 
wiadomość (\c GG_EVENT_MULTILOGON_MSG) */
        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) */
 };
 
 /**
@@ -2124,6 +2136,27 @@ enum {
 
 #endif /* DOXYGEN */
 
+#ifndef DOXYGEN
+
+#define GG_USERLIST100_REPLY_LIST 0x00
+#define GG_USERLIST100_REPLY_ACK 0x10
+#define GG_USERLIST100_REPLY_REJECT 0x12
+
+#else
+
+/**
+ * \ingroup importexport
+ *
+ * Typ odpowiedzi listy kontaktów (10.0).
+ */
+enum {
+       GG_USERLIST100_REPLY_LIST,      /**< W odpowiedzi znajduje się aktualna 
lista kontaktów na serwerze. */
+       GG_USERLIST100_REPLY_ACK,       /**< Potwierdzenie odebrania nowej 
wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się 
numer nowej wersji listy kontaktów. */
+       GG_USERLIST100_REPLY_REJECT,    /**< Odmowa przyjęcia nowej wersji 
listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer 
wersji listy kontaktów aktualnie przechowywanej przez serwer. */
+};
+
+#endif /* DOXYGEN */
+
 struct gg_dcc_tiny_packet {
        uint8_t type;           /* rodzaj pakietu */
 } GG_PACKED;
diff --git a/include/protocol.h b/include/protocol.h
index 2c2c06c..9e6cee6 100644
--- a/include/protocol.h
+++ b/include/protocol.h
@@ -309,6 +309,16 @@ struct gg_userlist100_request {
        /* char request[]; */
 } GG_PACKED;
 
+#define GG_USERLIST100_REPLY 0x41
+
+struct gg_userlist100_reply {
+       uint8_t type;                   /* rodzaj odpowiedzi */
+       uint32_t version;               /* numer wersji listy kontaktów 
aktualnie przechowywanej przez serwer */
+       uint8_t format_type;            /* rodzaj przesyłanego typu formatu 
listy kontaktów */
+       uint8_t unknown1;               /* 0x01 */
+       /* char reply[]; */
+} GG_PACKED;
+
 #ifdef _WIN32
 #pragma pack(pop)
 #endif
diff --git a/src/common.c b/src/common.c
index 79fcbb0..9fb2743 100644
--- a/src/common.c
+++ b/src/common.c
@@ -671,6 +671,93 @@ fail:
 }
 
 /**
+ * \internal Dekompresuje dane wejściowe w formacie Deflate.
+ *
+ * Wynik funkcji należy zwolnić za pomocą \c free.
+ *
+ * \param in Bufor danych skompresowanych algorytmem Deflate
+ * \param length Długość bufora wejściowego
+ *
+ * \note Dokleja \c \\0 na końcu bufora wynikowego.
+ *
+ * \return Zdekompresowany ciąg znaków, zakończony \c \\0,
+ *         lub \c NULL w przypadku niepowodzenia.
+ */
+char *gg_inflate(const unsigned char *in, size_t length)
+{
+       int ret;
+       z_stream strm;
+       char *out = NULL, *out2;
+       size_t out_len = 1024;
+       int first = 1;
+
+       if (in == NULL)
+               return NULL;
+
+       strm.zalloc = Z_NULL;
+       strm.zfree = Z_NULL;
+       strm.opaque = Z_NULL;
+       strm.avail_in = length;
+       strm.next_in = (unsigned char*) in;
+
+       ret = inflateInit(&strm);
+       if (ret != Z_OK) {
+               gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflateInit() failed 
(%d)\n", ret);
+               return NULL;
+       }
+
+       do {
+               out_len *= 2;
+               out2 = realloc(out, out_len);
+               
+               if (out2 == NULL) {
+                       gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough 
memory for output data (%d)\n", out_len);
+                       goto fail;
+               }
+               
+               out = out2;
+               
+               if (first) {
+                       strm.avail_out = out_len;
+                       strm.next_out = (unsigned char*) out;
+               } else {
+                       strm.avail_out = out_len / 2;
+                       strm.next_out = (unsigned char*) out + out_len / 2;
+               }
+               
+               ret = inflate(&strm, Z_NO_FLUSH);
+               
+               if (ret != Z_OK && ret != Z_STREAM_END) {
+                       gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflate() 
failed (ret=%d, msg=%s)\n", ret, strm.msg != NULL ? strm.msg : "no error 
message provided");
+                       goto fail;
+               }
+               
+               first = 0;
+       } while (ret != Z_STREAM_END);
+
+       /* rezerwujemy ostatni znak na NULL-a */
+       out_len = strm.total_out + 1;
+       out2 = realloc(out, out_len);
+
+       if (out2 == NULL) {
+               gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for 
output data (%d)\n", out_len);
+               goto fail;
+       }
+
+       out = out2;
+       out[out_len - 1] = '\0';
+
+       inflateEnd(&strm);
+
+       return out;
+
+fail:
+       inflateEnd(&strm);
+       free(out);
+       return NULL;
+}
+
+/**
  * \internal Tablica pomocnicza do wyznaczania sumy kontrolnej.
  */
 static const uint32_t gg_crc32_table[256] =
diff --git a/src/debug.c b/src/debug.c
index f253ec9..8eebf62 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -329,6 +329,7 @@ const char *gg_debug_event(enum gg_event_t event)
        GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_MSG)
        GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_INFO)
        GG_DEBUG_EVENT(GG_EVENT_USERLIST100_VERSION)
+       GG_DEBUG_EVENT(GG_EVENT_USERLIST100_REPLY)
 #undef GG_DEBUG_EVENT
 
        // Celowo nie ma default, żeby kompilator wyłapał brakujące stany
diff --git a/src/events.c b/src/events.c
index 80be78c..47a4d84 100644
--- a/src/events.c
+++ b/src/events.c
@@ -165,6 +165,10 @@ void gg_event_free(struct gg_event *e)
 
                        break;
                }
+
+               case GG_EVENT_USERLIST100_REPLY:
+                       free(e->event.userlist100_reply.reply);
+                       break;
        }
 
        free(e);
diff --git a/src/handlers.c b/src/handlers.c
index d2a18fc..ce33f39 100644
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -1712,6 +1712,36 @@ static int gg_session_handle_userlist_100_version(struct 
gg_session *gs, uint32_
 }
 
 /**
+ * \internal Obsługuje pakiet GG_USERLIST100_REPLY.
+ *
+ * Patrz gg_packet_handler_t
+ */
+static int gg_session_handle_userlist_100_reply(struct gg_session *gs, 
uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+{
+       struct gg_userlist100_reply *reply = (struct gg_userlist100_reply*) ptr;
+       char *data = NULL;
+
+       gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() 
received userlist 100 reply\n");
+
+       if (len > sizeof(*reply)) {
+               data = gg_inflate((const unsigned char*) ptr + sizeof(*reply), 
len - sizeof(*reply));
+               
+               if (data == NULL) {
+                       gg_debug_session(gs, GG_DEBUG_MISC, "// 
gg_handle_userlist_100_reply() gg_inflate() failed\n");
+                       return -1;
+               }
+       }
+
+       ge->type = GG_EVENT_USERLIST100_REPLY;
+       ge->event.userlist100_reply.type = reply->type;
+       ge->event.userlist100_reply.version = gg_fix32(reply->version);
+       ge->event.userlist100_reply.format_type = reply->format_type;
+       ge->event.userlist100_reply.reply = data;
+
+       return 0;
+}
+
+/**
  * \internal Tablica obsługiwanych pakietów
  */
 static const gg_packet_handler_t handlers[] =
@@ -1752,6 +1782,7 @@ static const gg_packet_handler_t handlers[] =
        { GG_XML_ACTION, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
        { 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 },
 };
 
 /**
-- 
1.7.5.rc1

_______________________________________________
libgadu-devel mailing list
[email protected]
http://lists.ziew.org/mailman/listinfo/libgadu-devel

Reply via email to