changeset 2846:4b3f17ca66bf

[gaim-migrate @ 2859] so here it comes - some bugs fixed, new ones introduced: - password changing (was in part 1) - update to latest libgg (fixes password change on alpha) - auto away on idle (remembers GG_STATE_FRIENDS_MASK) - handle_errcode() can now use hide_login_progress() - remove encode_postdata() and use gg_urlencode() from libgg + encode only fields (not whole url) - fixed status related ugly bug in GG_EVENT_NOTIFY (!!!) - remove linefeed from messages Thanks, Arkadiusz Miskiewicz committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Wed, 05 Dec 2001 09:48:56 +0000
parents 0c10058610a0
children e49bd1479edd
files src/protocols/gg/.cvsignore src/protocols/gg/Makefile.am src/protocols/gg/common.c src/protocols/gg/gg.c src/protocols/gg/libgg.c src/protocols/gg/libgg.h
diffstat 6 files changed, 1037 insertions(+), 665 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/gg/.cvsignore	Tue Dec 04 19:51:27 2001 +0000
+++ b/src/protocols/gg/.cvsignore	Wed Dec 05 09:48:56 2001 +0000
@@ -6,3 +6,4 @@
 libgg.la
 libgg.lo
 iconv_string.lo
+common.lo
--- a/src/protocols/gg/Makefile.am	Tue Dec 04 19:51:27 2001 +0000
+++ b/src/protocols/gg/Makefile.am	Wed Dec 05 09:48:56 2001 +0000
@@ -13,6 +13,7 @@
 
 libgg_a_SOURCES = libgg.c \
 		  libgg.h \
+		  common.c \
 		  iconv_string.c \
 		  iconv_string.h \
 		  gg.c
@@ -25,6 +26,7 @@
 
 libgg_la_SOURCES = libgg.c \
 		   libgg.h \
+		   common.c \
 		   iconv_string.c \
 		   iconv_string.h \
 		   gg.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/protocols/gg/common.c	Wed Dec 05 09:48:56 2001 +0000
@@ -0,0 +1,330 @@
+/* $Id: common.c 2859 2001-12-05 09:48:56Z warmenhoven $ */
+
+/*
+ *  (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>,
+ *                     Robert J. Woźny <speedy@ziew.org>
+ *
+ *  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 <sys/time.h>
+#include <netdb.h>
+#include <errno.h>
+#ifndef _AIX
+#  include <string.h>
+#endif
+#include <stdarg.h>
+#include <pwd.h>
+#include <time.h>
+#ifdef sun
+  #include <sys/filio.h>
+#endif
+#include "libgg.h"
+#include "config.h"
+
+/*
+ * gg_debug()
+ *
+ * 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(int level, char *format, ...)
+{
+	va_list ap;
+	
+	if ((gg_debug_level & level)) {
+		va_start(ap, format);
+		vprintf(format, ap);
+		va_end(ap);
+	}
+}
+
+/*
+ * gg_alloc_sprintf()
+ *
+ * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcześniej
+ * miejsce na dane. powinno działać na tych maszynach, które mają funkcję
+ * vsnprintf() zgodną z C99, jak i na wcześniejszych.
+ *
+ *  - 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, *tmp;
+        int size = 0, res;
+
+        va_start(ap, format);
+
+        if ((size = vsnprintf(buf, 0, format, ap)) < 1) {
+                size = 128;
+                do {
+                        size *= 2;
+                        if (!(tmp = realloc(buf, size))) {
+                                free(buf);
+                                return NULL;
+                        }
+                        buf = tmp;
+                        res = vsnprintf(buf, size, format, ap);
+                } while (res == size - 1);
+        } else {
+                if (!(buf = malloc(size + 1)))
+                        return NULL;
+        }
+
+        vsnprintf(buf, size + 1, format, ap);
+
+        va_end(ap);
+
+        return buf;
+}
+
+/*
+ * gg_get_line()
+ * 
+ * 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.
+ */
+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_connect()
+ *
+ * łą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) {
+		if (errno && (!async || errno != EINPROGRESS)) {
+			gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno));
+			return -1;
+		}
+		gg_debug(GG_DEBUG_MISC, "-- connect() in progress\n");
+	}
+	
+	return sock;
+}
+
+/*
+ * gg_read_line()
+ *
+ * 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.
+ */
+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_chomp()
+ *
+ * ucina "\r\n" lub "\n" z końca linii.
+ *
+ *  - line - ofiara operacji plastycznej.
+ *
+ * niczego nie zwraca.
+ */
+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_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.
+ */
+char *gg_urlencode(char *str)
+{
+	char *p, *q, *buf, hex[] = "0123456789abcdef";
+	int size = 0;
+
+	if (!str)
+		str = strdup("");
+
+	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_http_hash()
+ *
+ * funkcja, która liczy hash dla adresu e-mail i hasła.
+ *
+ *  - email - adres email,
+ *  - password - hasło.
+ *
+ * zwraca hash wykorzystywany przy rejestracji i wszelkich
+ * manipulacjach własnego wpisu w katalogu publicznym.
+ */
+
+int gg_http_hash(unsigned char *email, unsigned char *password)
+{
+	unsigned int a, c;
+	int b, i;
+	b = (-1);
+
+	i = 0;
+	while ((c = (int) email[i++]) != 0) {
+		a = (c ^ b) + (c << 8);
+		b = (a >> 24) | (a << 8);
+	}
+
+	i = 0;
+	while ((c = (int) password[i++]) != 0) {
+		a = (c ^ b) + (c << 8);
+		b = (a >> 24) | (a << 8);
+	}
+
+	return (b < 0 ? -b : b);
+}
+
+/*
+ * Local variables:
+ * c-indentation-style: k&r
+ * c-basic-offset: 8
+ * indent-tabs-mode: notnil
+ * End:
+ *
+ * vim: shiftwidth=8:
+ */
--- a/src/protocols/gg/gg.c	Tue Dec 04 19:51:27 2001 +0000
+++ b/src/protocols/gg/gg.c	Wed Dec 05 09:48:56 2001 +0000
@@ -1,6 +1,6 @@
 /*
  * gaim - Gadu-Gadu Protocol Plugin
- * $Id: gg.c 2848 2001-12-02 20:42:30Z warmenhoven $
+ * $Id: gg.c 2859 2001-12-05 09:48:56Z warmenhoven $
  *
  * Copyright (C) 2001 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
  * 
@@ -65,6 +65,7 @@
 #define AGG_PUBDIR_USERLIST_EXPORT_FORM "/appsvc/fmcontactsput.asp"
 #define AGG_PUBDIR_USERLIST_IMPORT_FORM "/appsvc/fmcontactsget.asp"
 #define AGG_PUBDIR_SEARCH_FORM "/appsvc/fmpubquery2.asp"
+#define AGG_REGISTER_DATA_FORM "/appsvc/fmregister.asp"
 #define AGG_PUBDIR_MAX_ENTRIES 200
 
 #define AGG_STATUS_AVAIL              _("Available")
@@ -80,11 +81,13 @@
 #define AGG_HTTP_USERLIST_IMPORT	2
 #define AGG_HTTP_USERLIST_EXPORT	3
 #define AGG_HTTP_USERLIST_DELETE	4
+#define AGG_HTTP_PASSWORD_CHANGE	5
 
 #define UC_NORMAL 2
 
 struct agg_data {
 	struct gg_session *sess;
+	int own_status;
 };
 
 struct agg_http {
@@ -170,7 +173,7 @@
 	return gg_localenc;
 }
 
-static char *handle_errcode(int errcode, gboolean show)
+static char *handle_errcode(struct gaim_connection *gc, int errcode)
 {
 	static char msg[AGG_BUF_LEN];
 
@@ -198,73 +201,51 @@
 		break;
 	}
 
-	if (show)
-		do_error_dialog(msg, _("Gadu-Gadu Error"));
+	hide_login_progress(gc, msg);
 
 	return msg;
 }
 
-static gchar *encode_postdata(const gchar *data)
-{
-	gchar *p = NULL;
-	int i, j = 0;
-	for (i = 0; i < strlen(data); i++) {
-		/* locale insensitive, doesn't reflect RFC (1738 section 2.2, 1866 section 8.2.1) */
-		if ((data[i] >= 'a' && data[i] <= 'z')
-		    || (data[i] >= 'A' && data[i] <= 'Z')
-		    || (data[i] >= '0' && data[i] <= '9')
-		    || data[i] == '=' || data[i] == '&') {
-			p = g_realloc(p, j + 1);
-			p[j] = data[i];
-			j++;
-		} else {
-			p = g_realloc(p, j + 4);	/* remember, sprintf appends a '\0' */
-			sprintf(p + j, "%%%02x", (unsigned char)data[i]);
-			j += 3;
-		}
-	}
-	p = g_realloc(p, j + 1);
-	p[j] = '\0';
-
-	if (p && strlen(p))
-		return p;
-	else
-		return g_strdup(data);
-}
-
 static void agg_set_away(struct gaim_connection *gc, char *state, char *msg)
 {
 	struct agg_data *gd = (struct agg_data *)gc->proto_data;
+	int status = gd->own_status;
 
 	if (gc->away)
 		gc->away = NULL;
 
 	if (!g_strcasecmp(state, AGG_STATUS_AVAIL))
-		gg_change_status(gd->sess, GG_STATUS_AVAIL);
+		status = GG_STATUS_AVAIL;
 	else if (!g_strcasecmp(state, AGG_STATUS_AVAIL_FRIENDS))
-		gg_change_status(gd->sess, GG_STATUS_AVAIL | GG_STATUS_FRIENDS_MASK);
+		status = GG_STATUS_AVAIL | GG_STATUS_FRIENDS_MASK;
 	else if (!g_strcasecmp(state, AGG_STATUS_BUSY)) {
-		gg_change_status(gd->sess, GG_STATUS_BUSY);
+		status = GG_STATUS_BUSY;
 		gc->away = "";
 	} else if (!g_strcasecmp(state, AGG_STATUS_BUSY_FRIENDS)) {
-		gg_change_status(gd->sess, GG_STATUS_BUSY | GG_STATUS_FRIENDS_MASK);
+		status =  GG_STATUS_BUSY | GG_STATUS_FRIENDS_MASK;
 		gc->away = "";
 	} else if (!g_strcasecmp(state, AGG_STATUS_INVISIBLE)) {
-		gg_change_status(gd->sess, GG_STATUS_INVISIBLE);
+		status = GG_STATUS_INVISIBLE;
 		gc->away = "";
 	} else if (!g_strcasecmp(state, AGG_STATUS_INVISIBLE_FRIENDS)) {
-		gg_change_status(gd->sess, GG_STATUS_INVISIBLE | GG_STATUS_FRIENDS_MASK);
+		status = GG_STATUS_INVISIBLE | GG_STATUS_FRIENDS_MASK;
 		gc->away = "";
 	} else if (!g_strcasecmp(state, AGG_STATUS_NOT_AVAIL)) {
-		gg_change_status(gd->sess, GG_STATUS_NOT_AVAIL);
+		status = GG_STATUS_NOT_AVAIL;
 		gc->away = "";
 	} else if (!g_strcasecmp(state, GAIM_AWAY_CUSTOM)) {
 		if (msg) {
-			gg_change_status(gd->sess, GG_STATUS_BUSY);
+			status = GG_STATUS_BUSY;
 			gc->away = "";
 		} else
-			gg_change_status(gd->sess, GG_STATUS_AVAIL);
+			status = GG_STATUS_AVAIL;
+
+		if (gd->own_status & GG_STATUS_FRIENDS_MASK)
+			status |= GG_STATUS_FRIENDS_MASK;
 	}
+
+	gd->own_status = status;
+	gg_change_status(gd->sess, status);
 }
 
 static gchar *get_away_text(int uc)
