]> git.pld-linux.org Git - packages/kadu.git/commitdiff
outdated
authorPaweł Gołaszewski <blues@pld-linux.org>
Thu, 15 Aug 2002 15:01:57 +0000 (15:01 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    kadu-am.patch -> 1.4
    kadu-libgg.patch -> 1.2

kadu-am.patch [deleted file]
kadu-libgg.patch [deleted file]

diff --git a/kadu-am.patch b/kadu-am.patch
deleted file mode 100644 (file)
index 91a9f51..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
---- kadu/Makefile.in~  Fri Apr  5 21:10:19 2002
-+++ kadu/Makefile.in   Fri Apr  5 21:24:44 2002
-@@ -600,13 +600,13 @@
-       $(INSTALL_DATA) $(srcdir)/kadu.desktop $(DESTDIR)$(kde_appsdir)/Applications/kadu.desktop
-       $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/32x32/apps/
-
--      $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/locolor/32x32/apps/
-+#     $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/locolor/32x32/apps/
- #>-   $(INSTALL_DATA) $(srcdir)/hi32-app-kadu.png $(kde_icondir)/hicolor/32x32/apps/kadu.png
- #>+ 1
-       $(INSTALL_DATA) $(srcdir)/hi32-app-kadu.png $(DESTDIR)$(kde_icondir)/hicolor/32x32/apps/kadu.png
-       $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/hicolor/16x16/apps/
-
--      $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/locolor/16x16/apps/
-+#     $(mkinstalldirs) $(DESTDIR)$(kde_icondir)/locolor/16x16/apps/
- #>-   $(INSTALL_DATA) $(srcdir)/hi16-app-kadu.png $(kde_icondir)/hicolor/16x16/apps/kadu.png
- #>+ 1
-       $(INSTALL_DATA) $(srcdir)/hi16-app-kadu.png $(DESTDIR)$(kde_icondir)/hicolor/16x16/apps/kadu.png
---- ekg/Makefile.in~   Sun Mar 17 18:53:11 2002
-+++ ekg/Makefile.in    Mon Apr 29 15:22:39 2002
-@@ -16,7 +16,7 @@
- CFLAGS = @DFLAGS@ @CFLAGS@ $(INCLUDES) -DTHEMES_DIR=\"$(datadir)/ekg/themes\" -DIOCTL_DAEMON_PATH=\"$(prefix)/bin/ioctl_daemon\"
- OBJS = stuff.o commands.o events.o themes.o vars.o dynstuff.o
--all:  libgadu ekg
-+all:  libgadu
- ekg:  
-       (cd src; $(MAKE) all)
-
---- ekg/configure~     Sun Mar 17 18:53:11 2002
-+++ ekg/configure      Mon Apr 29 15:28:00 2002
-@@ -4601,7 +4601,7 @@
- echo "${ECHO_T} just kidding :)" >&6
- fi
--ac_config_files="$ac_config_files Makefile lib/Makefile src/Makefile examples/Makefile"
-+ac_config_files="$ac_config_files Makefile lib/Makefile src/Makefile"
- cat >confcache <<\_ACEOF
- # This file is a shell script that caches the results of configure
- # tests run on this system so they can be shared between configure
diff --git a/kadu-libgg.patch b/kadu-libgg.patch
deleted file mode 100644 (file)
index 06339a3..0000000
+++ /dev/null
@@ -1,1995 +0,0 @@
-diff -urN kadu-0.1.6b.org/kadu/Makefile.am kadu-0.1.6b/kadu/Makefile.am
---- kadu-0.1.6b.org/kadu/Makefile.am   Sat Sep 29 16:56:11 2001
-+++ kadu-0.1.6b/kadu/Makefile.am       Sat Sep 29 17:00:54 2001
-@@ -1,7 +1,7 @@
- ####### kdevelop will overwrite this part!!! (begin)##########
- bin_PROGRAMS = kadu
--kadu_SOURCES = search.cpp userlist.cpp history.cpp chat.cpp events.cpp kadu.cpp main.cpp 
--kadu_LDADD   = -lgg -lpthread $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) $(LIBSOCKET)
-+kadu_SOURCES = search.cpp userlist.cpp history.cpp chat.cpp events.cpp kadu.cpp main.cpp libgg.c libgg_search.c
-+kadu_LDADD   = -lpthread $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) $(LIBSOCKET)
- EXTRA_DIST = main.cpp kadu.cpp kadu.h kadu.desktop lo32-app-kadu.png lo16-app-kadu.png events.h events.cpp chat.cpp chat.h history.h history.cpp pixmaps.h userlist.cpp search.h search.cpp libgg.h 
-diff -urN kadu-0.1.6b.org/kadu/libgg.c kadu-0.1.6b/kadu/libgg.c
---- kadu-0.1.6b.org/kadu/libgg.c       Thu Jan  1 01:00:00 1970
-+++ kadu-0.1.6b/kadu/libgg.c   Sat Sep 29 17:00:32 2001
-@@ -0,0 +1,1247 @@
-+/* $Id$ */
-+
-+/*
-+ *  (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>
-+ *
-+ *  This program is free software; you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License Version 2 as
-+ *  published by the Free Software Foundation.
-+ *
-+ *  This program is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *  GNU General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License
-+ *  along with this program; if not, write to the Free Software
-+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <sys/socket.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#include <sys/ioctl.h>
-+#include <sys/wait.h>
-+#include <netdb.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <stdarg.h>
-+#include <pwd.h>
-+#include "endian.h"
-+#include "libgg.h"
-+
-+extern int gg_debug_level;
-+
-+#ifdef GG_DEBUG
-+
-+/*
-+ * gg_debug_real()
-+ *
-+ * wyrzuca komunikat o danym poziomie, o ile u¿ytkownik sobie tego ¿yczy.
-+ *
-+ *  - level - poziom wiadomo¶ci,
-+ *  - format... - tre¶æ wiadomo¶ci (printf-alike.)
-+ *
-+ * niczego nie zwraca.
-+ */
-+void gg_debug_real(int level, char *format, ...)
-+{
-+      va_list ap;
-+      
-+      if ((gg_debug_level & level)) {
-+              va_start(ap, format);
-+              vprintf(format, ap);
-+              va_end(ap);
-+      }
-+}
-+
-+#endif /* GG_DEBUG */
-+
-+/*
-+ * fix32() // funkcja wewnêtrzna
-+ *
-+ * dla maszyn big-endianowych zamienia kolejno¶æ bajtów w ,,long''ach.
-+ */
-+static inline unsigned long fix32(unsigned long x)
-+{
-+#if __BYTE_ORDER == __LITTLE_ENDIAN
-+      return x;
-+#else
-+      char *y = &x;
-+
-+      return (y[0] << 24 + y[1] << 16 + y[2] << 8 + y[3]);
-+#endif                
-+}
-+
-+/*
-+ * fix16() // funkcja wewnêtrzna
-+ *
-+ * dla maszyn big-endianowych zamienia kolejno¶æ bajtów w ,,short''ach.
-+ */
-+static inline unsigned short fix16(unsigned short x)
-+{
-+#if __BYTE_ORDER == __LITTLE_ENDIAN
-+      return x;
-+#else
-+      char *y = &x;
-+
-+      return (y[0] << 8 + y[1]);
-+#endif        
-+}
-+
-+/*
-+ * gg_alloc_sprintf() // funkcja wewnêtrzna
-+ *
-+ * robi dok³adnie to samo, co sprintf(), tyle ¿e alokuje sobie wcze¶niej
-+ * miejsce na dane. jak znam ¿ycie, ze wzglêdu na ró¿nice miêdzy funkcjami
-+ * vsnprintf() na ró¿nych platformach, nie bêdzie dzia³a³o ;)
-+ *
-+ *  - format, ... - parametry takie same jak w innych funkcjach *printf()
-+ *
-+ * zwraca zaalokowany buforek, który wypada³oby pó¼niej zwolniæ, lub NULL
-+ * je¶li nie uda³o siê wykonaæ zadania.
-+ */
-+char *gg_alloc_sprintf(char *format, ...)
-+{
-+      va_list ap;
-+      char *buf = NULL;
-+      int size;
-+
-+      va_start(ap, format);
-+
-+      if ((size = vsnprintf(buf, 0, format, ap)) < 0)
-+              return NULL;
-+
-+      if (!(buf = malloc(size + 1)))
-+              return NULL;
-+
-+      vsnprintf(buf, size + 1, format, ap);
-+
-+      va_end(ap);
-+
-+      return buf;
-+}
-+
-+/*
-+ * gg_resolve() // funkcja wewnêtrzna
-+ *
-+ * tworzy pipe'y, forkuje siê i w drugim procesie zaczyna resolvowaæ 
-+ * podanego hosta. zapisuje w sesji deskryptor pipe'u. je¶li co¶ tam
-+ * bêdzie gotowego, znaczy, ¿e mo¿na wczytaæ ,,struct in_addr''. je¶li
-+ * nie znajdzie, zwraca INADDR_NONE.
-+ *
-+ *  - fd - wska¼nik gdzie wrzuciæ deskryptor,
-+ *  - pid - gdzie wrzuciæ pid dzieciaka,
-+ *  - hostname - nazwa hosta do zresolvowania.
-+ *
-+ * zwraca 0 je¶li uda³o siê odpaliæ proces lub -1 w przypadku b³êdu.
-+ */
-+int gg_resolve(int *fd, int *pid, char *hostname)
-+{
-+      int pipes[2], res;
-+      struct in_addr a;
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(..., \"%s\");\n", hostname);
-+      
-+      if (!fd | !pid) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+
-+      if (pipe(pipes) == -1)
-+              return -1;
-+
-+      if ((res = fork()) == -1)
-+              return -1;
-+
-+      if (!res) {
-+              if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) {
-+                      struct hostent *he;
-+              
-+                      if (!(he = gethostbyname(hostname)))
-+                              a.s_addr = INADDR_NONE;
-+                      else
-+                              memcpy((char*) &a, he->h_addr, sizeof(a));
-+              }
-+
-+              write(pipes[1], &a, sizeof(a));
-+
-+              exit(0);
-+      }
-+
-+      close(pipes[1]);
-+
-+      *fd = pipes[0];
-+      *pid = res;
-+
-+      return 0;
-+}
-+
-+/*
-+ * gg_connect() // funkcja wewnêtrzna
-+ *
-+ * ³±czy siê z serwerem. pierwszy argument jest typu (void *), ¿eby nie
-+ * musieæ niczego inkludowaæ w libgg.h i nie psuæ jaki¶ g³upich zale¿no¶ci
-+ * na dziwnych systemach.
-+ *
-+ *  - addr - adres serwera (struct in_addr *),
-+ *  - port - port serwera,
-+ *  - async - ma byæ asynchroniczne po³±czenie?
-+ *
-+ * zwraca po³±czonego socketa lub -1 w przypadku b³êdu. zobacz errno.
-+ */
-+int gg_connect(void *addr, int port, int async)
-+{
-+      int sock, one = 1;
-+      struct sockaddr_in sin;
-+      struct in_addr *a = addr;
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async);
-+      
-+      if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
-+              gg_debug(GG_DEBUG_MISC, "-- socket() failed. errno = %d (%s)\n", errno, strerror(errno));
-+              return -1;
-+      }
-+
-+      if (async) {
-+              if (ioctl(sock, FIONBIO, &one) == -1) {
-+                      gg_debug(GG_DEBUG_MISC, "-- ioctl() failed. errno = %d (%s)\n", errno, strerror(errno));
-+                      return -1;
-+              }
-+      }
-+
-+      sin.sin_port = htons(port);
-+      sin.sin_family = AF_INET;
-+      sin.sin_addr.s_addr = a->s_addr;
-+      
-+      if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
-+              gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno));
-+              if (errno && (!async || errno != EINPROGRESS))
-+                      return -1;
-+      }
-+      
-+      return sock;
-+}
-+
-+/*
-+ * gg_read_line() // funkcja wewnêtrzna
-+ *
-+ * czyta jedn± liniê tekstu z socketa.
-+ *
-+ *  - sock - socket,
-+ *  - buf - wska¼nik bufora,
-+ *  - length - d³ugo¶æ bufora.
-+ *
-+ * olewa b³êdy. je¶li na jaki¶ trafi, potraktuje go jako koniec linii.
-+ */
-+static void gg_read_line(int sock, char *buf, int length)
-+{
-+      int ret;
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_read_line(...);\n");
-+      
-+      for (; length > 1; buf++, length--) {
-+              do {
-+                      if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) {
-+                              *buf = 0;
-+                              return;
-+                      }
-+              } while (ret == -1 && errno == EINTR);
-+
-+              if (*buf == '\n') {
-+                      buf++;
-+                      break;
-+              }
-+      }
-+
-+      *buf = 0;
-+      return;
-+}
-+
-+/*
-+ * gg_recv_packet() // funkcja wewnêtrzna
-+ *
-+ * odbiera jeden pakiet gg i zwraca wska¼nik do niego. pamiêæ po nim
-+ * wypada³oby uwolniæ.
-+ *
-+ *  - sock - po³±czony socket.
-+ *
-+ * je¶li wyst±pi³ b³±d, zwraca NULL. reszta w errno.
-+ */
-+static void *gg_recv_packet(struct gg_session *sess)
-+{
-+      struct gg_header h;
-+      char *buf = NULL;
-+      int ret = 0, offset, size = 0;
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(...);\n");
-+      
-+      if (!sess) {
-+              errno = EFAULT;
-+              return NULL;
-+      }
-+
-+      if (sess->recv_left < 1) {
-+              while (ret != sizeof(h)) {
-+                      ret = read(sess->fd, &h, sizeof(h));
-+                      gg_debug(GG_DEBUG_MISC, "-- header recv(..., %d) = %d\n", sizeof(h), ret);
-+                      if (ret < sizeof(h)) {
-+                              if (errno != EINTR) {
-+                                      gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno));
-+                                      return NULL;
-+                              }
-+                      }
-+              }
-+
-+              h.type = fix32(h.type);
-+              h.length = fix32(h.length);
-+      } else {
-+              memcpy(&h, sess->recv_buf, sizeof(h));
-+      }
-+
-+      /* jakie¶ sensowne limity na rozmiar pakietu */
-+      if (h.length < 0 || h.length > 65535) {
-+              gg_debug(GG_DEBUG_MISC, "-- invalid packet length (%d)\n", h.length);
-+              errno = ERANGE;
-+              return NULL;
-+      }
-+
-+      if (sess->recv_left > 0) {
-+              gg_debug(GG_DEBUG_MISC, "-- resuming last gg_recv_packet()\n");
-+              size = sess->recv_left;
-+              offset = sess->recv_done;
-+              buf = sess->recv_buf;
-+      } else {
-+              if (!(buf = malloc(sizeof(h) + h.length + 1))) {
-+                      gg_debug(GG_DEBUG_MISC, "-- not enough memory\n");
-+                      return NULL;
-+              }
-+
-+              memcpy(buf, &h, sizeof(h));
-+
-+              offset = 0;
-+              size = h.length;
-+      }
-+
-+      while (size > 0) {
-+              ret = read(sess->fd, buf + sizeof(h) + offset, size);
-+              gg_debug(GG_DEBUG_MISC, "-- body recv(..., %d) = %d\n", size, ret);
-+              if (ret > -1 && ret <= size) {
-+                      offset += ret;
-+                      size -= ret;
-+              } else if (ret == -1) { 
-+                      gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno));
-+                      if (errno == EAGAIN) {
-+                              gg_debug(GG_DEBUG_MISC, "-- %d bytes received, %d left\n", offset, size);
-+                              sess->recv_buf = buf;
-+                              sess->recv_left = size;
-+                              sess->recv_done = offset;
-+                              return NULL;
-+                      }
-+                      if (errno != EINTR) {
-+//                            errno = EINVAL;
-+                              free(buf);
-+                              return NULL;
-+                      }
-+              }
-+      }
-+
-+      sess->recv_left = 0;
-+
-+#ifdef GG_DEBUG
-+      if ((gg_debug_level & GG_DEBUG_DUMP)) {
-+              int i;
-+
-+              gg_debug(GG_DEBUG_DUMP, ">> received packet (type=%.2x):", h.type);
-+              for (i = 0; i < sizeof(h) + h.length; i++) 
-+                      gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]);
-+              gg_debug(GG_DEBUG_DUMP, "\n");
-+      }
-+#endif
-+
-+      return buf;
-+}
-+
-+/*
-+ * gg_send_packet() // funkcja wewnêtrzna
-+ *
-+ * konstruuje pakiet i wysy³a go w do serwera.
-+ *
-+ *  - sock - po³±czony socket,
-+ *  - type - typ pakietu,
-+ *  - packet - wska¼nik do struktury pakietu,
-+ *  - length - d³ugo¶æ struktury pakietu,
-+ *  - payload - dodatkowy tekst doklejany do pakietu (np. wiadomo¶æ),
-+ *  - payload_length - d³ugo¶æ dodatkowego tekstu.
-+ *
-+ * je¶li posz³o dobrze, zwraca 0. w przypadku b³êdu -1. je¶li errno=ENOMEM,
-+ * zabrak³o pamiêci. inaczej by³ b³±d przy wysy³aniu pakietu. dla errno=0
-+ * nie wys³ano ca³ego pakietu.
-+ */
-+static int gg_send_packet(int sock, int type, void *packet, int length, void *payload, int payload_length)
-+{
-+      struct gg_header *h;
-+      int res, plen;
-+      char *tmp;
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(0x%.2x, %d, %d);\n", type, length, payload_length);
-+      
-+      if (length < 0 || payload_length < 0) {
-+              gg_debug(GG_DEBUG_MISC, "-- invalid packet/payload length\n");
-+              errno = ERANGE;
-+              return -1;
-+      }
-+
-+      if (!(tmp = malloc(sizeof(struct gg_header) + length + payload_length))) {
-+              gg_debug(GG_DEBUG_MISC, "-- not enough memory\n");
-+              return -1;
-+      }
-+
-+      h = (struct gg_header*) tmp;
-+      h->type = fix32(type);
-+      h->length = fix32(length + payload_length);
-+
-+      if (packet)
-+              memcpy(tmp + sizeof(struct gg_header), packet, length);
-+      if (payload)
-+              memcpy(tmp + sizeof(struct gg_header) + length, payload, payload_length);
-+
-+#ifdef GG_DEBUG
-+      if ((gg_debug_level & GG_DEBUG_DUMP)) {
-+              int i;
-+
-+              gg_debug(GG_DEBUG_DUMP, "%%%% sending packet (type=%.2x):", fix32(h->type));
-+              for (i = 0; i < sizeof(struct gg_header) + fix32(h->length); i++)
-+                      gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]);
-+              gg_debug(GG_DEBUG_DUMP, "\n");
-+      }
-+#endif
-+
-+      plen = sizeof(struct gg_header) + length + payload_length;
-+      
-+      if ((res = write(sock, tmp, plen)) < plen) {
-+              gg_debug(GG_DEBUG_MISC, "-- write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno));
-+              free(tmp);
-+              return -1;
-+      }
-+
-+      free(tmp);      
-+      return 0;
-+}
-+
-+
-+/*
-+ * gg_login()
-+ *
-+ * rozpoczyna procedurê ³±czenia siê z serwerem. resztê obs³guje siê przez
-+ * gg_watch_event.
-+ *
-+ *  - uin - numerek usera,
-+ *  - password - jego hase³ko,
-+ *  - async - ma byæ asynchronicznie?
-+ *
-+ * UWAGA! program musi obs³u¿yæ SIGCHLD, je¶li ³±czy siê asynchronicznie,
-+ * ¿eby zrobiæ pogrzeb zmar³emu procesowi resolvera.
-+ *
-+ * w przypadku b³êdu zwraca NULL, je¶li idzie dobrze (async) albo posz³o
-+ * dobrze (sync), zwróci wska¼nik do zaalokowanej struktury `gg_session'.
-+ */
-+struct gg_session *gg_login(uin_t uin, char *password, int async)
-+{
-+      struct gg_session *sess;
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%u, \"...\", %d);\n", uin, async);
-+
-+      if (!(sess = malloc(sizeof(*sess))))
-+              return NULL;
-+
-+      sess->uin = uin;
-+      if (!(sess->password = strdup(password))) {
-+              free(sess);
-+              return NULL;
-+      }
-+      sess->state = GG_STATE_RESOLVING;
-+      sess->check = GG_CHECK_READ;
-+      sess->async = async;
-+      sess->seq = 0;
-+      sess->recv_left = 0;
-+
-+      if (async) {
-+              if (gg_resolve(&sess->fd, &sess->pid, GG_APPMSG_HOST)) {
-+                      gg_debug(GG_DEBUG_MISC, "-- resolving failed\n");
-+                      free(sess);
-+                      return NULL;
-+              }
-+      } else {
-+              struct in_addr a;
-+
-+              if ((a.s_addr = inet_addr(GG_APPMSG_HOST)) == INADDR_NONE) {
-+                      struct hostent *he;
-+      
-+                      if (!(he = gethostbyname(GG_APPMSG_HOST))) {
-+                              gg_debug(GG_DEBUG_MISC, "-- host %s not found\n", GG_APPMSG_HOST);
-+                              free(sess);
-+                              return NULL;
-+                      } else
-+                              memcpy((char*) &a, he->h_addr, sizeof(a));
-+              }
-+
-+              if (!(sess->fd = gg_connect(&a, GG_APPMSG_PORT, 0)) == -1) {
-+                      gg_debug(GG_DEBUG_MISC, "-- connection failed\n");
-+                      free(sess);
-+                      return NULL;
-+              }
-+
-+              sess->state = GG_STATE_CONNECTING_HTTP;
-+
-+              while (sess->state != GG_STATE_CONNECTED) {
-+                      struct gg_event *e;
-+
-+                      if (!(e = gg_watch_fd(sess))) {
-+                              gg_debug(GG_DEBUG_MISC, "-- some nasty error in gg_watch_fd()\n");
-+                              free(sess);
-+                              return NULL;
-+                      }
-+
-+                      if (e->type == GG_EVENT_CONN_FAILED) {
-+                              gg_debug(GG_DEBUG_MISC, "-- could not login\n");
-+                              gg_free_event(e);
-+                              free(sess);
-+                              return NULL;
-+                      }
-+
-+                      gg_free_event(e);
-+              }
-+      }
-+
-+      return sess;
-+}
-+
-+/* 
-+ * gg_free_session()
-+ *
-+ * zwalnia pamiêæ zajmowan± przez opis sesji.
-+ *
-+ *  - sess - opis sesji.
-+ *
-+ * nie zwraca niczego, bo i po co?
-+ */
-+void gg_free_session(struct gg_session *sess)
-+{
-+      if (!sess)
-+              return;
-+
-+      free(sess->password);
-+      free(sess);
-+}
-+
-+/*
-+ * gg_change_status()
-+ *
-+ * zmienia status u¿ytkownika. przydatne do /away i /busy oraz /quit.
-+ *
-+ *  - sess - opis sesji,
-+ *  - status - nowy status u¿ytkownika.
-+ *
-+ * je¶li wys³a³ pakiet zwraca 0, je¶li nie uda³o siê, zwraca -1.
-+ */
-+int gg_change_status(struct gg_session *sess, int status)
-+{
-+      struct gg_new_status p;
-+
-+      if (!sess) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+
-+      if (sess->state != GG_STATE_CONNECTED) {
-+              errno = ENOTCONN;
-+              return -1;
-+      }
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status(..., %d);\n", status);
-+
-+      p.status = fix32(status);
-+
-+      return gg_send_packet(sess->fd, GG_NEW_STATUS, &p, sizeof(p), NULL, 0);
-+}
-+
-+/*
-+ * gg_logoff()
-+ *
-+ * wylogowuje u¿ytkownika i zamyka po³±czenie.
-+ *
-+ *  - sock - deskryptor socketu.
-+ *
-+ * nie zwraca b³êdów. skoro siê ¿egnamy, to olewamy wszystko.
-+ */
-+void gg_logoff(struct gg_session *sess)
-+{
-+      if (!sess)
-+              return;
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(...);\n");
-+
-+      if (sess->state == GG_STATE_CONNECTED)
-+              gg_change_status(sess, GG_STATUS_NOT_AVAIL);
-+      
-+      if (sess->fd) {
-+              shutdown(sess->fd, 2);
-+              close(sess->fd);
-+      }
-+}
-+
-+/*
-+ * gg_send_message()
-+ *
-+ * wysy³a wiadomo¶æ do innego u¿ytkownika. zwraca losowy numer
-+ * sekwencyjny, który mo¿na olaæ albo wykorzystaæ do potwierdzenia.
-+ *
-+ *  - sess - opis sesji,
-+ *  - msgclass - rodzaj wiadomo¶ci,
-+ *  - recipient - numer adresata,
-+ *  - message - tre¶æ wiadomo¶ci.
-+ *
-+ * w przypadku b³êdu zwraca -1, inaczej numer sekwencyjny.
-+ */
-+int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, unsigned char *message)
-+{
-+      struct gg_send_msg s;
-+
-+      if (!sess) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+      
-+      if (sess->state != GG_STATE_CONNECTED) {
-+              errno = ENOTCONN;
-+              return -1;
-+      }
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message(..., %d, %u, \"...\");\n", msgclass, recipient);
-+
-+      s.recipient = fix32(recipient);
-+      if (!sess->seq)
-+              sess->seq = 0x01740000 | (rand() & 0xffff);
-+      s.seq = fix32(sess->seq);
-+      s.msgclass = fix32(msgclass);
-+      sess->seq += (rand() % 0x300) + 0x300;
-+      
-+      if (gg_send_packet(sess->fd, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1) == -1)
-+              return -1;
-+
-+      return fix32(s.seq);
-+}
-+
-+/*
-+ * gg_ping()
-+ *
-+ * wysy³a do serwera pakiet typu yeah-i'm-still-alive.
-+ *
-+ *  - sess - zgadnij.
-+ *
-+ * je¶li nie powiod³o siê wys³anie pakietu, zwraca -1. otherwise 0.
-+ */
-+int gg_ping(struct gg_session *sess)
-+{
-+      if (!sess) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+
-+      if (sess->state != GG_STATE_CONNECTED) {
-+              errno = ENOTCONN;
-+              return -1;
-+      }
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_ping(...);\n");
-+
-+      return gg_send_packet(sess->fd, GG_PING, NULL, 0, NULL, 0);
-+}
-+
-+/*
-+ * gg_free_event()
-+ *
-+ * zwalnia pamiêæ zajmowan± przez informacjê o zdarzeniu
-+ *
-+ *  - event - wska¼nik do informacji o zdarzeniu
-+ *
-+ * nie ma czego zwracaæ.
-+ */
-+void gg_free_event(struct gg_event *e)
-+{
-+      if (!e)
-+              return;
-+      if (e->type == GG_EVENT_MSG)
-+              free(e->event.msg.message);
-+      if (e->type == GG_EVENT_NOTIFY)
-+              free(e->event.notify);
-+      free(e);
-+}
-+
-+/*
-+ * gg_notify()
-+ *
-+ * wysy³a serwerowi listê ludków, za którymi têsknimy.
-+ *
-+ *  - sess - identyfikator sesji,
-+ *  - userlist - wska¼nik do tablicy numerów,
-+ *  - count - ilo¶æ numerków.
-+ *
-+ * je¶li uda³o siê, zwraca 0. je¶li b³±d, dostajemy -1.
-+ */
-+int gg_notify(struct gg_session *sess, uin_t *userlist, int count)
-+{
-+      struct gg_notify *n;
-+      uin_t *u;
-+      int i, res = 0;
-+
-+      if (!sess) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+      
-+      if (sess->state != GG_STATE_CONNECTED) {
-+              errno = ENOTCONN;
-+              return -1;
-+      }
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(..., %d);\n", count);
-+      
-+      if (!userlist || !count)
-+              return 0;
-+      
-+      if (!(n = (struct gg_notify*) malloc(sizeof(*n) * count)))
-+              return -1;
-+      
-+      for (u = userlist, i = 0; i < count; u++, i++) { 
-+              n[i].uin = fix32(*u);
-+              n[i].dunno1 = 3;
-+      }
-+      
-+      if (gg_send_packet(sess->fd, GG_NOTIFY, n, sizeof(*n) * count, NULL, 0) == -1)
-+              res = -1;
-+
-+      free(n);
-+
-+      return res;
-+}
-+
-+/*
-+ * gg_add_notify()
-+ *
-+ * dodaje w locie do listy ukochanych dany numerek.
-+ *
-+ *  - sess - identyfikator sesji,
-+ *  - uin - numerek ukochanej.
-+ *
-+ * je¶li uda³o siê wys³aæ, daje 0. inaczej -1.
-+ */
-+int gg_add_notify(struct gg_session *sess, uin_t uin)
-+{
-+      struct gg_add_remove a;
-+
-+      if (!sess) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+
-+      if (sess->state != GG_STATE_CONNECTED) {
-+              errno = ENOTCONN;
-+              return -1;
-+      }
-+      
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify(..., %u);\n", uin);
-+      
-+      a.uin = fix32(uin);
-+      a.dunno1 = 3;
-+      
-+      return gg_send_packet(sess->fd, GG_ADD_NOTIFY, &a, sizeof(a), NULL, 0);
-+}
-+
-+/*
-+ * gg_remove_notify()
-+ *
-+ * w locie usuwa z listy zainteresowanych.
-+ *
-+ *  - sess - id sesji,
-+ *  - uin - numerek.
-+ *
-+ * zwraca -1 je¶li by³ b³±d, 0 je¶li siê uda³o wys³aæ pakiet.
-+ */
-+int gg_remove_notify(struct gg_session *sess, uin_t uin)
-+{
-+      struct gg_add_remove a;
-+
-+      if (!sess) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+
-+      if (sess->state != GG_STATE_CONNECTED) {
-+              errno = ENOTCONN;
-+              return -1;
-+      }
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify(..., %u);\n", uin);
-+      
-+      a.uin = fix32(uin);
-+      a.dunno1 = 3;
-+      
-+      return gg_send_packet(sess->fd, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL, 0);
-+}
-+
-+/*
-+ * gg_watch_fd_connected() // funkcja wewnêtrzna
-+ *
-+ * patrzy na socketa, odbiera pakiet i wype³nia strukturê zdarzenia.
-+ *
-+ *  - sock - lalala, trudno zgadn±æ.
-+ *
-+ * je¶li b³±d -1, je¶li dobrze 0.
-+ */
-+static int gg_watch_fd_connected(struct gg_session *sess, struct gg_event *e)
-+{
-+      struct gg_header *h;
-+      void *p;
-+
-+      if (!sess) {
-+              errno = EFAULT;
-+              return -1;
-+      }
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd_connected(...);\n");
-+
-+      if (!(h = gg_recv_packet(sess))) {
-+              gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet failed. errno = %d (%d)\n", errno, strerror(errno));
-+              return -1;
-+      }
-+
-+      p = (void*) h + sizeof(struct gg_header);
-+      
-+      if (h->type == GG_RECV_MSG) {
-+              struct gg_recv_msg *r = p;
-+
-+              gg_debug(GG_DEBUG_MISC, "-- received a message\n");
-+
-+              if (h->length >= sizeof(*r)) {
-+                      e->type = GG_EVENT_MSG;
-+                      e->event.msg.msgclass = fix32(r->msgclass);
-+                      e->event.msg.sender = fix32(r->sender);
-+                      e->event.msg.message = strdup((char*) r + sizeof(*r));
-+              }
-+      }
-+
-+      if (h->type == GG_NOTIFY_REPLY) {
-+              struct gg_notify_reply *n = p;
-+
-+              gg_debug(GG_DEBUG_MISC, "-- received a notify reply\n");
-+              
-+              e->type = GG_EVENT_NOTIFY;
-+              if (!(e->event.notify = (void*) malloc(h->length + 2 * sizeof(*n)))) {
-+                      gg_debug(GG_DEBUG_MISC, "-- not enough memory\n");
-+                      free(h);
-+                      return -1;
-+              }
-+              memcpy(e->event.notify, p, h->length);
-+              e->event.notify[h->length / sizeof(*n)].uin = 0;
-+      }
-+
-+      if (h->type == GG_STATUS) {
-+              struct gg_status *s = p;
-+
-+              gg_debug(GG_DEBUG_MISC, "-- received a status change\n");
-+
-+              if (h->length >= sizeof(*s)) {
-+                      e->type = GG_EVENT_STATUS;
-+                      memcpy(&e->event.status, p, h->length);
-+              }
-+      }
-+
-+      if (h->type == GG_SEND_MSG_ACK) {
-+              struct gg_send_msg_ack *s = p;
-+
-+              gg_debug(GG_DEBUG_MISC, "-- received a message ack\n");
-+
-+              if (h->length >= sizeof(*s)) {
-+                      e->type = GG_EVENT_ACK;
-+                      e->event.ack.status = fix32(s->status);
-+                      e->event.ack.recipient = fix32(s->recipient);
-+                      e->event.ack.seq = fix32(s->seq);
-+              }
-+      }
-+
-+      free(h);
-+
-+      return 0;
-+}
-+
-+/*
-+ * gg_chomp() // funkcja wewnêtrzna
-+ *
-+ * ucina "\r\n" lub "\n" z koñca linii.
-+ *
-+ *  - line - ofiara operacji plastycznej.
-+ *
-+ * niczego nie zwraca.
-+ */
-+static void gg_chomp(char *line)
-+{
-+      if (!line || strlen(line) < 1)
-+              return;
-+
-+      if (line[strlen(line) - 1] == '\n')
-+              line[strlen(line) - 1] = 0;
-+      if (line[strlen(line) - 1] == '\r')
-+              line[strlen(line) - 1] = 0;
-+}
-+
-+/*
-+ * gg_watch_fd()
-+ *
-+ * funkcja wywo³ywana, gdy co¶ siê stanie na obserwowanym deskryptorze.
-+ * zwraca klientowi informacjê o tym, co siê dzieje.
-+ *
-+ *  - sess - identyfikator sesji.
-+ *
-+ * zwraca wska¼nik do struktury gg_event, któr± trzeba zwolniæ pó¼niej
-+ * za pomoc± gg_free_event(). jesli rodzaj zdarzenia jest równy
-+ * GG_EVENT_NONE, nale¿y je olaæ kompletnie. je¶li zwróci³o NULL,
-+ * sta³o siê co¶ niedobrego -- albo brak³o pamiêci albo zerwa³o
-+ * po³±czenie albo co¶ takiego.
-+ */
-+struct gg_event *gg_watch_fd(struct gg_session *sess)
-+{
-+      struct gg_event *e;
-+      int res = 0;
-+
-+      if (!sess) {
-+              errno = EFAULT;
-+              return NULL;
-+      }
-+
-+      gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(...);\n");
-+
-+      if (!(e = (void*) malloc(sizeof(*e)))) {
-+              gg_debug(GG_DEBUG_MISC, "-- not enough memory\n");
-+              return NULL;
-+      }
-+
-+      e->type = GG_EVENT_NONE;
-+
-+      switch (sess->state) {
-+              case GG_STATE_RESOLVING:
-+              {
-+                      struct in_addr a;
-+
-+                      gg_debug(GG_DEBUG_MISC, "== GG_STATE_RESOLVING\n");
-+
-+                      if (read(sess->fd, &a, sizeof(a)) < sizeof(a) || a.s_addr == INADDR_NONE) {
-+                              gg_debug(GG_DEBUG_MISC, "-- resolving failed\n");                               
-+
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_RESOLVING;
-+                              sess->state = GG_STATE_IDLE;
-+
-+                              close(sess->fd);
-+
-+                              break;
-+                      }
-+
-+                      close(sess->fd);
-+
-+                      waitpid(sess->pid, NULL, 0);
-+
-+                      gg_debug(GG_DEBUG_MISC, "-- resolved, now connecting\n");
-+
-+                      if ((sess->fd = gg_connect(&a, GG_APPMSG_PORT, sess->async)) == -1) {
-+                              gg_debug(GG_DEBUG_MISC, "-- connection failed\n");
-+
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_CONNECTING;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+
-+                      sess->state = GG_STATE_CONNECTING_HTTP;
-+                      sess->check = GG_CHECK_WRITE;
-+
-+                      break;
-+              }
-+
-+              case GG_STATE_CONNECTING_HTTP:
-+              {
-+                      char buf[1024];
-+                      int res, res_size = sizeof(res);
-+
-+                      gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_HTTP\n");
-+
-+                      if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
-+                              gg_debug(GG_DEBUG_MISC, "-- http connection failed, errno = %d (%s)\n", res, strerror(res));
-+
-+                              errno = res;
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_CONNECTING;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+
-+                      gg_debug(GG_DEBUG_MISC, "-- http connection succeded, sending query\n");
-+
-+
-+                      snprintf(buf, sizeof(buf) - 1,
-+                              "GET /appsvc/appmsg.asp?fmnumber=%u HTTP/1.0\r\n"
-+                              "Host: " GG_APPMSG_HOST "\r\n"
-+                              "User-Agent: Mozilla/4.7 [en] (Win98; I)\r\n"
-+                              "Pragma: no-cache\r\n"
-+                              "\r\n", sess->uin);
-+
-+                      if (write(sess->fd, buf, strlen(buf)) < strlen(buf)) {
-+                              gg_debug(GG_DEBUG_MISC, "-- sending query failed\n");
-+
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_WRITING;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+
-+                      sess->state = GG_STATE_WRITING_HTTP;
-+                      sess->check = GG_CHECK_READ;
-+
-+                      break;
-+              }
-+
-+              case GG_STATE_WRITING_HTTP:
-+              {
-+                      char buf[1024], *tmp, *host;
-+                      int port = GG_DEFAULT_PORT;
-+                      struct in_addr a;
-+
-+                      gg_debug(GG_DEBUG_MISC, "== GG_STATE_WRITING_HTTP\n");
-+
-+                      gg_read_line(sess->fd, buf, sizeof(buf) - 1);
-+                      gg_chomp(buf);
-+      
-+                      gg_debug(GG_DEBUG_TRAFFIC, "-- got http response (%s)\n", buf);
-+      
-+                      if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) {
-+                              gg_debug(GG_DEBUG_MISC, "-- but that's not what we've expected\n");
-+
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_INVALID;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+      
-+                      while (strcmp(buf, "\r\n") && strcmp(buf, ""))
-+                              gg_read_line(sess->fd, buf, sizeof(buf) - 1);
-+
-+                      gg_read_line(sess->fd, buf, sizeof(buf) - 1);
-+                      gg_chomp(buf);
-+      
-+                      close(sess->fd);
-+      
-+                      gg_debug(GG_DEBUG_TRAFFIC, "-- received http data (%s)\n", buf);
-+
-+                      tmp = buf;
-+                      while (*tmp && *tmp != ' ')
-+                              tmp++;
-+                      while (*tmp && *tmp == ' ')
-+                              tmp++;
-+                      while (*tmp && *tmp != ' ')
-+                              tmp++;
-+                      while (*tmp && *tmp == ' ')
-+                              tmp++;
-+                      while (*tmp && *tmp != ' ')
-+                              tmp++;
-+                      while (*tmp && *tmp == ' ')
-+                              tmp++;
-+                      host = tmp;
-+                      while (*tmp && *tmp != ' ')
-+                              tmp++;
-+                      *tmp = 0;
-+
-+                      if ((tmp = strchr(host, ':'))) {
-+                              *tmp = 0;
-+                              port = atoi(tmp+1);
-+                      }
-+
-+                      a.s_addr = inet_addr(host);
-+
-+                      if ((sess->fd = gg_connect(&a, port, sess->async)) == -1) {
-+                              gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno));
-+
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_CONNECTING;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+
-+                      sess->state = GG_STATE_CONNECTING_GG;
-+                      sess->check = GG_CHECK_WRITE;
-+              
-+                      break;
-+              }
-+
-+              case GG_STATE_CONNECTING_GG:
-+              {
-+                      int res, res_size = sizeof(res);
-+
-+                      gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_GG\n");
-+
-+                      if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
-+                              gg_debug(GG_DEBUG_MISC, "-- connection failed, errno = %d (%s)\n", errno, strerror(errno));
-+
-+                              errno = res;
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_CONNECTING;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+
-+                      gg_debug(GG_DEBUG_MISC, "-- connected\n");
-+                      
-+                      sess->state = GG_STATE_WAITING_FOR_KEY;
-+                      sess->check = GG_CHECK_READ;
-+
-+                      break;
-+              }
-+
-+              case GG_STATE_WAITING_FOR_KEY:
-+              {
-+                      struct gg_header *h;                    
-+                      struct gg_welcome *w;
-+                      struct gg_login l;
-+                      unsigned int hash;
-+                      char *password = sess->password;
-+
-+                      gg_debug(GG_DEBUG_MISC, "== GG_STATE_WAITING_FOR_KEY\n");
-+
-+                      if (!(h = gg_recv_packet(sess))) {
-+                              gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet() failed. errno = %d (%s)\n", errno, strerror(errno));
-+
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_READING;
-+                              sess->state = GG_STATE_IDLE;
-+                              close(sess->fd);
-+                              break;
-+                      }
-+      
-+                      if (h->type != GG_WELCOME) {
-+                              gg_debug(GG_DEBUG_MISC, "-- invalid packet received\n");
-+
-+                              free(h);
-+                              close(sess->fd);
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_INVALID;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+      
-+                      w = (void*) h + sizeof(struct gg_header);
-+                      w->key = fix32(w->key);
-+
-+                      for (hash = 1; *password; password++)
-+                              hash *= (*password) + 1;
-+                      hash *= w->key;
-+      
-+                      gg_debug(GG_DEBUG_DUMP, "%%%% klucz serwera %.4x, hash has³a %.8x\n", w->key, hash);
-+      
-+                      free(h);
-+
-+                      free(sess->password);
-+                      sess->password = NULL;
-+      
-+                      l.uin = fix32(sess->uin);
-+                      l.hash = fix32(hash);
-+                      l.status = fix32(GG_STATUS_AVAIL);
-+                      l.dunno = fix32(0x0b);
-+                      l.local_ip = 0;
-+                      l.local_port = 0;
-+      
-+                      gg_debug(GG_DEBUG_TRAFFIC, "-- sending GG_LOGIN packet\n");
-+
-+                      if (gg_send_packet(sess->fd, GG_LOGIN, &l, sizeof(l), NULL, 0) == -1) {
-+                              gg_debug(GG_DEBUG_TRAFFIC, "-- oops, failed. errno = %d (%s)\n", errno, strerror(errno));
-+
-+                              close(sess->fd);
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_WRITING;
-+                              sess->state = GG_STATE_IDLE;
-+                              break;
-+                      }
-+      
-+                      sess->state = GG_STATE_SENDING_KEY;
-+
-+                      break;
-+              }
-+
-+              case GG_STATE_SENDING_KEY:
-+              {
-+                      struct gg_header *h;
-+
-+                      gg_debug(GG_DEBUG_MISC, "== GG_STATE_SENDING_KEY\n");
-+
-+                      if (!(h = gg_recv_packet(sess))) {
-+                              gg_debug(GG_DEBUG_MISC, "-- recv_packet failed\n");
-+                              e->type = GG_EVENT_CONN_FAILED;
-+                              e->event.failure = GG_FAILURE_READING;
-+                              sess->state = GG_STATE_IDLE;
-+                              close(sess->fd);
-+                              break;
-+                      }
-+      
-+                      if (h->type == GG_LOGIN_OK) {
-+                              gg_debug(GG_DEBUG_MISC, "-- login succeded\n");
-+                              e->type = GG_EVENT_CONN_SUCCESS;
-+                              sess->state = GG_STATE_CONNECTED;
-+                              break;
-+                      }
-+
-+                      if (h->type == GG_LOGIN_FAILED) {
-+                              gg_debug(GG_DEBUG_MISC, "-- login failed\n");
-+                              e->event.failure = GG_FAILURE_PASSWORD;
-+                              errno = EACCES;
-+                      } else {
-+                              gg_debug(GG_DEBUG_MISC, "-- invalid packet\n");
-+                              e->event.failure = GG_FAILURE_INVALID;
-+                      }
-+
-+                      e->type = GG_EVENT_CONN_FAILED;
-+                      sess->state = GG_STATE_IDLE;
-+                      close(sess->fd);
-+
-+                      break;
-+              }
-+
-+              case GG_STATE_CONNECTED:
-+              {
-+                      gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTED\n");
-+
-+                      if ((res = gg_watch_fd_connected(sess, e)) == -1) {
-+
-+                              gg_debug(GG_DEBUG_MISC, "-- watch_fd_connected failed. errno = %d (%s)\n", errno, strerror(errno));
-+
-+                              if (errno == EAGAIN) {
-+                                      e->type = GG_EVENT_NONE;
-+                                      res = 0;
-+                              } else
-+                                      res = -1;
-+                      }
-+                      break;
-+              }
-+      }
-+
-+      if (res == -1) {
-+              free(e);
-+              e = NULL;
-+      }
-+
-+      return e;
-+}
-+
-+
-diff -urN kadu-0.1.6b.org/kadu/libgg.h kadu-0.1.6b/kadu/libgg.h
---- kadu-0.1.6b.org/kadu/libgg.h       Sat Sep 29 16:56:11 2001
-+++ kadu-0.1.6b/kadu/libgg.h   Sat Sep 29 17:00:22 2001
-@@ -1,4 +1,21 @@
--/* $Id$ */
-+/* $Id$ */
-+
-+/*
-+ *  (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>
-+ *
-+ *  This program is free software; you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License Version 2 as
-+ *  published by the Free Software Foundation.
-+ *
-+ *  This program is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *  GNU General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License
-+ *  along with this program; if not, write to the Free Software
-+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
- #ifndef __LIBGG_H
- #define __LIBGG_H
-@@ -19,7 +36,7 @@
-  */
- struct gg_session {
-       int state, check;
--      int fd;
-+      int fd, pid;
-       int port;
-       int seq, async;
-@@ -158,7 +175,7 @@
-       struct gg_search_request request;
-       /* bzdurki */
--      int mode, fd, async, state, check, error;
-+      int mode, fd, async, state, check, error, pid;
-       char *header_buf, *data_buf;
-       int header_size, data_size;
-@@ -180,7 +197,7 @@
-  * je¶li chcemy sobie podebugowaæ, wystarczy zdefiniowaæ GG_DEBUG.
-  */
--// int gg_debug_level;
-+//int gg_debug_level;
- #ifdef GG_DEBUG
-@@ -208,7 +225,7 @@
-  * -------------------------------------------------------------------------
-  */
--int gg_resolve(int *fd, char *hostname);
-+int gg_resolve(int *fd, int *pid, char *hostname);
- int gg_connect(void *addr, int port, int async);
- char *gg_alloc_sprintf(char *format, ...);
-diff -urN kadu-0.1.6b.org/kadu/libgg_search.c kadu-0.1.6b/kadu/libgg_search.c
---- kadu-0.1.6b.org/kadu/libgg_search.c        Thu Jan  1 01:00:00 1970
-+++ kadu-0.1.6b/kadu/libgg_search.c    Sat Sep 29 11:45:22 2001
-@@ -0,0 +1,665 @@
-+/* $Id$ */
-+
-+/*
-+ *  (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>
-+ *
-+ *  This program is free software; you can redistribute it and/or modify
-+ *  it under the terms of the GNU General Public License Version 2 as
-+ *  published by the Free Software Foundation.
-+ *
-+ *  This program is distributed in the hope that it will be useful,
-+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *  GNU General Public License for more details.
-+ *
-+ *  You should have received a copy of the GNU General Public License
-+ *  along with this program; if not, write to the Free Software
-+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdio.h>
-+#include <sys/socket.h>
-+#include <netinet/in.h>
-+#include <arpa/inet.h>
-+#include <sys/wait.h>
-+#include <netdb.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <stdarg.h>
-+#include <ctype.h>
-+#include "libgg.h"
-+
-+/*
-+ * gg_urlencode() // funkcja wewnêtrzna
-+ *
-+ * zamienia podany tekst na ci±g znaków do formularza http. przydaje siê
-+ * przy szukaniu userów z dziwnymi znaczkami.
-+ *
-+ *  - str - ci±g znaków do poprawki.
-+ *
-+ * zwraca zaalokowany bufor, który wypada³oby kiedy¶ zwolniæ albo NULL
-+ * w przypadku b³êdu.
-+ */
-+static char *gg_urlencode(char *str)
-+{
-+      char *p, *q, *buf, hex[] = "0123456789abcdef";
-+      int size = 0;
-+
-+      for (p = str; *p; p++, size++) {
-+              if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9'))
-+                      size += 2;
-+      }
-+
-+      if (!(buf = malloc(size + 1)))
-+              return NULL;
-+
-+      for (p = str, q = buf; *p; p++, q++) {
-+              if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9'))
-+                      *q = *p;
-+              else {
-+                      *q++ = '%';
-+                      *q++ = hex[*p >> 4 & 15];
-+                      *q = hex[*p & 15];
-+              }
-+      }
-+
-+      *q = 0;
-+
-+      return buf;
-+}
-+
-+/*
-+ * gg_get_line() // funkcja wewnêtrzna
-+ *
-+ * podaje kolejn± liniê z bufora tekstowego. psuje co bezpowrotnie, dziel±c
-+ * na kolejne stringi. zdarza siê, nie ma potrzeby pisania funkcji dubluj±cej
-+ * bufor ¿eby tylko mieæ nieruszone dane wej¶ciowe, skoro i tak nie bêd± nam
-+ * po¼niej potrzebne. obcina `\r\n'.
-+ *
-+ *  - ptr - wska¼nik do zmiennej, która przechowuje aktualn± pozycjê
-+ *    w przemiatanym buforze.
-+ *
-+ * wska¼nik do kolejnej linii tekstu lub NULL, je¶li to ju¿ koniec bufora.
-+ */
-+static char *gg_get_line(char **ptr)
-+{
-+        char *foo, *res;
-+
-+        if (!ptr || !*ptr || !strcmp(*ptr, ""))
-+                return NULL;
-+
-+        res = *ptr;
-+
-+        if (!(foo = strchr(*ptr, '\n')))
-+                *ptr += strlen(*ptr);
-+        else {
-+                *ptr = foo + 1;
-+                *foo = 0;
-+              if (res[strlen(res) - 1] == '\r')
-+                      res[strlen(res) - 1] = 0;
-+        }
-+
-+        return res;
-+}
-+
-+
-+/*
-+ * gg_search()
-+ *
-+ * rozpoczyna szukanie u¿ytkowników. informacje o tym, czego dok³adnie szukamy
-+ * s± zawarte w strukturze `gg_search_request'. ze wzglêdu na specyfikê ich
-+ * przeszukiwarki, niektórych pól nie mo¿na mieszaæ. s± oznaczone w libgg.h
-+ * jako osobne mode'y.
-+ *
-+ *  - r - informacja o tym, czego szukamy,
-+ *  - async - ma byæ asynchronicznie?
-+ *
-+ * zwraca zaalokowan± strukturê `gg_search', któr± po¼niej nale¿y zwolniæ
-+ * funkcj± gg_free_search(), albo NULL je¶li wyst±pi³ b³±d.
-+ */
-+struct gg_search *gg_search(struct gg_search_request *r, int async)
-+{
-+      struct gg_search *f;
-+      int mode = -1;
-+
-+      if (!r) {
-+              errno = EFAULT;
-+              return NULL;
-+      }
-+
-+      if (r->nickname || r->first_name || r->last_name || r->city || r->gender || r->min_birth || r->max_birth)
-+              mode = 0;
-+
-+      if (r->email) {
-+              if (mode != -1) {
-+                      errno = EINVAL;
-+                      return NULL;
-+              }
-+              mode = 1;
-+      }
-+
-+      if (r->phone) {
-+              if (mode != -1) {
-+                      errno = EINVAL;
-+                      return NULL;
-+              }
-+              mode = 2;
-+      }
-+
-+      if (r->uin) {
-+              if (mode != -1) {
-+                      errno = EINVAL;
-+                      return NULL;
-+              }
-+              mode = 3;
-+      }
-+
-+      if (mode == -1) {
-+              errno = EINVAL;
-+              return NULL;
-+      }
-+
-+      if (!(f = malloc(sizeof(*f))))
-+              return NULL;
-+
-+      memset(f, 0, sizeof(*f));
-+
-+      if (r->first_name)
-+              f->request.first_name = strdup(r->first_name);
-+      if (r->last_name)
-+              f->request.last_name = strdup(r->last_name);
-+      if (r->nickname)
-+              f->request.nickname = strdup(r->nickname);
-+      if (r->city)
-+              f->request.city = strdup(r->city);
-+      if (r->email)
-+              f->request.email = strdup(r->email);
-+      if (r->phone)
-+              f->request.phone = strdup(r->phone);
-+      f->request.active = r->active;
-+      f->request.gender = r->gender;
-+      if (f->request.gender == GG_GENDER_NONE)
-+              f->request.gender = -1;
-+      f->request.min_birth = r->min_birth;
-+      f->request.max_birth = r->max_birth;
-+      f->request.uin = r->uin;
-+
-+      f->async = async;
-+      f->mode = mode;
-+
-+      if (async) {
-+              if (gg_resolve(&f->fd, &f->pid, GG_PUBDIR_HOST)) {
-+                      gg_free_search(f);
-+                      return NULL;
-+              }
-+
-+              f->state = GG_STATE_RESOLVING;
-+              f->check = GG_CHECK_READ;
-+      } else {
-+              struct hostent *he;
-+              struct in_addr a;
-+
-+              if (!(he = gethostbyname(GG_PUBDIR_HOST))) {
-+                      gg_free_search(f);
-+                      return NULL;
-+              } else
-+                      memcpy((char*) &a, he->h_addr, sizeof(a));
-+
-+              if (!(f->fd = gg_connect(&a, GG_PUBDIR_PORT, 0)) == -1) {
-+                      gg_free_search(f);
-+                      return NULL;
-+              }
-+
-+              f->state = GG_STATE_CONNECTING_HTTP;
-+
-+              while (f->state != GG_STATE_IDLE && f->state != GG_STATE_FINISHED) {
-+                      if (gg_search_watch_fd(f) == -1)
-+                              break;
-+              }
-+
-+              if (f->state != GG_STATE_FINISHED) {
-+                      gg_free_search(f);
-+                      return NULL;
-+              }
-+      }
-+
-+      return f;
-+}
-+
-+#define GET_LOST(x) \
-+      close(f->fd); \
-+      f->state = GG_STATE_IDLE; \
-+      f->error = x; \
-+      f->fd = 0; \
-+      return -1;
-+
-+/*
-+ * gg_search_watch_fd()
-+ *
-+ * przy asynchronicznym szukaniu userów wypada³oby wywo³aæ t± funkcjê przy
-+ * jaki¶ zmianach na gg_search->fd.
-+ *
-+ *  - f - to co¶, co zwróci³o gg_search()
-+ *
-+ * je¶li wszystko posz³o dobrze to 0, inaczej -1. przeszukiwanie bêdzie
-+ * zakoñczone, je¶li f->state == GG_STATE_FINISHED. je¶li wyst±pi jaki¶
-+ * b³±d, to bêdzie tam GG_STATE_IDLE i odpowiedni kod b³êdu w f->error.
-+ */
-+int gg_search_watch_fd(struct gg_search *f)
-+{
-+      if (!f) {
-+              errno = EINVAL;
-+              return -1;
-+      }
-+
-+      if (f->state == GG_STATE_RESOLVING) {
-+              struct in_addr a;
-+
-+              gg_debug(GG_DEBUG_MISC, "=> resolved\n");
-+
-+              if (read(f->fd, &a, sizeof(a)) < sizeof(a) || a.s_addr == INADDR_NONE) {
-+                      gg_debug(GG_DEBUG_MISC, "=> resolver thread failed\n");
-+                      GET_LOST(GG_FAILURE_RESOLVING);
-+              }
-+
-+              close(f->fd);
-+
-+              waitpid(f->pid, NULL, 0);
-+
-+              gg_debug(GG_DEBUG_MISC, "=> connecting\n");
-+
-+              if ((f->fd = gg_connect(&a, GG_PUBDIR_PORT, f->async)) == -1) {
-+                      gg_debug(GG_DEBUG_MISC, "=> connection failed\n");
-+                      GET_LOST(GG_FAILURE_CONNECTING);
-+              }
-+
-+              f->state = GG_STATE_CONNECTING_HTTP;
-+              f->check = GG_CHECK_WRITE;
-+
-+              return 0;
-+      }
-+
-+      if (f->state == GG_STATE_CONNECTING_HTTP) {
-+              int res, res_size = sizeof(res);
-+              char *form, *query;
-+
-+              if (f->async && (getsockopt(f->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
-+                      gg_debug(GG_DEBUG_MISC, "=> async connection failed\n");
-+                      GET_LOST(GG_FAILURE_CONNECTING);
-+              }
-+
-+              if (f->mode == 0) {
-+                      char *__first_name, *__last_name, *__nickname, *__city;
-+
-+                      __first_name = gg_urlencode((f->request.first_name) ? f->request.first_name : "");
-+                      __last_name = gg_urlencode((f->request.last_name) ? f->request.last_name : "");
-+                      __nickname = gg_urlencode((f->request.nickname) ? f->request.nickname : "");
-+                      __city = gg_urlencode((f->request.city) ? f->request.city : "");
-+
-+                      if (!__first_name || !__last_name || !__nickname || !__city) {
-+                              free(__first_name);
-+                              free(__last_name);
-+                              free(__nickname);
-+                              free(__city);
-+                              gg_debug(GG_DEBUG_MISC, "=> not enough memory for form fields\n");
-+                              GET_LOST(GG_FAILURE_WRITING);
-+                      }
-+
-+                      form = gg_alloc_sprintf("Mode=0&FirstName=%s&LastName=%s&Gender=%d&NickName=%s&City=%s&MinBirth=%d&MaxBirth=%d%s", __first_name, __last_name, f->request.gender, __nickname, __city, f->request.min_birth, f->request.max_birth, (f->request.active) ? "&ActiveOnly=" : "");
-+
-+                      free(__first_name);
-+                      free(__last_name);
-+                      free(__nickname);
-+                      free(__city);
-+
-+              } else if (f->mode == 1) {
-+                      char *__email = gg_urlencode((f->request.email) ? f->request.email : "");
-+
-+                      if (!__email) {
-+                              gg_debug(GG_DEBUG_MISC, "=> not enough memory for form fields\n");
-+                              GET_LOST(GG_FAILURE_WRITING);
-+                      }
-+
-+                      form = gg_alloc_sprintf("Mode=1&Email=%s%s", __email, (f->request.active) ? "&ActiveOnly=" : "");
-+
-+                      free(__email);
-+
-+              } else if (f->mode == 2) {
-+                      char *__phone = gg_urlencode((f->request.phone) ? f->request.phone : "");
-+
-+                      if (!__phone) {
-+                              gg_debug(GG_DEBUG_MISC, "=> not enough memory for form fields\n");
-+                              GET_LOST(GG_FAILURE_WRITING);
-+                      }
-+
-+                      form = gg_alloc_sprintf("Mode=2&MobilePhone=%s%s", __phone, (f->request.active) ? "&ActiveOnly=" : "");
-+
-+                      free(__phone);
-+
-+              } else
-+                      form = gg_alloc_sprintf("Mode=3&UserId=%u%s", f->request.uin, (f->request.active) ? "&ActiveOnly=" : "");
-+
-+              if (!form) {
-+                      gg_debug(GG_DEBUG_MISC, "=> not enough memory for form query\n");
-+                      GET_LOST(GG_FAILURE_WRITING);
-+              }
-+
-+              gg_debug(GG_DEBUG_MISC, "=> %s\n", form);
-+
-+              query = gg_alloc_sprintf(
-+                      "POST /appsvc/fmpubquery2.asp HTTP/1.0\r\n"
-+                      "Host: " GG_PUBDIR_HOST "\r\n"
-+                      "Content-Type: application/x-www-form-urlencoded\r\n"
-+                      "User-Agent: Mozilla/4.7 [en] (Win98; I)\r\n"
-+                      "Content-Length: %d\r\n"
-+                      "Pragma: no-cache\r\n"
-+                      "\r\n"
-+                      "%s",
-+                      strlen(form), form);
-+
-+              free(form);
-+
-+              if (!query) {
-+                      gg_debug(GG_DEBUG_MISC, "=> not enough memory for query string\n");
-+                      GET_LOST(GG_FAILURE_WRITING);
-+              }
-+
-+              if ((res = write(f->fd, query, strlen(query))) < strlen(query)) {
-+                      gg_debug(GG_DEBUG_MISC, "=> http request failed (len=%d, res=%d, errno=%d)\n", strlen(query), res, errno);
-+                      free(query);
-+                      GET_LOST(GG_FAILURE_WRITING);
-+              }
-+
-+              free(query);
-+
-+              gg_debug(GG_DEBUG_MISC, "=> http request sent (len=%d)\n", strlen(query));
-+
-+              f->state = GG_STATE_READING_HEADER;
-+              f->check = GG_CHECK_READ;
-+
-+              return 0;
-+      
-+      }
-+
-+      if (f->state == GG_STATE_READING_HEADER) {
-+              char buf[1024], *tmp;
-+              int res;
-+
-+              if ((res = read(f->fd, buf, sizeof(buf))) == -1) {
-+                      gg_debug(GG_DEBUG_MISC, "=> reading http header failed (errno=%d)\n", errno);
-+                      if (f->header_buf) {
-+                              free(f->header_buf);
-+                              f->header_buf = NULL;
-+                      }
-+                      GET_LOST(GG_FAILURE_READING);
-+              }
-+
-+              gg_debug(GG_DEBUG_MISC, "=> read %d bytes\n", res);
-+
-+#if 0
-+              if (!f->header_buf) {
-+                      if (!(f->header_buf = malloc(res + 1))) {
-+                              gg_debug(GG_DEBUG_MISC, "=> not enough memory for header\n");
-+                              GET_LOST(GG_FAILURE_READING);
-+                      }
-+                      memcpy(f->header_buf, buf, res);
-+                      f->header_size = res;
-+              } else {
-+                      if (!(f->header_buf = realloc(f->header_buf, f->header_size + res + 1))) {
-+                              gg_debug(GG_DEBUG_MISC, "=> not enough memory for header\n");
-+                              GET_LOST(GG_FAILURE_READING);
-+                      }
-+                      memcpy(f->header_buf + f->header_size, buf, res);
-+                      f->header_size += res;
-+              }
-+#endif
-+
-+              if (!(f->header_buf = realloc(f->header_buf, f->header_size + res + 1))) {
-+                      gg_debug(GG_DEBUG_MISC, "=> not enough memory for header\n");
-+                      GET_LOST(GG_FAILURE_READING);
-+              }
-+              memcpy(f->header_buf + f->header_size, buf, res);
-+              f->header_size += res;
-+
-+              gg_debug(GG_DEBUG_MISC, "=> header_buf=%p, header_size=%d\n", f->header_buf, f->header_size);
-+
-+              f->header_buf[f->header_size] = 0;
-+
-+              if ((tmp = strstr(f->header_buf, "\r\n\r\n")) || (tmp = strstr(f->header_buf, "\n\n"))) {
-+                      int sep_len = (*tmp == '\r') ? 4 : 2, left;
-+                      char *line;
-+
-+                      left = f->header_size - ((int)(tmp) - (int)(f->header_buf) + sep_len);
-+
-+                      gg_debug(GG_DEBUG_MISC, "=> got all header (%d bytes, %d left)\n", f->header_size - left, left);
-+
-+                      /* HTTP/1.1 200 OK */
-+                      if (strlen(f->header_buf) < 16 || strncmp(f->header_buf + 9, "200", 3)) {
-+                              gg_debug(GG_DEBUG_MISC, "=> didn't get 200 OK -- no results\n");
-+                              free(f->header_buf);
-+                              f->header_buf = NULL;
-+                              close(f->fd);
-+                              f->state = GG_STATE_FINISHED;
-+                              f->fd = 0;
-+                              f->count = 0;
-+                              f->results = NULL;
-+
-+                              return 0;
-+                      }
-+
-+                      f->data_size = 0;
-+                      line = f->header_buf;
-+                      *tmp = 0;
-+
-+                      while (line) {
-+                              if (!strncasecmp(line, "Content-length: ", 16)) {
-+                                      f->data_size = atoi(line + 16);
-+                              }
-+                              line = strchr(line, '\n');
-+                              if (line)
-+                                      line++;
-+                      }
-+
-+                      if (!f->data_size) {
-+                              gg_debug(GG_DEBUG_MISC, "=> content-length not found\n");
-+                              free(f->header_buf);
-+                              f->header_buf = NULL;
-+                              GET_LOST(GG_FAILURE_READING);
-+                      }
-+
-+                      gg_debug(GG_DEBUG_MISC, "=> data_size=%d\n", f->data_size);
-+
-+                      if (!(f->data_buf = malloc(f->data_size + 1))) {
-+                              gg_debug(GG_DEBUG_MISC, "=> not enough memory (%d bytes for data_buf)\n", f->data_size + 1);
-+                              free(f->header_buf);
-+                              f->header_buf = NULL;
-+                              GET_LOST(GG_FAILURE_READING);
-+                      }
-+
-+                      if (left) {
-+                              if (left > f->data_size) {
-+                                      gg_debug(GG_DEBUG_MISC, "=> too much data (%d bytes left, %d needed)\n", left, f->data_size);
-+                                      free(f->header_buf);
-+                                      free(f->data_buf);
-+                                      f->header_buf = NULL;
-+                                      f->data_buf = NULL;
-+                                      GET_LOST(GG_FAILURE_READING);
-+                              }
-+
-+                              memcpy(f->data_buf, tmp + sep_len, left);
-+                              f->data_buf[left] = 0;
-+                      }
-+
-+                      free(f->header_buf);
-+                      f->header_buf = NULL;
-+                      f->header_size = 0;
-+
-+                      if (left && left == f->data_size) {
-+                              gg_debug(GG_DEBUG_MISC, "=> wow, we already have all data\n");
-+                              f->state = GG_STATE_PARSING;
-+                      } else {
-+                              f->state = GG_STATE_READING_DATA;
-+                              f->check = GG_CHECK_READ;
-+                              return 0;
-+                      }
-+              } else
-+                      return 0;
-+      }
-+
-+      if (f->state == GG_STATE_READING_DATA) {
-+              char buf[1024];
-+              int res;
-+
-+              if ((res = read(f->fd, buf, sizeof(buf))) == -1) {
-+                      gg_debug(GG_DEBUG_MISC, "=> reading http data failed (errno=%d)\n", errno);
-+                      if (f->data_buf) {
-+                              free(f->data_buf);
-+                              f->data_buf = NULL;
-+                      }
-+                      GET_LOST(GG_FAILURE_READING);
-+              }
-+
-+              gg_debug(GG_DEBUG_MISC, "=> read %d bytes of data\n", res);
-+
-+              if (strlen(f->data_buf) + res > f->data_size) {
-+                      gg_debug(GG_DEBUG_MISC, "=> too much data (%d bytes, %d needed), truncating\n", strlen(f->data_buf) + res, f->data_size);
-+                      res = f->data_size - strlen(f->data_buf);
-+              }
-+
-+              memcpy(f->data_buf + strlen(f->data_buf), buf, res);
-+
-+              gg_debug(GG_DEBUG_MISC, "=> strlen(data_buf)=%d, data_size=%d\n", strlen(f->data_buf), f->data_size);
-+
-+              if (strlen(f->data_buf) >= f->data_size) {
-+                      gg_debug(GG_DEBUG_MISC, "=> okay, we've got all the data, closing socket\n");
-+                      f->state = GG_STATE_PARSING;
-+                      close(f->fd);
-+                      f->fd = 0;
-+              } else
-+                      return 0;
-+      }
-+
-+      if (f->state == GG_STATE_PARSING) {
-+              char *foo = f->data_buf;
-+
-+              gg_debug(GG_DEBUG_MISC, "=> ladies and gentlemen, parsing begins\n");
-+              f->count = 0;
-+              f->results = NULL;
-+              f->state = GG_STATE_FINISHED;
-+
-+              if (!gg_get_line(&foo))
-+                      return 0;
-+              
-+              while (1) {
-+                      char *tmp[8];
-+                      int i;
-+
-+                      for (i = 0; i < 8; i++) {
-+                              if (!(tmp[i] = gg_get_line(&foo))) {
-+                                      free(f->data_buf);
-+                                      f->data_buf = NULL;
-+                                      return 0;
-+                              }
-+                              gg_debug(GG_DEBUG_MISC, "=> [%s]\n", tmp[i]);
-+                      }
-+
-+                      if (!(f->results = realloc(f->results, (f->count + 1) * sizeof(struct gg_search_result)))) {
-+                              gg_debug(GG_DEBUG_MISC, "=> not enough memory for results (non critical)\n");
-+                              free(f->data_buf);
-+                              f->data_buf = NULL;
-+                              return 0;
-+                      }
-+
-+                      f->results[f->count].active = (atoi(tmp[0]) == 2);
-+                      f->results[f->count].uin = (strtol(tmp[1], NULL, 0));
-+                      f->results[f->count].first_name = strdup(tmp[2]);
-+                      f->results[f->count].last_name = strdup(tmp[3]);
-+                      f->results[f->count].nickname = strdup(tmp[4]);
-+                      f->results[f->count].born = atoi(tmp[5]);
-+                      f->results[f->count].gender = atoi(tmp[6]);
-+                      f->results[f->count].city = strdup(tmp[7]);
-+
-+                      f->count++;
-+              }
-+
-+              free(f->data_buf);
-+              f->data_buf = NULL;
-+
-+              f->state = GG_STATE_FINISHED;
-+
-+              return 0;
-+      }
-+
-+      if (f->fd)
-+              close(f->fd);
-+
-+      f->state = GG_STATE_IDLE;
-+      f->error = 0;
-+
-+      return -1;
-+}
-+
-+#undef GET_LOST
-+
-+/*
-+ * gg_search_cancel()
-+ *
-+ * je¶li szukanie jest w trakcie, przerywa.
-+ *
-+ *  - f - to co¶, co zwróci³o gg_search().
-+ *
-+ * UWAGA! funkcja potencjalnie niebezpieczna, bo mo¿e pozwalniaæ bufory
-+ * i pozamykaæ sockety, kiedy co¶ siê dzieje. ale to ju¿ nie mój problem ;)
-+ */
-+void gg_search_cancel(struct gg_search *f)
-+{
-+      if (!f)
-+              return;
-+
-+      if (f->state == GG_STATE_IDLE || f->state == GG_STATE_FINISHED)
-+              return;
-+
-+      if (f->fd)
-+              close(f->fd);
-+
-+      if (f->header_buf)
-+              free(f->header_buf);
-+      if (f->data_buf)
-+              free(f->data_buf);      
-+}
-+
-+/*
-+ * gg_free_search()
-+ *
-+ * zwalnia pamiêæ po efektach szukania userów.
-+ *
-+ *  - f - to co¶, co nie jest ju¿ nam potrzebne.
-+ *
-+ * nie zwraca niczego. najwy¿ej segfaultnie ;)
-+ */
-+void gg_free_search(struct gg_search *f)
-+{
-+      int i;
-+
-+      if (!f)
-+              return;
-+
-+      for (i = 0; i < f->count; i++) {
-+              free(f->results[i].first_name);
-+              free(f->results[i].last_name);
-+              free(f->results[i].nickname);
-+              free(f->results[i].city);
-+      }
-+
-+      free(f->results);
-+      free(f->request.first_name);
-+      free(f->request.last_name);
-+      free(f->request.nickname);
-+      free(f->request.city);
-+      free(f->request.email);
-+      free(f->request.phone);
-+      free(f);
-+}
-+
This page took 0.15148 seconds and 4 git commands to generate.