@@ -359,6 +340,7 @@
 
 	if (!(e = gg_watch_fd(gd->sess))) {
 		debug_printf("main_callback: gg_watch_fd failed - CRITICAL!\n");
+		hide_login_progress(gc, _("Unable to read socket"));
 		signoff(gc);
 		return;
 	}
@@ -373,7 +355,7 @@
 	case GG_EVENT_CONN_FAILED:
 		if (gc->inpa)
 			gaim_input_remove(gc->inpa);
-		handle_errcode(e->event.failure, TRUE);
+		handle_errcode(gc, e->event.failure);
 		signoff(gc);
 		break;
 	case GG_EVENT_MSG:
@@ -385,6 +367,7 @@
 			if (!allowed_uin(gc, user))
 				break;
 			imsg = charset_convert(e->event.msg.message, "CP1250", find_local_charset());
+			strip_linefeed(imsg);
 			/* e->event.msg.time - we don't know what this time is for */
 			serv_got_im(gc, user, imsg, 0, time((time_t) NULL));
 			g_free(imsg);
@@ -404,8 +387,7 @@
 				case GG_STATUS_AVAIL:
 				case GG_STATUS_BUSY:
 				case GG_STATUS_INVISIBLE:
-				case GG_STATUS_FRIENDS_MASK:
-					status = UC_NORMAL | (e->event.status.status << 5);
+					status = UC_NORMAL | (n->status << 5);
 					break;
 				default:
 					status = UC_NORMAL;
@@ -431,7 +413,6 @@
 			case GG_STATUS_AVAIL:
 			case GG_STATUS_BUSY:
 			case GG_STATUS_INVISIBLE:
-			case GG_STATUS_FRIENDS_MASK:
 				status = UC_NORMAL | (e->event.status.status << 5);
 				break;
 			default:
@@ -440,8 +421,8 @@
 			}
 
 			g_snprintf(user, sizeof(user), "%lu", e->event.status.uin);
-			serv_got_update(gc, user, (status == UC_UNAVAILABLE) ? 0 : 1, 0, 0, 0, status,
-					0);
+			serv_got_update(gc, user, (status == UC_UNAVAILABLE) ? 0 : 1, 0, 0, 0,
+					status, 0);
 		}
 		break;
 	case GG_EVENT_ACK:
@@ -479,18 +460,17 @@
 		gc->inpa = gaim_input_add(gd->sess->fd, GAIM_INPUT_READ, login_callback, gc);
 
 	switch (gd->sess->state) {
-	case GG_STATE_CONNECTING_HTTP:
-	case GG_STATE_WRITING_HTTP:
-		set_login_progress(gc, 2, _("Handshake"));
+	case GG_STATE_READING_DATA:
+		set_login_progress(gc, 2, _("Reading data"));
 		break;
 	case GG_STATE_CONNECTING_GG:
-		set_login_progress(gc, 3, _("Connecting to GG server"));
+		set_login_progress(gc, 3, _("Balancer handshake"));
 		break;
-	case GG_STATE_WAITING_FOR_KEY:
-		set_login_progress(gc, 4, _("Waiting for server key"));
+	case GG_STATE_READING_KEY:
+		set_login_progress(gc, 4, _("Reading server key"));
 		break;
-	case GG_STATE_SENDING_KEY:
-		set_login_progress(gc, 5, _("Sending key"));
+	case GG_STATE_READING_REPLY:
+		set_login_progress(gc, 5, _("Exchanging key hash"));
 		break;
 	default:
 		break;
@@ -498,6 +478,7 @@
 
 	if (!(e = gg_watch_fd(gd->sess))) {
 		debug_printf("login_callback: gg_watch_fd failed - CRITICAL!\n");
+		hide_login_progress(gc, _("Critical error in GG library\n"));
 		signoff(gc);
 		return;
 	}
@@ -522,7 +503,7 @@
 	case GG_EVENT_CONN_FAILED:
 		gaim_input_remove(gc->inpa);
 		gc->inpa = 0;
-		handle_errcode(e->event.failure, TRUE);
+		handle_errcode(gc, e->event.failure);
 		signoff(gc);
 		break;
 	default:
@@ -536,6 +517,7 @@
 {
 	struct agg_data *gd = (struct agg_data *)gc->proto_data;
 	if (gg_ping(gd->sess) < 0) {
+		hide_login_progress(gc, _("Unable to ping server"));
 		signoff(gc);
 		return;
 	}
@@ -578,7 +560,7 @@
 
 	gd->sess->uin = (uin_t) strtol(user->username, (char **)NULL, 10);
 	gd->sess->password = g_strdup(user->password);
-	gd->sess->state = GG_STATE_CONNECTING_HTTP;
+	gd->sess->state = GG_STATE_CONNECTING;
 	gd->sess->check = GG_CHECK_WRITE;
 	gd->sess->async = 1;
 	gd->sess->fd = proxy_connect(GG_APPMSG_HOST, GG_APPMSG_PORT, login_callback, gc);
@@ -599,6 +581,7 @@
 	gg_logoff(gd->sess);
 	gg_free_session(gd->sess);
 	g_free(gc->proto_data);
+	gd->own_status = GG_STATUS_NOT_AVAIL;
 }
 
 static int agg_send_im(struct gaim_connection *gc, char *who, char *msg, int flags)
@@ -614,7 +597,8 @@
 
 	if (strlen(msg) > 0) {
 		imsg = charset_convert(msg, find_local_charset(), "CP1250");
-		if (gg_send_message(gd->sess, (flags & IM_FLAG_CHECKBOX) ? GG_CLASS_MSG : GG_CLASS_CHAT,
+		if (gg_send_message(gd->sess, (flags & IM_FLAG_CHECKBOX)
+				    ? GG_CLASS_MSG : GG_CLASS_CHAT,
 				    strtol(who, (char **)NULL, 10), imsg) < 0)
 			return -1;
 		g_free(imsg);
@@ -848,6 +832,18 @@
 	do_error_dialog(_("Couldn't delete Buddies List from Server"), _("Gadu-Gadu Error"));
 }
 
+static void password_change_server_results(struct gaim_connection *gc, gchar *webdata)
+{
+	if (strstr(webdata, "reg_success:")) {
+		do_error_dialog(_("Password changed sucessfully"),
+				_("Gadu-Gadu Information"));
+		return;
+	}
+
+	debug_printf("delete_buddies_server_results: webdata [%s]\n", webdata);
+	do_error_dialog(_("Password couldn't be changed"), _("Gadu-Gadu Error"));
+}
+
 static void http_results(gpointer data, gint source, GaimInputCondition cond)
 {
 	struct agg_http *hdata = data;
@@ -904,6 +900,9 @@
 	case AGG_HTTP_USERLIST_DELETE:
 	        delete_buddies_server_results(gc, webdata);
 		break;
+	case AGG_HTTP_PASSWORD_CHANGE:
+		password_change_server_results(gc, webdata);
+		break;
 	case AGG_HTTP_NONE:
 	default:
 		debug_printf("http_results: unsupported type %d\n", hdata->type);
@@ -920,7 +919,6 @@
 	struct gaim_connection *gc = hdata->gc;
 	gchar *request = hdata->request;
 	gchar *buf;
-	char *ptr;
 
 	debug_printf("http_req_callback: begin\n");
 
@@ -938,10 +936,7 @@
 		return;
 	}
 
-	ptr = encode_postdata(request);
-	g_free(request);
-
-	debug_printf("http_req_callback: http request [%s]\n", ptr);
+	debug_printf("http_req_callback: http request [%s]\n", request);
 
 	buf = g_strdup_printf("POST %s HTTP/1.0\r\n"
 			      "Host: %s\r\n"
@@ -949,9 +944,9 @@
 			      "User-Agent: " GG_HTTP_USERAGENT "\r\n"
 			      "Content-Length: %d\r\n"
 			      "Pragma: no-cache\r\n" "\r\n" "%s\r\n",
-			      hdata->form, hdata->host, strlen(ptr), ptr);
+			      hdata->form, hdata->host, strlen(request), request);
 
-	g_free(ptr);
+	g_free(request);
 
 	if (write(source, buf, strlen(buf)) < strlen(buf)) {
 		g_free(buf);
@@ -970,12 +965,17 @@
 {
 	struct agg_http *hi = g_new0(struct agg_http, 1);
 	static char msg[AGG_BUF_LEN];
+	gchar *u = gg_urlencode(gc->username);
+	gchar *p = gg_urlencode(gc->password);
 
 	hi->gc = gc;
 	hi->type = AGG_HTTP_USERLIST_IMPORT;
 	hi->form = AGG_PUBDIR_USERLIST_IMPORT_FORM;
 	hi->host = GG_PUBDIR_HOST;
-	hi->request = g_strdup_printf("FmNum=%s&Pass=%s", gc->username, gc->password);
+	hi->request = g_strdup_printf("FmNum=%s&Pass=%s", u, p);
+
+	g_free(u);
+	g_free(p);
 
 	if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, hi) < 0) {
 		g_snprintf(msg, sizeof(msg), _("Buddies List import from Server failed (%s)"),
@@ -992,13 +992,19 @@
 	struct agg_http *he = g_new0(struct agg_http, 1);
 	static char msg[AGG_BUF_LEN];
 	gchar *ptr;
+	gchar *u = gg_urlencode(gc->username);
+	gchar *p = gg_urlencode(gc->password);
+
 	GSList *gr = gc->groups;
 
 	he->gc = gc;
 	he->type = AGG_HTTP_USERLIST_EXPORT;
 	he->form = AGG_PUBDIR_USERLIST_EXPORT_FORM;
 	he->host = GG_PUBDIR_HOST;
-	he->request = g_strdup_printf("FmNum=%s&Pass=%s&Contacts=", gc->username, gc->password);
+	he->request = g_strdup_printf("FmNum=%s&Pass=%s&Contacts=", u, p);
+
+	g_free(u);
+	g_free(p);
 
 	while (gr) {
 		struct group *g = gr->data;
@@ -1007,17 +1013,24 @@
 			struct buddy *b = m->data;
 			gchar *newdata;
 			/* GG Number */
-			gchar *name = b->name;
+			gchar *name = gg_urlencode(b->name);
 			/* GG Pseudo */
-			gchar *show = strlen(b->show) ? b->show : b->name;
+			gchar *show = gg_urlencode(strlen(b->show) ? b->show : b->name);
+			/* Group Name */
+			gchar *gname = gg_urlencode(g->name);
 
 			ptr = he->request;
 			newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s\r\n",
-						  show, show, show, show, "", g->name, name);
+						  show, show, show, show, "", gname, name);
 			he->request = g_strconcat(ptr, newdata, NULL);
+
 			g_free(newdata);
 			g_free(ptr);
 
+			g_free(gname);
+			g_free(show);
+			g_free(name);
+
 			m = g_slist_next(m);
 		}
 		gr = g_slist_next(gr);
@@ -1037,12 +1050,14 @@
 {
 	struct agg_http *he = g_new0(struct agg_http, 1);
 	static char msg[AGG_BUF_LEN];
+	gchar *u = gg_urlencode(gc->username);
+	gchar *p = gg_urlencode(gc->password);
 
 	he->gc = gc;
 	he->type = AGG_HTTP_USERLIST_DELETE;
 	he->form = AGG_PUBDIR_USERLIST_EXPORT_FORM;
 	he->host = GG_PUBDIR_HOST;
-	he->request = g_strdup_printf("FmNum=%s&Pass=%s&Delete=1", gc->username, gc->password);
+	he->request = g_strdup_printf("FmNum=%s&Pass=%s&Delete=1", u, p);
 
 	if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, he) < 0) {
 		g_snprintf(msg, sizeof(msg), _("Deletion of Buddies List from Server failed (%s)"),
@@ -1055,7 +1070,8 @@
 }
 
 static void agg_dir_search(struct gaim_connection *gc, char *first, char *middle,
-			   char *last, char *maiden, char *city, char *state, char *country, char *email)
+			   char *last, char *maiden, char *city, char *state,
+			   char *country, char *email)
 {
 	struct agg_http *srch = g_new0(struct agg_http, 1);
 	static char msg[AGG_BUF_LEN];
@@ -1066,25 +1082,36 @@
 	srch->host = GG_PUBDIR_HOST;
 
 	if (email && strlen(email)) {
-		srch->request = g_strdup_printf("Mode=1&Email=%s", email);
+		gchar *eemail = gg_urlencode(email);
+		srch->request = g_strdup_printf("Mode=1&Email=%s", eemail);
+		g_free(eemail);
 	} else {
 		gchar *new_first = charset_convert(first, find_local_charset(), "CP1250");
 		gchar *new_last = charset_convert(last, find_local_charset(), "CP1250");
 		gchar *new_city = charset_convert(city, find_local_charset(), "CP1250");
 
-		/* For active only add &ActiveOnly= */
-		srch->request = g_strdup_printf("Mode=0&FirstName=%s&LastName=%s&Gender=%d"
-						"&NickName=%s&City=%s&MinBirth=%d&MaxBirth=%d",
-						new_first, new_last, AGG_GENDER_NONE,
-						"", new_city, 0, 0);
+		gchar *enew_first = gg_urlencode(new_first);
+		gchar *enew_last = gg_urlencode(new_last);
+		gchar *enew_city = gg_urlencode(new_city);
 
 		g_free(new_first);
 		g_free(new_last);
 		g_free(new_city);
+
+		/* For active only add &ActiveOnly= */
+		srch->request = g_strdup_printf("Mode=0&FirstName=%s&LastName=%s&Gender=%d"
+						"&NickName=%s&City=%s&MinBirth=%d&MaxBirth=%d",
+						enew_first, enew_last, AGG_GENDER_NONE,
+						"", enew_city, 0, 0);
+
+		g_free(enew_first);
+		g_free(enew_last);
+		g_free(enew_city);
 	}
 
 	if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, srch) < 0) {
-		g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"), GG_PUBDIR_HOST);
+		g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"),
+			   GG_PUBDIR_HOST);
 		do_error_dialog(msg, _("Gadu-Gadu Error"));
 		g_free(srch->request);
 		g_free(srch);
@@ -1092,10 +1119,45 @@
 	}
 }
 
+static void agg_change_passwd(struct gaim_connection *gc, char *old, char *new)
+{
+	struct agg_http *hpass = g_new0(struct agg_http, 1);
+	static char msg[AGG_BUF_LEN];
+	gchar *u = gg_urlencode(gc->username);
+	gchar *p = gg_urlencode(gc->password);
+	gchar *enew = gg_urlencode(new);
+	gchar *eold = gg_urlencode(old);
+
+	hpass->gc = gc;
+	hpass->type = AGG_HTTP_PASSWORD_CHANGE;
+	hpass->form = AGG_REGISTER_DATA_FORM;
+	hpass->host = GG_REGISTER_HOST;
+
+	/* We are using old password as place for email - it's ugly */
+	hpass->request = g_strdup_printf("fmnumber=%s&fmpwd=%s&pwd=%s&email=%s&code=%u",
+					 u, p, enew, eold, gg_http_hash(old, new));
+
+	g_free(u);
+	g_free(p);
+	g_free(enew);
+	g_free(eold);
+
+	if (proxy_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, http_req_callback, hpass) < 0) {
+		g_snprintf(msg, sizeof(msg), _("Changing Password failed (%s)"),
+			   GG_REGISTER_HOST);
+		do_error_dialog(msg, _("Gadu-Gadu Error"));
+		g_free(hpass->request);
+		g_free(hpass);
+		return;
+	}                                        
+}
+
 static void agg_do_action(struct gaim_connection *gc, char *action)
 {
 	if (!strcmp(action, _("Directory Search"))) {
 		show_find_info(gc);
+	} else if (!strcmp(action, _("Change Password"))) {
+		show_change_passwd(gc);
 	} else if (!strcmp(action, _("Import Buddies List from Server"))) {
 		import_buddies_server(gc);
 	} else if (!strcmp(action, _("Export Buddies List to Server"))) {
@@ -1110,6 +1172,9 @@
 	GList *m = NULL;
 
 	m = g_list_append(m, _("Directory Search"));
+	m = g_list_append(m, NULL);
+	m = g_list_append(m, _("Change Password"));
+	m = g_list_append(m, NULL);
 	m = g_list_append(m, _("Import Buddies List from Server"));
 	m = g_list_append(m, _("Export Buddies List to Server"));
 	m = g_list_append(m, _("Delete Buddies List from Server"));
@@ -1130,17 +1195,21 @@
 	/* If it's invalid uin then maybe it's nickname? */
 	if (invalid_uin(who)) {
 		gchar *new_who = charset_convert(who, find_local_charset(), "CP1250");
+		gchar *enew_who = gg_urlencode(new_who);
+		
+		g_free(new_who);
 
 		srch->request = g_strdup_printf("Mode=0&FirstName=%s&LastName=%s&Gender=%d"
 						"&NickName=%s&City=%s&MinBirth=%d&MaxBirth=%d",
-						"", "", AGG_GENDER_NONE, new_who, "", 0, 0);
+						"", "", AGG_GENDER_NONE, enew_who, "", 0, 0);
 
-		g_free(new_who);
+		g_free(enew_who);
 	} else
 		srch->request = g_strdup_printf("Mode=3&UserId=%s", who);
 
 	if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, srch) < 0) {
-		g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"), GG_PUBDIR_HOST);
+		g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"),
+			   GG_PUBDIR_HOST);
 		do_error_dialog(msg, _("Gadu-Gadu Error"));
 		g_free(srch->request);
 		g_free(srch);
@@ -1199,7 +1268,7 @@
 	ret->get_dir = agg_get_info;
 	ret->dir_search = agg_dir_search;
 	ret->set_idle = NULL;
-	ret->change_passwd = NULL;
+	ret->change_passwd = agg_change_passwd;
 	ret->add_buddy = agg_add_buddy;
 	ret->add_buddies = agg_add_buddies;
 	ret->remove_buddy = agg_rem_buddy;
@@ -1245,3 +1314,13 @@
 }
 
 #endif
+
+/*
+ * Local variables:
+ * c-indentation-style: k&r
+ * c-basic-offset: 8
+ * indent-tabs-mode: notnil
+ * End:
+ *
+ * vim: shiftwidth=8:
+ */
--- a/src/protocols/gg/libgg.c	Tue Dec 04 19:51:27 2001 +0000
+++ b/src/protocols/gg/libgg.c	Wed Dec 05 09:48:56 2001 +0000
@@ -1,8 +1,8 @@
-/* $Id: libgg.c 2805 2001-11-26 21:22:56Z warmenhoven $ */
+/* $Id: libgg.c 2859 2001-12-05 09:48:56Z warmenhoven $ */
 
 /*
  *  (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>,
- *                     Robert J. Woźny <speedy@atman.pl>
+ *                     Robert J. Woźny <speedy@ziew.org>
  *
  *  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
@@ -37,7 +37,7 @@
 #include <pwd.h>
 #include <time.h>
 #ifdef sun
-#include <sys/filio.h>
+  #include <sys/filio.h>
 #endif
 #include <glib.h>
 #if G_BYTE_ORDER == G_BIG_ENDIAN
@@ -47,37 +47,19 @@
 #include "config.h"
 
 int gg_debug_level = 0;
+int gg_http_use_proxy = 0;
+int gg_http_proxy_port = 0;
+char *gg_http_proxy_host = NULL;
 
-#ifndef lint
+#ifndef lint 
 
 static char rcsid[]
 #ifdef __GNUC__
-    __attribute__ ((unused))
+__attribute__ ((unused))
 #endif
-    = "$Id: libgg.c 2805 2001-11-26 21:22:56Z warmenhoven $";
-
-#endif
+= "$Id: libgg.c 2859 2001-12-05 09:48:56Z warmenhoven $";
 
-/*
- * gg_debug()
- *
- * 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(int level, char *format, ...)
-{
-	va_list ap;
-
-	if ((gg_debug_level & level)) {
-		va_start(ap, format);
-		vprintf(format, ap);
-		va_end(ap);
-	}
-}
+#endif 
 
 /*
  * fix32() // funkcja wewnętrzna
@@ -90,10 +72,11 @@
 	return x;
 #else
 	return (unsigned long)
-	    (((x & (unsigned long)0x000000ffU) << 24) |
-	     ((x & (unsigned long)0x0000ff00U) << 8) |
-	     ((x & (unsigned long)0x00ff0000U) >> 8) | ((x & (unsigned long)0xff000000U) >> 24));
-#endif
+		(((x & (unsigned long) 0x000000ffU) << 24) |
+                 ((x & (unsigned long) 0x0000ff00U) << 8) |
+                 ((x & (unsigned long) 0x00ff0000U) >> 8) |
+                 ((x & (unsigned long) 0xff000000U) >> 24));
+#endif		
 }
 
 /*
@@ -107,88 +90,12 @@
 	return x;
 #else
 	return (unsigned short)
-	    (((x & (unsigned short)0x00ffU) << 8) | ((x & (unsigned short)0xff00U) >> 8));
+		(((x & (unsigned short) 0x00ffU) << 8) |
+                 ((x & (unsigned short) 0xff00U) >> 8));
 #endif
 }
 
 /*
- * gg_alloc_sprintf() // funkcja wewnętrzna
- *
- * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcześniej
- * miejsce na dane. powinno działać na tych maszynach, które mają funkcję
- * vsnprintf() zgodną z C99, jak i na wcześniejszych.
- *
- *  - 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, *tmp;
-	int size = 0, res;
-
-	va_start(ap, format);
-
-	if ((size = vsnprintf(buf, 0, format, ap)) < 1) {
-		size = 128;
-		do {
-			size *= 2;
-			if (!(tmp = realloc(buf, size))) {
-				free(buf);
-				return NULL;
-			}
-			buf = tmp;
-			res = vsnprintf(buf, size, format, ap);
-		} while (res == size - 1);
-	} else {
-		if (!(buf = malloc(size + 1)))
-			return NULL;
-	}
-
-	vsnprintf(buf, size + 1, format, ap);
-
-	va_end(ap);
-
-	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.
- */
-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_resolve() // funkcja wewnętrzna
  *
  * tworzy pipe'y, forkuje się i w drugim procesie zaczyna resolvować 
@@ -208,7 +115,7 @@
 	struct in_addr a;
 
 	gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(..., \"%s\");\n", hostname);
-
+	
 	if (!fd | !pid) {
 		errno = EFAULT;
 		return -1;
@@ -223,11 +130,11 @@
 	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));
+				memcpy((char*) &a, he->h_addr, sizeof(a));
 		}
 
 		write(pipes[1], &a, sizeof(a));
@@ -244,91 +151,6 @@
 }
 
 /*
- * 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) {
-		if (errno && (!async || errno != EINPROGRESS)) {
-			gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno,
-				 strerror(errno));
-			return -1;
-		}
-		gg_debug(GG_DEBUG_MISC, "-- connect() in progress\n");
-	}
-
-	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
@@ -345,7 +167,7 @@
 	int ret = 0, offset, size = 0;
 
 	gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(...);\n");
-
+	
 	if (!sess) {
 		errno = EFAULT;
 		return NULL;
@@ -357,8 +179,7 @@
 			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));
+					gg_debug(GG_DEBUG_MISC, "-- errno = %d (%s)\n", errno, strerror(errno));
 					return NULL;
 				}
 			}
@@ -400,7 +221,7 @@
 		if (ret > -1 && ret <= size) {
 			offset += ret;
 			size -= ret;
-		} else if (ret == -1) {
+		} 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);
@@ -410,7 +231,7 @@
 				return NULL;
 			}
 			if (errno != EINTR) {
-//                              errno = EINVAL;
+//				errno = EINVAL;
 				free(buf);
 				return NULL;
 			}
@@ -423,8 +244,8 @@
 		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]);
+		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");
 	}
 
@@ -447,16 +268,14 @@
  * 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)
+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);
-
+	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;
@@ -468,7 +287,7 @@
 		return -1;
 	}
 
-	h = (struct gg_header *)tmp;
+	h = (struct gg_header*) tmp;
 	h->type = fix32(type);
 	h->length = fix32(length + payload_length);
 
@@ -482,20 +301,19 @@
 
 		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, " %.2x", (unsigned char) tmp[i]);
 		gg_debug(GG_DEBUG_DUMP, "\n");
 	}
 
 	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));
+		gg_debug(GG_DEBUG_MISC, "-- write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno));
 		free(tmp);
 		return -1;
 	}
 
-	free(tmp);
+	free(tmp);	
 	return 0;
 }
 
@@ -519,6 +337,8 @@
 struct gg_session *gg_login(uin_t uin, char *password, int async)
 {
 	struct gg_session *sess;
+	char *hostname;
+	int port;
 
 	gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%u, \"...\", %d);\n", uin, async);
 
@@ -538,9 +358,18 @@
 	sess->last_pong = 0;
 	sess->server_ip = 0;
 	sess->initial_status = 0;
+        sess->type = GG_SESSION_GG;
+	
+	if (gg_http_use_proxy) {
+		hostname = gg_http_proxy_host;
+		port = gg_http_proxy_port;
+	} else {
+		hostname = GG_APPMSG_HOST;
+		port = GG_APPMSG_PORT;
+	};
 
 	if (async) {
-		if (gg_resolve(&sess->fd, &sess->pid, GG_APPMSG_HOST)) {
+		if (gg_resolve(&sess->fd, &sess->pid, hostname)) {
 			gg_debug(GG_DEBUG_MISC, "-- resolving failed\n");
 			free(sess);
 			return NULL;
@@ -548,24 +377,24 @@
 	} else {
 		struct in_addr a;
 
-		if ((a.s_addr = inet_addr(GG_APPMSG_HOST)) == INADDR_NONE) {
+		if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) {
 			struct hostent *he;
-
-			if (!(he = gethostbyname(GG_APPMSG_HOST))) {
-				gg_debug(GG_DEBUG_MISC, "-- host %s not found\n", GG_APPMSG_HOST);
+	
+			if (!(he = gethostbyname(hostname))) {
+				gg_debug(GG_DEBUG_MISC, "-- host %s not found\n", hostname);
 				free(sess);
 				return NULL;
 			} else
-				memcpy((char *)&a, he->h_addr, sizeof(a));
+				memcpy((char*) &a, he->h_addr, sizeof(a));
 		}
 
-		if (!(sess->fd = gg_connect(&a, GG_APPMSG_PORT, 0)) == -1) {
+		if (!(sess->fd = gg_connect(&a, port, 0)) == -1) {
 			gg_debug(GG_DEBUG_MISC, "-- connection failed\n");
 			free(sess);
 			return NULL;
 		}
 
-		sess->state = GG_STATE_CONNECTING_HTTP;
+		sess->state = GG_STATE_CONNECTING;
 
 		while (sess->state != GG_STATE_CONNECTED) {
 			struct gg_event *e;
@@ -658,7 +487,7 @@
 
 	if (sess->state == GG_STATE_CONNECTED)
 		gg_change_status(sess, GG_STATUS_NOT_AVAIL);
-
+	
 	if (sess->fd) {
 		shutdown(sess->fd, 2);
 		close(sess->fd);
@@ -686,7 +515,7 @@
 		errno = EFAULT;
 		return -1;
 	}
-
+	
 	if (sess->state != GG_STATE_CONNECTED) {
 		errno = ENOTCONN;
 		return -1;
@@ -700,7 +529,7 @@
 	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;
 
@@ -764,7 +593,7 @@
  *
  * 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)
+int gg_notify(struct gg_session *sess, uin_t *userlist, int count)
 {
 	struct gg_notify *n;
 	uin_t *u;
@@ -774,25 +603,25 @@
 		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)))
+	
+	if (!(n = (struct gg_notify*) malloc(sizeof(*n) * count)))
 		return -1;
-
-	for (u = userlist, i = 0; i < count; u++, i++) {
+	
+	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;
 
@@ -824,12 +653,12 @@
 		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);
 }
 
@@ -858,10 +687,10 @@
 	}
 
 	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);
 }
 
@@ -887,13 +716,12 @@
 	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));
+		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);
-
+	p = (void*) h + sizeof(struct gg_header);
+	
 	if (h->type == GG_RECV_MSG) {
 		struct gg_recv_msg *r = p;
 
@@ -903,7 +731,7 @@
 			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));
+			e->event.msg.message = strdup((char*) r + sizeof(*r));
 			e->event.msg.time = fix32(r->time);
 		}
 	}
@@ -913,9 +741,9 @@
 		int count, i;
 
 		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)))) {
+		if (!(e->event.notify = (void*) malloc(h->length + 2 * sizeof(*n)))) {
 			gg_debug(GG_DEBUG_MISC, "-- not enough memory\n");
 			free(h);
 			return -1;
@@ -967,26 +795,6 @@
 }
 
 /*
- * 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.
@@ -1004,6 +812,7 @@
 {
 	struct gg_event *e;
 	int res = 0;
+	int port;
 
 	if (!sess) {
 		errno = EFAULT;
@@ -1012,7 +821,7 @@
 
 	gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(...);\n");
 
-	if (!(e = (void *)malloc(sizeof(*e)))) {
+	if (!(e = (void*) malloc(sizeof(*e)))) {
 		gg_debug(GG_DEBUG_MISC, "-- not enough memory\n");
 		return NULL;
 	}
@@ -1020,14 +829,14 @@
 	e->type = GG_EVENT_NONE;
 
 	switch (sess->state) {
-	case GG_STATE_RESOLVING:
+		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");
+				gg_debug(GG_DEBUG_MISC, "-- resolving failed\n");				
 
 				errno = ENOENT;
 				e->type = GG_EVENT_CONN_FAILED;
@@ -1038,7 +847,7 @@
 
 				break;
 			}
-
+			
 			sess->server_ip = a.s_addr;
 
 			close(sess->fd);
@@ -1046,81 +855,87 @@
 			waitpid(sess->pid, NULL, 0);
 
 			gg_debug(GG_DEBUG_MISC, "-- resolved, now connecting\n");
+			
+			if (gg_http_use_proxy) {
+				port = gg_http_proxy_port;
+			} else {
+				port = GG_APPMSG_PORT;
+			};
 
-			if ((sess->fd = gg_connect(&a, GG_APPMSG_PORT, sess->async)) == -1) {
-				struct in_addr *addr = (struct in_addr *)&sess->server_ip;
-
-				gg_debug(GG_DEBUG_MISC,
-					 "-- connection failed, trying direct connection\n");
+			if ((sess->fd = gg_connect(&a, port, sess->async)) == -1) {
+				struct in_addr *addr = (struct in_addr*) &sess->server_ip;
+				
+				gg_debug(GG_DEBUG_MISC, "-- connection failed, trying direct connection\n");
 
 				if ((sess->fd = gg_connect(addr, GG_DEFAULT_PORT, sess->async)) == -1) {
-					gg_debug(GG_DEBUG_MISC,
-						 "-- connection failed, trying https connection\n");
-					if ((sess->fd =
-					     gg_connect(&a, GG_HTTPS_PORT, sess->async)) == -1) {
-						gg_debug(GG_DEBUG_MISC,
-							 "-- connect() failed. errno = %d (%s)\n", errno,
-							 strerror(errno));
+				    gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n");
+				    if ((sess->fd = gg_connect(&a, GG_HTTPS_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;
-					}
+					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;
 			} else {
-				sess->state = GG_STATE_CONNECTING_HTTP;
+				sess->state = GG_STATE_CONNECTING;
 				sess->check = GG_CHECK_WRITE;
 			}
-
+				
 			break;
 		}
 
-	case GG_STATE_CONNECTING_HTTP:
+		case GG_STATE_CONNECTING:
 		{
 			char buf[1024];
 			int res, res_size = sizeof(res);
 
-			gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING_HTTP\n");
+			gg_debug(GG_DEBUG_MISC, "== GG_STATE_CONNECTING\n");
 
-			if (sess->async
-			    && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
-				struct in_addr *addr = (struct in_addr *)&sess->server_ip;
-				gg_debug(GG_DEBUG_MISC,
-					 "-- http connection failed, errno = %d (%s), trying direct connection\n",
-					 res, strerror(res));
+			if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
+				struct in_addr *addr = (struct in_addr*) &sess->server_ip;
+				gg_debug(GG_DEBUG_MISC, "-- http connection failed, errno = %d (%s), trying direct connection\n", res, strerror(res));
 
 				if ((sess->fd = gg_connect(addr, GG_DEFAULT_PORT, sess->async)) == -1) {
-					gg_debug(GG_DEBUG_MISC,
-						 "-- connection failed, trying https connection\n");
-					if ((sess->fd =
-					     gg_connect(addr, GG_HTTPS_PORT, sess->async)) == -1) {
-						gg_debug(GG_DEBUG_MISC,
-							 "-- connect() failed. errno = %d (%s)\n", errno,
-							 strerror(errno));
+				    gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n");
+				    if ((sess->fd = gg_connect(addr, GG_HTTPS_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;
-					}
+					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;
 			}
-
+			
 			gg_debug(GG_DEBUG_MISC, "-- http connection succeded, sending query\n");
 
-			snprintf(buf, sizeof(buf) - 1,
-				 "GET /appsvc/appmsg.asp?fmnumber=%lu HTTP/1.0\r\n"
-				 "Host: " GG_APPMSG_HOST "\r\n"
-				 "User-Agent: " GG_HTTP_USERAGENT "\r\n"
-				 "Pragma: no-cache\r\n" "\r\n", sess->uin);
+			if (gg_http_use_proxy) {
+				snprintf(buf, sizeof(buf) - 1,
+					"GET http://" GG_APPMSG_HOST "/appsvc/appmsg.asp?fmnumber=%lu HTTP/1.0\r\n"
+					"Host: " GG_APPMSG_HOST "\r\n"
+					"User-Agent: " GG_HTTP_USERAGENT "\r\n"
+					"Pragma: no-cache\r\n"
+					"\r\n", sess->uin);
+			} else {
+				snprintf(buf, sizeof(buf) - 1,
+					"GET /appsvc/appmsg.asp?fmnumber=%lu HTTP/1.0\r\n"
+					"Host: " GG_APPMSG_HOST "\r\n"
+					"User-Agent: " GG_HTTP_USERAGENT "\r\n"
+					"Pragma: no-cache\r\n"
+					"\r\n", sess->uin);
+			};
 
+    			gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", buf);
+	 
 			if (write(sess->fd, buf, strlen(buf)) < strlen(buf)) {
 				gg_debug(GG_DEBUG_MISC, "-- sending query failed\n");
 
@@ -1131,25 +946,24 @@
 				break;
 			}
 
-			sess->state = GG_STATE_WRITING_HTTP;
+			sess->state = GG_STATE_READING_DATA;
 			sess->check = GG_CHECK_READ;
 
 			break;
 		}
 
-	case GG_STATE_WRITING_HTTP:
+		case GG_STATE_READING_DATA:
 		{
 			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_debug(GG_DEBUG_MISC, "== GG_STATE_READING_DATA\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");
 
@@ -1159,18 +973,19 @@
 				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 == ' ')
@@ -1190,78 +1005,70 @@
 
 			if ((tmp = strchr(host, ':'))) {
 				*tmp = 0;
-				port = atoi(tmp + 1);
+				port = atoi(tmp+1);
 			}
 
 			a.s_addr = inet_addr(host);
 			sess->server_ip = a.s_addr;
 
 			if ((sess->fd = gg_connect(&a, port, sess->async)) == -1) {
-				gg_debug(GG_DEBUG_MISC,
-					 "-- connection failed, trying https connection\n");
+				gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n");
 				if ((sess->fd = gg_connect(&a, GG_HTTPS_PORT, sess->async)) == -1) {
-					gg_debug(GG_DEBUG_MISC,
-						 "-- connection failed, errno = %d (%s)\n", errno,
-						 strerror(errno));
+				    gg_debug(GG_DEBUG_MISC, "-- connection 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;
+				    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:
+		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)) {
-				struct in_addr *addr = (struct in_addr *)&sess->server_ip;
+			if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
+				struct in_addr *addr = (struct in_addr*) &sess->server_ip;
 
-				gg_debug(GG_DEBUG_MISC,
-					 "-- connection failed, trying https connection\n");
+				gg_debug(GG_DEBUG_MISC, "-- connection failed, trying https connection\n");
 				if ((sess->fd = gg_connect(addr, GG_HTTPS_PORT, sess->async)) == -1) {
-					gg_debug(GG_DEBUG_MISC,
-						 "-- connection 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;
+				    gg_debug(GG_DEBUG_MISC, "-- connection 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;
 				}
 			}
 
 			gg_debug(GG_DEBUG_MISC, "-- connected\n");
-
-			sess->state = GG_STATE_WAITING_FOR_KEY;
+			
+			sess->state = GG_STATE_READING_KEY;
 			sess->check = GG_CHECK_READ;
 
 			break;
 		}
 
-	case GG_STATE_WAITING_FOR_KEY:
+		case GG_STATE_READING_KEY:
 		{
-			struct gg_header *h;
+			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");
+			gg_debug(GG_DEBUG_MISC, "== GG_STATE_READING_KEY\n");
 
 			if (!(h = gg_recv_packet(sess))) {
-				gg_debug(GG_DEBUG_MISC, "-- gg_recv_packet() failed. errno = %d (%s)\n",
-					 errno, strerror(errno));
+				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;
@@ -1269,7 +1076,7 @@
 				close(sess->fd);
 				break;
 			}
-
+	
 			if (h->type != GG_WELCOME) {
 				gg_debug(GG_DEBUG_MISC, "-- invalid packet received\n");
 
@@ -1281,34 +1088,32 @@
 				sess->state = GG_STATE_IDLE;
 				break;
 			}
-
-			w = (void *)h + sizeof(struct gg_header);
+	
+			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);
-
+	
+			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(sess->initial_status ? sess->initial_status : 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));
+				gg_debug(GG_DEBUG_TRAFFIC, "-- oops, failed. errno = %d (%s)\n", errno, strerror(errno));
 
 				close(sess->fd);
 				e->type = GG_EVENT_CONN_FAILED;
@@ -1316,17 +1121,17 @@
 				sess->state = GG_STATE_IDLE;
 				break;
 			}
-
-			sess->state = GG_STATE_SENDING_KEY;
+	
+			sess->state = GG_STATE_READING_REPLY;
 
 			break;
 		}
 
-	case GG_STATE_SENDING_KEY:
+		case GG_STATE_READING_REPLY:
 		{
 			struct gg_header *h;
 
-			gg_debug(GG_DEBUG_MISC, "== GG_STATE_SENDING_KEY\n");
+			gg_debug(GG_DEBUG_MISC, "== GG_STATE_READING_REPLY\n");
 
 			if (!(h = gg_recv_packet(sess))) {
 				gg_debug(GG_DEBUG_MISC, "-- recv_packet failed\n");
@@ -1336,7 +1141,7 @@
 				close(sess->fd);
 				break;
 			}
-
+	
 			if (h->type == GG_LOGIN_OK) {
 				gg_debug(GG_DEBUG_MISC, "-- login succeded\n");
 				e->type = GG_EVENT_CONN_SUCCESS;
@@ -1363,17 +1168,15 @@
 			break;
 		}
 
-	case GG_STATE_CONNECTED:
+		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));
+				gg_debug(GG_DEBUG_MISC, "-- watch_fd_connected failed. errno = %d (%s)\n", errno, strerror(errno));
 
-				if (errno == EAGAIN) {
+ 				if (errno == EAGAIN) {
 					e->type = GG_EVENT_NONE;
 					res = 0;
 				} else
@@ -1390,3 +1193,13 @@
 
 	return e;
 }
+
+/*
+ * Local variables:
+ * c-indentation-style: k&r
+ * c-basic-offset: 8
+ * indent-tabs-mode: notnil
+ * End:
+ *
+ * vim: shiftwidth=8:
+ */
--- a/src/protocols/gg/libgg.h	Tue Dec 04 19:51:27 2001 +0000
+++ b/src/protocols/gg/libgg.h	Wed Dec 05 09:48:56 2001 +0000
@@ -1,8 +1,8 @@
-/* $Id: libgg.h 2805 2001-11-26 21:22:56Z warmenhoven $ */
+/* $Id: libgg.h 2859 2001-12-05 09:48:56Z warmenhoven $ */
 
 /*
  *  (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>,
- *                     Robert J. Woźny <speedy@atman.pl>
+ *                     Robert J. Woźny <speedy@ziew.org>
  *
  *  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
@@ -18,15 +18,15 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef __LIBGG_H
-#define __LIBGG_H
+#ifndef __GG_LIBGG_H
+#define __GG_LIBGG_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #if defined(sun) && !defined(INADDR_NONE)
-#define INADDR_NONE 0xffffffff
+  #define INADDR_NONE 0xffffffff
 #endif
 
 #include <sys/types.h>
@@ -34,176 +34,297 @@
 /*
  * typ zmiennej określającej numerek danej osoby.
  */
-	typedef unsigned long uin_t;
+typedef unsigned long uin_t;
+
+/*
+ * struktura opisująca daną sesję. tworzona przez gg_login().
+ */
+struct gg_session {
+        int fd;         	/* podglądany deskryptor */
+        int check;      	/* sprawdzamy zapis czy odczyt */
+        int state;      	/* aktualny stan maszynki */
+        int error;      	/* kod błędu dla GG_STATE_ERROR */
+	int type;		/* rodzaj sesji. == GG_SESSION_GG */
+	
+        int async;      	/* czy połączenie jest asynchroniczne */
+	int pid;        	/* pid procesu resolvera */
+	int port;       	/* port, z którym się łączymy */
+	int seq;        	/* numer sekwencyjny ostatniej wiadomości */
+	int last_pong;  	/* czas otrzymania ostatniego ping/pong */
+
+	unsigned int server_ip;	/* adres serwera */
+	unsigned int client_ip;	/* adres klienta */
+	int client_port;	/* port, na którym klient słucha */
+
+	uin_t uin;		/* numerek klienta */
+	char *password;		/* i jego hasło. zwalniane automagicznie */
+        
+	int initial_status;	/* początkowy stan klienta */
+
+	char *recv_buf;		/* bufor na otrzymywane pakiety */
+	int recv_done;		/* ile już wczytano do bufora */
+        int recv_left;		/* i ile jeszcze trzeba wczytać */
+};
 
 /*
- * cośtam.
+ * ogólna struktura opisująca stan wszystkich operacji http.
  */
-	struct gg_session {
-		int state, check;
-		int fd, pid;
-		int port;
-		int seq, async;
-		int last_pong;
+struct gg_http {
+        int fd;                 /* podglądany deskryptor */
+        int check;              /* sprawdzamy zapis czy odczyt */
+        int state;              /* aktualny stan maszynki */
+        int error;              /* kod błędu dla GG_STATE_ERROR */
+ 	int type;		/* rodzaj sesji. == GG_SESSION_HTTP */
+	
+        int async;              /* czy połączenie asynchroniczne */
+	int pid;                /* pid procesu resolvera */
+	int port;               /* port, z którym się łączymy */
+
+        char *query;            /* bufor zapytania http */
+        char *header;           /* bufor nagłówka */
+        int header_size;        /* rozmiar wczytanego nagłówka */
+        char *body;             /* bufor otrzymanych informacji */
+        int body_size;          /* ilość informacji */
 
-		/* powinno być ,,in_addr'', ale nie chcę inkludować sieci tutaj */
-		unsigned long server_ip;
+        void *data;             /* dane danej operacji http */
+};
 
-		uin_t uin;
-		char *password;
-		int initial_status;
+/*
+ * ogólna struktura opisująca różne sesje. przydatna w klientach.
+ */
+struct gg_common {
+        int fd;                 /* podglądany deskryptor */
+        int check;              /* sprawdzamy zapis czy odczyt */
+        int state;              /* aktualny stan maszynki */
+        int error;              /* kod błędu dla GG_STATE_ERROR */
+	int type;		/* rodzaj sesji */
+};
 
-		char *recv_buf;
-		int recv_done, recv_left;
-	};
+/*
+ * rodzaje sesji.
+ */
+enum {
+	GG_SESSION_GG = 1,	/* połączenie z serwerem gg */
+	GG_SESSION_HTTP,	/* ogólna sesja http */
+	GG_SESSION_SEARCH,	/* szukanie */
+	GG_SESSION_REGISTER,	/* rejestrowanie */
+};
 
 /*
  * różne stany asynchronicznej maszynki.
  */
-	enum {
-		GG_STATE_IDLE = 0,	/* wspólne */
-		GG_STATE_RESOLVING,
-		GG_STATE_CONNECTING_HTTP,
+enum {
+        /* wspólne */
+        GG_STATE_IDLE = 0,		/* nie powinno wystąpić. */
+        GG_STATE_RESOLVING,             /* wywołał gethostbyname() */
+	GG_STATE_CONNECTING,            /* wywołał connect() */
+	GG_STATE_READING_DATA,		/* czeka na dane http */
+	GG_STATE_ERROR,			/* wystąpił błąd. kod w x->error */
+
+        /* gg_session */
+	GG_STATE_CONNECTING_GG,         /* wywołał connect() */
+	GG_STATE_READING_KEY,           /* czeka na klucz */
+	GG_STATE_READING_REPLY,         /* czeka na odpowiedź */
+	GG_STATE_CONNECTED,             /* połączył się */
 
-		GG_STATE_WRITING_HTTP,	/* gg_login */
-		GG_STATE_CONNECTING_GG,
-		GG_STATE_WAITING_FOR_KEY,
-		GG_STATE_SENDING_KEY,
-		GG_STATE_CONNECTED,
+        /* gg_http */
+	GG_STATE_READING_HEADER,	/* czeka na nagłówek http */
+	GG_STATE_PARSING,               /* przetwarza dane */
+	GG_STATE_DONE,                  /* skończył */
+};
 
-		GG_STATE_READING_HEADER,	/* gg_search */
-		GG_STATE_READING_DATA,
-		GG_STATE_PARSING,
-		GG_STATE_FINISHED,
-	};
+/*
+ * dla zachowania kompatybilności wstecz. w wersji 1.0 będzie usunięte. oby.
+ */
+#define GG_STATE_WRITING_HTTP GG_STATE_READING_DATA
+#define GG_STATE_WAITING_FOR_KEY GG_STATE_READING_KEY
+#define GG_STATE_SENDING_KEY GG_STATE_READING_REPLY
+#define GG_STATE_FINISHED GG_STATE_DONE
 
 /*
  * co proces klienta powinien sprawdzać w deskryptorach?
  */
-	enum {
-		GG_CHECK_NONE = 0,
-		GG_CHECK_WRITE = 1,
-		GG_CHECK_READ = 2,
-	};
+enum {
+	GG_CHECK_NONE = 0,		/* nic. nie powinno wystąpić */
+	GG_CHECK_WRITE = 1,		/* sprawdzamy możliwość zapisu */
+	GG_CHECK_READ = 2,		/* sprawdzamy możliwość odczytu */
+};
 
-	struct gg_session *gg_login(uin_t uin, char *password, int async);
-	void gg_free_session(struct gg_session *sess);
-	void gg_logoff(struct gg_session *sess);
-	int gg_change_status(struct gg_session *sess, int status);
-	int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient,
-			    unsigned char *message);
-	int gg_ping(struct gg_session *sess);
+struct gg_session *gg_login(uin_t uin, char *password, int async);
+void gg_free_session(struct gg_session *sess);
+void gg_logoff(struct gg_session *sess);
+int gg_change_status(struct gg_session *sess, int status);
+int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, unsigned char *message);
+int gg_ping(struct gg_session *sess);
 
-	struct gg_notify_reply {
-		uin_t uin;	/* numerek */
-		unsigned long status;	/* status danej osoby */
-		unsigned long remote_ip;	/* adres ip delikwenta */
-		unsigned short remote_port;	/* port, na którym słucha klient */
-		unsigned long dunno1;	/* == 0x0b */
-		unsigned short dunno2;	/* znowu port? */
-	} __attribute__ ((packed));
+struct gg_notify_reply {
+	uin_t uin;			/* numerek */
+	unsigned long status;		/* status danej osoby */
+	unsigned long remote_ip;	/* adres ip delikwenta */
+	unsigned short remote_port;	/* port, na którym słucha klient */
+	unsigned long version;		/* == 0x0b */
+	unsigned short dunno2;		/* znowu port? */
+} __attribute__ ((packed));
 
-	struct gg_status {
-		uin_t uin;	/* numerek */
-		unsigned long status;	/* nowy stan */
-	} __attribute__ ((packed));
+struct gg_status {
+	uin_t uin;			/* numerek */
+	unsigned long status;		/* nowy stan */
+} __attribute__ ((packed));
 
-	enum {
-		GG_EVENT_NONE = 0,
-		GG_EVENT_MSG,
-		GG_EVENT_NOTIFY,
-		GG_EVENT_STATUS,
-		GG_EVENT_ACK,
-		GG_EVENT_CONN_FAILED,
-		GG_EVENT_CONN_SUCCESS,
-	};
-
-	enum {
-		GG_FAILURE_RESOLVING = 1,
-		GG_FAILURE_CONNECTING,
-		GG_FAILURE_INVALID,
-		GG_FAILURE_READING,
-		GG_FAILURE_WRITING,
-		GG_FAILURE_PASSWORD,
-	};
+enum {
+	GG_EVENT_NONE = 0,
+	GG_EVENT_MSG,
+	GG_EVENT_NOTIFY,
+	GG_EVENT_STATUS,
+	GG_EVENT_ACK,
+	GG_EVENT_CONN_FAILED,
+	GG_EVENT_CONN_SUCCESS,
+};
 
-	struct gg_event {
-		int type;
-		union {
-			struct {
-				uin_t sender;
-				int msgclass;
-				time_t time;
-				unsigned char *message;
-			} msg;
-			struct gg_notify_reply *notify;
-			struct gg_status status;
-			struct {
-				uin_t recipient;
-				int status;
-				int seq;
-			} ack;
-			int failure;
-		} event;
-	};
+/*
+ * niedługo się tego pozbędę na rzecz sensownej obsługi błędów. --w
+ */
+enum {
+	GG_FAILURE_RESOLVING = 1,
+	GG_FAILURE_CONNECTING,
+	GG_FAILURE_INVALID,
+	GG_FAILURE_READING,
+	GG_FAILURE_WRITING,
+	GG_FAILURE_PASSWORD,
+	GG_FAILURE_404,
+};
 
-	struct gg_event *gg_watch_fd(struct gg_session *sess);
-	void gg_free_event(struct gg_event *e);
-
-	int gg_notify(struct gg_session *sess, uin_t * userlist, int count);
-	int gg_add_notify(struct gg_session *sess, uin_t uin);
-	int gg_remove_notify(struct gg_session *sess, uin_t uin);
+/*
+ * rodzaje błędów, na razie używane przez http. bez rozczulania się nad
+ * powodami. klient powie, że albo nie znalazł hosta, albo nie mógł się
+ * połączyć, albo nie mógł wysłać, albo nie mógł odebrac. i tyle. jak
+ * ktoś będzie chciał, to będzie mógł sprawdzić errno. ale po co?
+ */
+enum {
+	GG_ERROR_RESOLVING = 1,
+	GG_ERROR_CONNECTING,
+	GG_ERROR_READING,
+	GG_ERROR_WRITING,
+};
 
 /*
- * jakieśtam bzdurki dotyczące szukania userów.
+ * struktura opisująca rodzaj zdarzenia. wychodzi z gg_watch_fd()
+ */
+struct gg_event {
+        int type;
+        union {
+                struct {
+                        uin_t sender;
+			int msgclass;
+			time_t time;
+                        unsigned char *message;
+                } msg;
+                struct gg_notify_reply *notify;
+                struct gg_status status;
+                struct {
+                        uin_t recipient;
+                        int status;
+                        int seq;
+                } ack;
+		int failure;
+        } event;
+};
+
+struct gg_event *gg_watch_fd(struct gg_session *sess);
+void gg_free_event(struct gg_event *e);
+
+int gg_notify(struct gg_session *sess, uin_t *userlist, int count);
+int gg_add_notify(struct gg_session *sess, uin_t uin);
+int gg_remove_notify(struct gg_session *sess, uin_t uin);
+
+
+/*
+ * OBSŁUGA HTTP
+ */
+
+struct gg_http *gg_http_connect(char *hostname, int port, int async, char *method, char *path, char *header);
+int gg_http_watch_fd(struct gg_http *h);
+void gg_http_stop(struct gg_http *h);
+void gg_free_http(struct gg_http *h);
+
+/* 
+ * SZUKANIE UŻYTKOWNIKÓW
  */
 
-	struct gg_search_result {
-		uin_t uin;
-		char *first_name;
-		char *last_name;
-		char *nickname;
-		int born;
-		int gender;
-		char *city;
-		int active;
-	};
+/*
+ * struktura opisująca kryteria wyszukiwania. argument gg_search().
+ */
+struct gg_search_request {
+	int active;		/* czy ma szukać tylko aktywnych? */
+
+	/* mode 0 */
+	char *nickname;		/* pseudonim */
+	char *first_name;	/* imię */
+	char *last_name;	/* nazwisko */
+	char *city;		/* miasto */
+	int gender;		/* płeć */
+	int min_birth;		/* urodzony od roku... */
+	int max_birth;		/* urodzony do roku... */
+	
+	/* mode 1 */
+	char *email;		/* adres e-mail */
+
+	/* mode 2 */
+	char *phone;		/* numer telefonu */
+	
+	/* mode 3 */
+	uin_t uin;		/* numerek */
+};
+
+/*
+ * struktura opisująca rezultat wyszukiwania. pole gg_http.
+ */
+struct gg_search {
+	int count;				/* ilość znalezionych */
+	struct gg_search_result *results;	/* tabelka z nimi */
+};
 
-	struct gg_search_request {
-		/* czy ma szukać tylko aktywnych? */
-		int active;
-		/* mode 0 */
-		char *nickname, *first_name, *last_name, *city;
-		int gender, min_birth, max_birth;
-		/* mode 1 */
-		char *email;
-		/* mode 2 */
-		char *phone;
-		/* mode 3 */
-		uin_t uin;
-	};
+/*
+ * pojedynczy rezultat wyszukiwania.
+ */
+struct gg_search_result {
+	uin_t uin;		/* numerek */
+	char *first_name;	/* imię */
+	char *last_name;	/* nazwisko */
+	char *nickname;		/* pseudonim */
+	int born;		/* rok urodzenia */
+	int gender;		/* płeć */
+	char *city;		/* miasto */
+	int active;		/* czy jest aktywny */
+};
 
-	struct gg_search {
-		struct gg_search_request request;
+#define GG_GENDER_NONE 0	/* nie podano lub bez znaczenia */
+#define GG_GENDER_FEMALE 1	/* kobieta */
+#define GG_GENDER_MALE 2	/* mężczyzna */
 
-		/* bzdurki */
-		int mode, fd, async, state, check, error, pid;
-		char *header_buf, *data_buf;
-		int header_size, data_size;
+struct gg_http *gg_search(struct gg_search_request *r, int async);
+int gg_search_watch_fd(struct gg_http *f);
+void gg_free_search(struct gg_http *f);
+
+struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active);
+struct gg_search_request *gg_search_request_mode_1(char *email, int active);
+struct gg_search_request *gg_search_request_mode_2(char *phone, int active);
+struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active);
 
-		/* wyniki */
-		int count;
-		struct gg_search_result *results;
-	};
+/*
+ * OPERACJE NA KATALOGU PUBLICZNYM
+ */
 
-#define GG_GENDER_NONE 0
-#define GG_GENDER_FEMALE 1
-#define GG_GENDER_MALE 2
+struct gg_pubdir {
+	int success;		/* czy się udało */
+	uin_t uin;		/* otrzymany numerek. 0 jeśli błąd */
+};
 
-	struct gg_search *gg_search(struct gg_search_request *r, int async);
-	int gg_search_watch_fd(struct gg_search *f);
-	void gg_free_search(struct gg_search *f);
-	void gg_search_cancel(struct gg_search *f);
+struct gg_http *gg_register(char *email, char *password, int async);
+void gg_free_register(struct gg_http *f);
+
+int gg_pubdir_watch_fd(struct gg_http *f);
+#define gg_register_watch_fd gg_pubdir_watch_fd
 
 /*
  * jeśli chcemy sobie podebugować, wystarczy ustawić `gg_debug_level'.
@@ -211,7 +332,7 @@
  * się ustawiać odpowiednich leveli, więc większość szła do _MISC.
  */
 
-	extern int gg_debug_level;
+extern int gg_debug_level;
 
 #define GG_DEBUG_NET 1
 #define GG_DEBUG_TRAFFIC 2
@@ -219,7 +340,16 @@
 #define GG_DEBUG_FUNCTION 8
 #define GG_DEBUG_MISC 16
 
-	void gg_debug(int level, char *format, ...);
+void gg_debug(int level, char *format, ...);
+
+/*
+ * Pare małych zmiennych do obsługi "http proxy"
+ *   
+ */
+ 
+extern int gg_http_use_proxy;
+extern char *gg_http_proxy_host;
+extern int gg_http_proxy_port;
 
 /*
  * -------------------------------------------------------------------------
@@ -230,41 +360,47 @@
  * -------------------------------------------------------------------------
  */
 
-	int gg_resolve(int *fd, int *pid, char *hostname);
-	int gg_connect(void *addr, int port, int async);
-	char *gg_alloc_sprintf(char *format, ...);
-	char *gg_get_line(char **ptr);
-	char *gg_urlencode(char *str);
+int gg_resolve(int *fd, int *pid, char *hostname);
+void gg_debug(int level, char *format, ...);
+char *gg_alloc_sprintf(char *format, ...);
+char *gg_get_line(char **ptr);
+int gg_connect(void *addr, int port, int async);
+void gg_read_line(int sock, char *buf, int length);
+void gg_chomp(char *line);
+char *gg_urlencode(char *str);
+int gg_http_hash(unsigned char *email, unsigned char *password);
 
 #define GG_APPMSG_HOST "appmsg.gadu-gadu.pl"
 #define GG_APPMSG_PORT 80
 #define GG_PUBDIR_HOST "pubdir.gadu-gadu.pl"
 #define GG_PUBDIR_PORT 80
+#define GG_REGISTER_HOST "register.gadu-gadu.pl"
+#define GG_REGISTER_PORT 80
 #define GG_DEFAULT_PORT 8074
 #define GG_HTTPS_PORT 443
 #define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)"
 
-	struct gg_header {
-		unsigned long type;	/* typ pakietu */
-		unsigned long length;	/* długość reszty pakietu */
-	} __attribute__ ((packed));
+struct gg_header {
+	unsigned long type;		/* typ pakietu */
+	unsigned long length;		/* długość reszty pakietu */
+} __attribute__ ((packed));
 
 #define GG_WELCOME 0x0001
 
-	struct gg_welcome {
-		unsigned long key;	/* klucz szyfrowania hasła */
-	} __attribute__ ((packed));
-
+struct gg_welcome {
+	unsigned long key;		/* klucz szyfrowania hasła */
+} __attribute__ ((packed));
+	
 #define GG_LOGIN 0x000c
 
-	struct gg_login {
-		uin_t uin;	/* twój numerek */
-		unsigned long hash;	/* hash hasła */
-		unsigned long status;	/* status na dzień dobry */
-		unsigned long dunno;	/* == 0x0b */
-		unsigned long local_ip;	/* mój adres ip */
-		unsigned short local_port;	/* port, na którym słucham */
-	} __attribute__ ((packed));
+struct gg_login {
+	uin_t uin;			/* twój numerek */
+	unsigned long hash;		/* hash hasła */
+	unsigned long status;		/* status na dzień dobry */
+	unsigned long dunno;		/* == 0x0b */
+	unsigned long local_ip;		/* mój adres ip */
+	unsigned short local_port;	/* port, na którym słucham */
+} __attribute__ ((packed));
 
 #define GG_LOGIN_OK 0x0003
 
@@ -273,39 +409,39 @@
 #define GG_NEW_STATUS 0x0002
 
 #define GG_STATUS_NOT_AVAIL 0x0001	/* rozłączony */
-#define GG_STATUS_AVAIL 0x0002	/* dostępny */
-#define GG_STATUS_BUSY 0x0003	/* zajęty */
+#define GG_STATUS_AVAIL 0x0002		/* dostępny */
+#define GG_STATUS_BUSY 0x0003		/* zajęty */
 #define GG_STATUS_INVISIBLE 0x0014	/* niewidoczny (GG 4.6) */
 
 #define GG_STATUS_FRIENDS_MASK 0x8000	/* tylko dla znajomych (GG 4.6) */
 
-	struct gg_new_status {
-		unsigned long status;	/* na jaki zmienić? */
-	} __attribute__ ((packed));
+struct gg_new_status {
+	unsigned long status;			/* na jaki zmienić? */
+} __attribute__ ((packed));
 
 #define GG_NOTIFY 0x0010
-
-	struct gg_notify {
-		uin_t uin;	/* numerek danej osoby */
-		char dunno1;	/* == 3 */
-	} __attribute__ ((packed));
-
+	
+struct gg_notify {
+	uin_t uin;		/* numerek danej osoby */
+	char dunno1;		/* == 3 */
+} __attribute__ ((packed));
+	
 #define GG_NOTIFY_REPLY 0x000c	/* tak, to samo co GG_LOGIN */
-
+	
 /* struct gg_notify_reply zadeklarowane wyżej */
 
 #define GG_ADD_NOTIFY 0x000d
 #define GG_REMOVE_NOTIFY 0x000e
-
-	struct gg_add_remove {
-		uin_t uin;	/* numerek */
-		char dunno1;	/* == 3 */
-	} __attribute__ ((packed));
+	
+struct gg_add_remove {
+	uin_t uin;		/* numerek */
+	char dunno1;		/* == 3 */
+} __attribute__ ((packed));
 
 #define GG_STATUS 0x0002
 
 /* struct gg_status zadeklarowane wcześniej */
-
+	
 #define GG_SEND_MSG 0x000b
 
 #define GG_CLASS_QUEUED 0x0001
@@ -313,37 +449,48 @@
 #define GG_CLASS_MSG 0x0004
 #define GG_CLASS_CHAT 0x0008
 
-	struct gg_send_msg {
-		unsigned long recipient;
-		unsigned long seq;
-		unsigned long msgclass;
-	} __attribute__ ((packed));
+struct gg_send_msg {
+	unsigned long recipient;
+	unsigned long seq;
+	unsigned long msgclass;
+} __attribute__ ((packed));
 
 #define GG_SEND_MSG_ACK 0x0005
 
 #define GG_ACK_DELIVERED 0x0002
 #define GG_ACK_QUEUED 0x0003
-
-	struct gg_send_msg_ack {
-		unsigned long status;
-		unsigned long recipient;
-		unsigned long seq;
-	} __attribute__ ((packed));
+	
+struct gg_send_msg_ack {
+	unsigned long status;
+	unsigned long recipient;
+	unsigned long seq;
+} __attribute__ ((packed));
 
 #define GG_RECV_MSG 0x000a
-
-	struct gg_recv_msg {
-		unsigned long sender;
-		unsigned long seq;
-		unsigned long time;
-		unsigned long msgclass;
-	} __attribute__ ((packed));
+	
+struct gg_recv_msg {
+	unsigned long sender;
+	unsigned long seq;
+	unsigned long time;
+	unsigned long msgclass;
+} __attribute__ ((packed));
 
 #define GG_PING 0x0008
-
+	
 #define GG_PONG 0x0007
 
 #ifdef __cplusplus
 }
 #endif
-#endif
+
+#endif /* __GG_LIBGG_H */
+
+/*
+ * Local variables:
+ * c-indentation-style: k&r
+ * c-basic-offset: 8
+ * indent-tabs-mode: notnil
+ * End:
+ *
+ * vim: shiftwidth=8:
+ */