changeset 12007:8724718d387f

[gaim-migrate @ 14300] Further updates to gg from Bartosz Oler. This makes the login and token retrieval processes asynchronous. There are also some encoding fixes and various cleanups. There are some changes from me to make it work on win32. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Tue, 08 Nov 2005 19:45:09 +0000
parents de25a063aebe
children 91aaa1b3ac30
files src/protocols/gg/buddylist.c src/protocols/gg/buddylist.h src/protocols/gg/confer.c src/protocols/gg/confer.h src/protocols/gg/gg.c src/protocols/gg/gg.h src/protocols/gg/lib/libgadu.c src/protocols/gg/lib/libgadu.h src/protocols/gg/search.c src/protocols/gg/search.h src/protocols/gg/utils.c src/protocols/gg/utils.h
diffstat 12 files changed, 923 insertions(+), 513 deletions(-) [+]
line wrap: on
line diff
--- a/src/protocols/gg/buddylist.c	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/buddylist.c	Tue Nov 08 19:45:09 2005 +0000
@@ -32,50 +32,52 @@
 void ggp_buddylist_send(GaimConnection *gc)
 {
 	GGPInfo *info = gc->proto_data;
+	GaimAccount *account = gaim_connection_get_account(gc);
 
 	GaimBuddyList *blist;
 	GaimBlistNode *gnode, *cnode, *bnode;
 	GaimBuddy *buddy;
 	uin_t *userlist = NULL;
 	gchar *types = NULL;
-	int userlist_size = 0;
+	int size = 0;
+
+	if ((blist = gaim_get_blist()) == NULL)
+	    return;
 
-	if ((blist = gaim_get_blist()) != NULL)
-	{
-		for (gnode = blist->root; gnode != NULL; gnode = gnode->next)
-		{
-			if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
+	for (gnode = blist->root; gnode != NULL; gnode = gnode->next) {
+		if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
+			continue;
+
+		for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) {
+			if (!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 				continue;
-			for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
-			{
-				if (!GAIM_BLIST_NODE_IS_CONTACT(cnode))
+
+			for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) {
+				if (!GAIM_BLIST_NODE_IS_BUDDY(bnode))
 					continue;
-				for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
-				{
-					if (!GAIM_BLIST_NODE_IS_BUDDY(bnode))
-						continue;
-					buddy = (GaimBuddy *)bnode;
+
+				buddy = (GaimBuddy *)bnode;
+
+				if (buddy->account != account)
+					continue;
 
-					if (buddy->account != gc->account)
-						continue;
-
-					userlist_size++;
-					userlist = (uin_t *) g_renew(uin_t, userlist, userlist_size);
-					types = (gchar *) g_renew(gchar, types, userlist_size);
-					userlist[userlist_size - 1] = ggp_str_to_uin(buddy->name);
-					types[userlist_size - 1] = GG_USER_NORMAL;
-					gaim_debug_info("gg", "ggp_buddylist_send: adding %d\n", userlist[userlist_size - 1]);
-				}
+				size++;
+				userlist = (uin_t *) g_renew(uin_t, userlist, size);
+				types    = (gchar *) g_renew(gchar, types, size);
+				userlist[size - 1] = ggp_str_to_uin(buddy->name);
+				types[size - 1]    = GG_USER_NORMAL;
+				gaim_debug_info("gg", "ggp_buddylist_send: adding %d\n",
+						userlist[size - 1]);
 			}
 		}
 	}
 
 	if (userlist) {
-		int ret = gg_notify_ex(info->session, userlist, types, userlist_size);
+		int ret = gg_notify_ex(info->session, userlist, types, size);
 		g_free(userlist);
 		g_free(types);
 
-		gaim_debug_info("gg", "send: ret=%d; size=%d\n", ret, userlist_size);
+		gaim_debug_info("gg", "send: ret=%d; size=%d\n", ret, size);
 	}
 }
 /* }}} */
@@ -88,6 +90,9 @@
 	gchar **users_tbl;
 	int i;
 
+	/*
+	 * XXX: Limit of entries in a buddylist that will be imported.
+	 */
 	users_tbl = g_strsplit(buddylist, "\r\n", 200);
 
 	for (i = 0; users_tbl[i] != NULL; i++) {
@@ -122,7 +127,9 @@
 			g_strfreev(group_tbl);
 		}
 
-		buddy = gaim_buddy_new(gaim_connection_get_account(gc), name, strlen(show) ? show : NULL);
+		buddy = gaim_buddy_new(gaim_connection_get_account(gc), name,
+				       strlen(show) ? show : NULL);
+
 		if (!(group = gaim_find_group(g))) {
 			group = gaim_group_new(g);
 			gaim_blist_add_group(group, NULL);
@@ -144,35 +151,38 @@
 /* void ggp_buddylist_offline(GaimConnection *gc) {{{ */
 void ggp_buddylist_offline(GaimConnection *gc)
 {
+	GaimAccount *account = gaim_connection_get_account(gc);
 	GaimBuddyList *blist;
 	GaimBlistNode *gnode, *cnode, *bnode;
 	GaimBuddy *buddy;
 
-	if ((blist = gaim_get_blist()) != NULL)
-	{
-		for (gnode = blist->root; gnode != NULL; gnode = gnode->next)
-		{
-			if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
+	if ((blist = gaim_get_blist()) == NULL)
+		return;
+
+	for (gnode = blist->root; gnode != NULL; gnode = gnode->next) {
+		if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
+			continue;
+
+		for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) {
+			if (!GAIM_BLIST_NODE_IS_CONTACT(cnode))
 				continue;
-			for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
-			{
-				if (!GAIM_BLIST_NODE_IS_CONTACT(cnode))
+
+			for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) {
+				if (!GAIM_BLIST_NODE_IS_BUDDY(bnode))
 					continue;
-				for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
-				{
-					if (!GAIM_BLIST_NODE_IS_BUDDY(bnode))
-						continue;
+
+				buddy = (GaimBuddy *)bnode;
 
-					buddy = (GaimBuddy *)bnode;
+				if (buddy->account != account)
+					continue;
 
-					if (buddy->account != gc->account)
-						continue;
+				gaim_prpl_got_user_status(
+					gaim_connection_get_account(gc),
+					buddy->name, "offline", NULL);
 
-					gaim_prpl_got_user_status(
-						gaim_connection_get_account(gc),
-						buddy->name, "offline", NULL);
-					gaim_debug_info("gg", "ggp_buddylist_offline: gone: %s\n", buddy->name);
-				}
+				gaim_debug_info("gg",
+					"ggp_buddylist_offline: gone: %s\n",
+					buddy->name);
 			}
 		}
 	}
@@ -204,7 +214,8 @@
 				continue;
 
 			for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) {
-				gchar *newdata, *name, *show, *gname;
+				gchar *newdata, *name, *alias, *gname;
+				gchar *cp_alias, *cp_gname;
 
 				if (!GAIM_BLIST_NODE_IS_BUDDY(bnode))
 					continue;
@@ -214,17 +225,23 @@
 					continue;
 
 				name = buddy->name;
-				show = buddy->alias ? buddy->alias : buddy->name;
+				alias = buddy->alias ? buddy->alias : buddy->name;
 				gname = group->name;
 
-				newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
-						show, show, show, show, "", gname, name, "", "");
+				cp_gname = charset_convert(gname, "UTF-8", "CP1250");
+				cp_alias = charset_convert(alias, "UTF-8", "CP1250");
+				newdata = g_strdup_printf(
+						"%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
+						cp_alias, cp_alias, cp_alias, cp_alias,
+						"", cp_gname, name, "", "");
 
 				ptr = buddylist;
 				buddylist = g_strconcat(ptr, newdata, NULL);
 
 				g_free(newdata);
 				g_free(ptr);
+				g_free(cp_gname);
+				g_free(cp_alias);
 			}
 		}
 	}
@@ -234,4 +251,4 @@
 /* }}} */
 
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/buddylist.h	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/buddylist.h	Tue Nov 08 19:45:09 2005 +0000
@@ -61,4 +61,5 @@
 
 #endif /* _GAIM_GG_BUDDYLIST_H */
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/confer.c	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/confer.c	Tue Nov 08 19:45:09 2005 +0000
@@ -33,13 +33,13 @@
 	g_return_val_if_fail(name != NULL, NULL);
 
 	return gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, name,
-				gaim_connection_get_account(gc));
+			gaim_connection_get_account(gc));
 }
 /* }}} */
 
 /* void ggp_confer_participants_add_uin(GaimConnection *gc, const gchar *chat_name, const uin_t uin) {{{ */
 void ggp_confer_participants_add_uin(GaimConnection *gc, const gchar *chat_name,
-								   const uin_t uin)
+							 const uin_t uin)
 {
 	GaimConversation *conv;
 	GGPInfo *info = gc->proto_data;
@@ -52,23 +52,27 @@
 	for (l = info->chats; l != NULL; l = l->next) {
 		chat = l->data;
 
-		if (g_utf8_collate(chat->name, chat_name) == 0) {
-			if (g_list_find(chat->participants, str_uin) == NULL) {
-				chat->participants = g_list_append(chat->participants, str_uin);
-				conv = ggp_confer_find_by_name(gc, chat_name);
+		if (g_utf8_collate(chat->name, chat_name) != 0)
+			continue;
+
+		if (g_list_find(chat->participants, str_uin) == NULL) {
+			chat->participants = g_list_append(
+						chat->participants, str_uin);
 
-				gaim_conv_chat_add_user(GAIM_CONV_CHAT(conv),
-						ggp_buddy_get_name(gc, uin), NULL, GAIM_CBFLAGS_NONE, TRUE);
-			}
-			break;
+			conv = ggp_confer_find_by_name(gc, chat_name);
+
+			gaim_conv_chat_add_user(GAIM_CONV_CHAT(conv),
+				ggp_buddy_get_name(gc, uin), NULL,
+				GAIM_CBFLAGS_NONE, TRUE);
 		}
+		break;
 	}
 }
 /* }}} */
 
 /* void ggp_confer_participants_add(GaimConnection *gc, const gchar *chat_name, const uin_t *recipients, int count) {{{ */
 void ggp_confer_participants_add(GaimConnection *gc, const gchar *chat_name,
-							   const uin_t *recipients, int count)
+				 const uin_t *recipients, int count)
 {
 	GaimConversation *conv;
 	GGPInfo *info = gc->proto_data;
@@ -80,28 +84,34 @@
 	for (l = info->chats; l != NULL; l = l->next) {
 		chat = l->data;
 
-		if (g_utf8_collate(chat->name, chat_name) == 0) {
+		if (g_utf8_collate(chat->name, chat_name) != 0)
+			continue;
 
-			for (i = 0; i < count; i++) {
-				uin = g_strdup_printf("%lu", (unsigned long int)recipients[i]);
-				if (g_list_find(chat->participants, uin) == NULL) {
-					chat->participants = g_list_append(chat->participants, uin);
-					conv = ggp_confer_find_by_name(gc, chat_name);
+		for (i = 0; i < count; i++) {
+			uin = g_strdup_printf("%lu", (unsigned long int)recipients[i]);
+
+			if (g_list_find(chat->participants, uin) != NULL) {
+				g_free(uin);
+				continue;
+			}
 
-					gaim_conv_chat_add_user(GAIM_CONV_CHAT(conv),
-							ggp_buddy_get_name(gc, recipients[i]),
-							NULL, GAIM_CBFLAGS_NONE, TRUE);
-				}
-				g_free(uin);
-			}
-			break;
+			chat->participants = g_list_append(chat->participants, uin);
+			conv = ggp_confer_find_by_name(gc, chat_name);
+
+			gaim_conv_chat_add_user(GAIM_CONV_CHAT(conv),
+				ggp_buddy_get_name(gc, recipients[i]),
+				NULL, GAIM_CBFLAGS_NONE, TRUE);
+
+			g_free(uin);
 		}
+		break;
 	}
 }
 /* }}} */
 
 /* const char *ggp_confer_find_by_participants(GaimConnection *gc, const uin_t *recipients, int count) {{{ */
-const char *ggp_confer_find_by_participants(GaimConnection *gc, const uin_t *recipients, int count)
+const char *ggp_confer_find_by_participants(GaimConnection *gc,
+					    const uin_t *recipients, int count)
 {
 	GGPInfo *info = gc->proto_data;
 	GGPChat *chat = NULL;
@@ -157,4 +167,4 @@
 }
 /* }}} */
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/confer.h	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/confer.h	Tue Nov 08 19:45:09 2005 +0000
@@ -44,7 +44,8 @@
  * @param chat_name Name of the conversation.
  */
 void
-ggp_confer_participants_add_uin(GaimConnection *gc, const gchar *chat_name, const uin_t uin);
+ggp_confer_participants_add_uin(GaimConnection *gc, const gchar *chat_name,
+						    const uin_t uin);
 
 /**
  * Add the specified UINs to the specified conversation.
@@ -56,7 +57,7 @@
  */
 void
 ggp_confer_participants_add(GaimConnection *gc, const gchar *chat_name,
-						  const uin_t *recipients, int count);
+			    const uin_t *recipients, int count);
 
 /**
  * Finds a conversation in which all the specified recipients participate.
@@ -71,7 +72,8 @@
  * @return Name of the conversation.
  */
 const char*
-ggp_confer_find_by_participants(GaimConnection *gc, const uin_t *recipients, int count);
+ggp_confer_find_by_participants(GaimConnection *gc, const uin_t *recipients,
+						    int count);
 
 /**
  * Adds a new conversation to the internal list of conversations.
@@ -88,4 +90,4 @@
 
 #endif /* _GAIM_GG_CONFER_H */
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/gg.c	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/gg.c	Tue Nov 08 19:45:09 2005 +0000
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2005  Bartosz Oler <bartosz@bzimage.us>
  *
- * Some parts of the code are adapted or taken for the previous implementation
+ * Some parts of the code are adapted or taken from the previous implementation
  * of this plugin written by Arkadiusz Miskiewicz <misiek@pld.org.pl>
  *
  * Thanks to Google's Summer of Code Program.
@@ -60,6 +60,105 @@
 /* ----- EXTERNAL CALLBACKS --------------------------------------------- */
 /* ---------------------------------------------------------------------- */
 
+
+/* ----- HELPERS -------------------------------------------------------- */
+
+/*
+ */
+/* static void ggp_async_token_handler(gpointer _gc, gint fd, GaimInputCondition cond) {{{ */
+static void ggp_async_token_handler(gpointer _gc, gint fd, GaimInputCondition cond)
+{
+	GaimConnection *gc = _gc;
+	GGPInfo *info = gc->proto_data;
+	GGPToken *token = info->token;
+	GGPTokenCallback cb;
+
+	struct gg_token *t = NULL;
+
+	gaim_debug_info("gg", "token_handler: token->req->fd = %d\n", token->req->fd);
+	gaim_debug_info("gg", "token_handler: token->req: check = %d; state = %d;\n",
+			token->req->check, token->req->state);
+
+	if (gg_token_watch_fd(token->req) == -1 || token->req->state == GG_STATE_ERROR) {
+		gaim_debug_error("gg", "token error (1): %d\n", token->req->error);
+		gaim_input_remove(token->inpa);
+		gg_token_free(token->req);
+		token->req = NULL;
+
+		gaim_notify_error(gaim_connection_get_account(gc),
+				  _("Token Error"),
+				  _("Unable to fetch the token.\n"), NULL);
+		return;
+	}
+
+	if (token->req->state != GG_STATE_DONE) {
+		gaim_input_remove(token->inpa);
+		token->inpa = gaim_input_add(token->req->fd,
+						   (token->req->check == 1)
+						   	? GAIM_INPUT_WRITE
+							: GAIM_INPUT_READ,
+						   ggp_async_token_handler, gc);
+		return;
+	}
+
+	if (!(t = token->req->data) || !token->req->body) {
+		gaim_debug_error("gg", "token error (2): %d\n", token->req->error);
+		gaim_input_remove(token->inpa);
+		gg_token_free(token->req);
+		token->req = NULL;
+
+		gaim_notify_error(gaim_connection_get_account(gc),
+				  _("Token Error"),
+				  _("Unable to fetch the token.\n"), NULL);
+		return;
+	}
+
+	gaim_input_remove(token->inpa);
+
+	token->id = g_strdup(t->tokenid);
+	token->size = token->req->body_size;
+	token->data = g_new0(char, token->size);
+	memcpy(token->data, token->req->body, token->size);
+
+	gaim_debug_info("gg", "TOKEN! tokenid = %s; size = %d\n",
+			token->id, token->size);
+
+	gg_token_free(token->req);
+	token->req = NULL;
+	token->inpa = 0;
+
+	cb = token->cb;
+	token->cb = NULL;
+	cb(gc);
+}
+/* }}} */
+
+/*
+ */
+/* static void ggp_token_request(GaimConnection *gc, GGPTokenCallback cb) {{{ */
+static void ggp_token_request(GaimConnection *gc, GGPTokenCallback cb)
+{
+	GGPInfo *info = gc->proto_data;
+	struct gg_http *req;
+
+	if ((req = gg_token(1)) == NULL) {
+		gaim_notify_error(gaim_connection_get_account(gc),
+				  _("Token Error"),
+				  _("Unable to fetch the token.\n"), NULL);
+		return;
+	}
+
+	info->token = g_new(GGPToken, 1);
+	info->token->cb = cb;
+
+	info->token->req = req;
+	info->token->inpa = gaim_input_add(req->fd, GAIM_INPUT_READ,
+					   ggp_async_token_handler, gc);
+}
+/* }}} */
+
+/* ---------------------------------------------------------------------- */
+
 /**
  * Request buddylist from the server.
  * Buddylist is received in the ggp_callback_recv().
@@ -134,8 +233,8 @@
 
 	if (buddylist == NULL) {
 		gaim_notify_info(account, _("Save Buddylist..."),
-				 _("Your buddylist is empty, nothing was written to the file."),
-				 NULL);
+			 _("Your buddylist is empty, nothing was written to the file."),
+			 NULL);
 		return;
 	}
 
@@ -163,35 +262,27 @@
 static void ggp_callback_buddylist_load_ok(GaimConnection *gc, gchar *file)
 {
 	GaimAccount *account = gaim_connection_get_account(gc);
-	char *buddylist, *tmp, *ptr;
-	FILE *fh;
-	gchar *msg;
-
-	buddylist = g_strdup("");
-	tmp = g_new0(gchar, 50);
+	GError *error = NULL;
+	char *buddylist = NULL;
+	gsize length;
 
 	gaim_debug_info("gg", "file_name = %s\n", file);
 
-	if ((fh = g_fopen(file, "rb")) == NULL) {
-		msg = g_strconcat(_("Couldn't open file"), ": ", file, "\n", NULL);
-		gaim_debug_error("gg", "Could not open file: %s\n", file);
-		gaim_notify_error(account, _("Could't open file"), msg, NULL);
-		g_free(msg);
-		g_free(file);
+	if (!g_file_get_contents(file, &buddylist, &length, &error)) {
+		gaim_notify_error(account,
+				_("Couldn't load buddylist"),
+				_("Couldn't load buddylist"),
+				error->message);
+
+		gaim_debug_error("gg",
+			"Couldn't load buddylist. file = %s; error = %s\n",
+			file, error->message);
+
+		g_error_free(error);
+
 		return;
 	}
 
-	while (fread(tmp, sizeof(gchar), 49, fh) == 49) {
-		tmp[49] = '\0';
-		/* gaim_debug_info("gg", "read: %s\n", tmp); */
-		ptr = g_strconcat(buddylist, tmp, NULL);
-		memset(tmp, '\0', 50); 
-		g_free(buddylist);
-		buddylist = ptr;
-	}
-	fclose(fh);
-	g_free(tmp);
-
 	ggp_buddylist_load(gc, buddylist);
 	g_free(buddylist);
 
@@ -209,7 +300,7 @@
 	GaimConnection *gc = (GaimConnection *)action->context;
 
 	gaim_request_file(action, _("Save buddylist..."), NULL, TRUE,
-				G_CALLBACK(ggp_callback_buddylist_save_ok), NULL, gc);
+			G_CALLBACK(ggp_callback_buddylist_save_ok), NULL, gc);
 }
 /* }}} */
 
@@ -221,14 +312,15 @@
 	GaimConnection *gc = (GaimConnection *)action->context;
 
 	gaim_request_file(action, "Load buddylist from file...", NULL, FALSE,
-				G_CALLBACK(ggp_callback_buddylist_load_ok), NULL, gc);
+			G_CALLBACK(ggp_callback_buddylist_load_ok), NULL, gc);
 }
 /* }}} */
 
 /*
  */
 /* static void ggp_callback_register_account_ok(GaimConnection *gc, GaimRequestFields *fields) {{{ */
-static void ggp_callback_register_account_ok(GaimConnection *gc, GaimRequestFields *fields)
+static void ggp_callback_register_account_ok(GaimConnection *gc,
+					     GaimRequestFields *fields)
 {
 	GaimAccount *account;
 	GGPInfo *info = gc->proto_data;
@@ -236,7 +328,7 @@
 	struct gg_pubdir *s;
 	uin_t uin;
 	gchar *email, *p1, *p2, *t;
-	GGPToken *token = info->register_token;
+	GGPToken *token = info->token;
 
 	email = charset_convert(gaim_request_fields_get_string(fields, "email"),
 			     "UTF-8", "CP1250");
@@ -260,7 +352,9 @@
 		goto exit_err;
 	}
 
-	h = gg_register3(email, p1, token->token_id, t, 0);
+	gaim_debug_info("gg", "register_account_ok: token_id = %d; t = %s\n",
+			token->id, t);
+	h = gg_register3(email, p1, token->id, t, 0);
 	if (h == NULL || !(s = h->data) || !s->success) {
 		gaim_connection_error(gc,
 			_("Unable to register new account. Error occurred.\n"));
@@ -279,7 +373,10 @@
 	gaim_notify_info(NULL, _("New Gadu-Gadu Account Registered"),
 			 _("Registration completed successfully!"), NULL);
 
-	/* TODO: the currently open Accounts Window will not be updated withthe new username and etc, we need to somehow have it refresh at this point */
+	/* TODO: the currently open Accounts Window will not be updated withthe
+	 * new username and etc, we need to somehow have it refresh at this
+	 * point
+	 */
 
 	/* Need to disconnect or actually log in. For now, we disconnect. */
 	gaim_connection_destroy(gc);
@@ -290,7 +387,7 @@
 	g_free(p1);
 	g_free(p2);
 	g_free(t);
-	g_free(token->token_id);
+	g_free(token->id);
 	g_free(token);
 }
 /* }}} */
@@ -298,19 +395,77 @@
 /*
  */
 /* static void ggp_callback_register_account_cancel(GaimConnection *gc, GaimRequestFields *fields) {{{ */
-static void ggp_callback_register_account_cancel(GaimConnection *gc, GaimRequestFields *fields)
+static void ggp_callback_register_account_cancel(GaimConnection *gc,
+						 GaimRequestFields *fields)
 {
 	GGPInfo *info = gc->proto_data;
-	GGPToken *token = info->register_token;
+	GGPToken *token = info->token;
 
 	gaim_connection_destroy(gc);
 
-	g_free(token->token_id);
+	g_free(token->id);
+	g_free(token->data);
 	g_free(token);
 
 }
 /* }}} */
 
+/*
+ */
+/* static void ggp_register_user_dialog(GaimConnection *gc) {{{ */
+static void ggp_register_user_dialog(GaimConnection *gc)
+{
+	GaimAccount *account;
+	GaimRequestFields *fields;
+	GaimRequestFieldGroup *group;
+	GaimRequestField *field;
+
+	GGPInfo *info = gc->proto_data;
+	GGPToken *token = info->token;
+
+
+	account = gaim_connection_get_account(gc);
+
+	fields = gaim_request_fields_new();
+	group = gaim_request_field_group_new(NULL);
+	gaim_request_fields_add_group(fields, group);
+
+	field = gaim_request_field_string_new("email",
+			_("e-Mail"), "", FALSE);
+	gaim_request_field_string_set_masked(field, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("password1",
+			_("Password"), "", FALSE);
+	gaim_request_field_string_set_masked(field, TRUE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("password2",
+			_("Password (retype)"), "", FALSE);
+	gaim_request_field_string_set_masked(field, TRUE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("token",
+			_("Enter current token"), "", FALSE);
+	gaim_request_field_string_set_masked(field, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	/* original size: 60x24 */
+	field = gaim_request_field_image_new("token_img",
+			_("Current token"), token->data, token->size);
+	gaim_request_field_group_add_field(group, field);
+
+	gaim_request_fields(account,
+		_("Register New Gadu-Gadu Account"),
+		_("Register New Gadu-Gadu Account"),
+		_("Please, fill in the following fields"),
+		fields,
+		_("OK"), G_CALLBACK(ggp_callback_register_account_ok),
+		_("Cancel"), G_CALLBACK(ggp_callback_register_account_cancel),
+		gc);
+}
+/* }}} */
+
 /* ----- PUBLIC DIRECTORY SEARCH ---------------------------------------- */
 
 /*
@@ -332,7 +487,7 @@
 static void ggp_callback_add_buddy(GaimConnection *gc, GList *row)
 {
 	gaim_blist_request_add_buddy(gaim_connection_get_account(gc),
-			g_list_nth_data(row, 0), NULL, NULL);
+				     g_list_nth_data(row, 0), NULL, NULL);
 }
 /* }}} */
 
@@ -351,16 +506,21 @@
 	 */
 	info->search_form = form;
 
-	form->lastname  = charset_convert(gaim_request_fields_get_string(fields, "lastname"),
-									 "UTF-8", "CP1250");
-	form->firstname = charset_convert(gaim_request_fields_get_string(fields, "firstname"),
-									 "UTF-8", "CP1250");
-	form->nickname  = charset_convert(gaim_request_fields_get_string(fields, "nickname"),
-									 "UTF-8", "CP1250");
-	form->city      = charset_convert(gaim_request_fields_get_string(fields, "city"),
-									 "UTF-8", "CP1250");
-	form->birthyear = charset_convert(gaim_request_fields_get_string(fields, "year"),
-								     "UTF-8", "CP1250");
+	form->lastname  = charset_convert(
+				gaim_request_fields_get_string(fields, "lastname"),
+				"UTF-8", "CP1250");
+	form->firstname = charset_convert(
+				gaim_request_fields_get_string(fields, "firstname"),
+				"UTF-8", "CP1250");
+	form->nickname  = charset_convert(
+				gaim_request_fields_get_string(fields, "nickname"),
+				"UTF-8", "CP1250");
+	form->city      = charset_convert(
+				gaim_request_fields_get_string(fields, "city"),
+				"UTF-8", "CP1250");
+	form->birthyear = charset_convert(
+				gaim_request_fields_get_string(fields, "year"),
+				"UTF-8", "CP1250");
 
 	switch (gaim_request_fields_get_choice(fields, "gender")) {
 		case 1:
@@ -398,32 +558,38 @@
 	group = gaim_request_field_group_new(NULL);
 	gaim_request_fields_add_group(fields, group);
 
-	field = gaim_request_field_string_new("lastname", _("Last name"), NULL, FALSE);
+	field = gaim_request_field_string_new("lastname",
+			_("Last name"), NULL, FALSE);
 	gaim_request_field_string_set_masked(field, FALSE);
 	gaim_request_field_group_add_field(group, field);
 
-	field = gaim_request_field_string_new("firstname", _("First name"), NULL, FALSE);
+	field = gaim_request_field_string_new("firstname",
+			_("First name"), NULL, FALSE);
 	gaim_request_field_string_set_masked(field, FALSE);
 	gaim_request_field_group_add_field(group, field);
 
-	field = gaim_request_field_string_new("nickname", _("Nickname"), NULL, FALSE);
+	field = gaim_request_field_string_new("nickname",
+			_("Nickname"), NULL, FALSE);
 	gaim_request_field_string_set_masked(field, FALSE);
 	gaim_request_field_group_add_field(group, field);
 
-	field = gaim_request_field_string_new("city", _("City"), NULL, FALSE);
+	field = gaim_request_field_string_new("city",
+			_("City"), NULL, FALSE);
 	gaim_request_field_string_set_masked(field, FALSE);
 	gaim_request_field_group_add_field(group, field);
 
-	field = gaim_request_field_string_new("year", _("Year of birth"), NULL, FALSE);
+	field = gaim_request_field_string_new("year",
+			_("Year of birth"), NULL, FALSE);
 	gaim_request_field_group_add_field(group, field);
 
-	field = gaim_request_field_choice_new("gender", "Gender", 0);
-	gaim_request_field_choice_add(field, "Male or female");
-	gaim_request_field_choice_add(field, "Male");
-	gaim_request_field_choice_add(field, "Female");
+	field = gaim_request_field_choice_new("gender", _("Gender"), 0);
+	gaim_request_field_choice_add(field, _("Male or female"));
+	gaim_request_field_choice_add(field, _("Male"));
+	gaim_request_field_choice_add(field, _("Female"));
 	gaim_request_field_group_add_field(group, field);
 
-	field = gaim_request_field_bool_new("active", _("Only online"), FALSE);
+	field = gaim_request_field_bool_new("active",
+			_("Only online"), FALSE);
 	gaim_request_field_group_add_field(group, field);
 
 	gaim_request_fields(gc,
@@ -449,14 +615,18 @@
 	struct gg_http *h;
 	gchar *cur, *p1, *p2, *t;
 
-	cur = charset_convert(gaim_request_fields_get_string(fields, "password_cur"),
-			     "UTF-8", "CP1250");
-	p1  = charset_convert(gaim_request_fields_get_string(fields, "password1"),
-			     "UTF-8", "CP1250");
-	p2  = charset_convert(gaim_request_fields_get_string(fields, "password2"),
-			     "UTF-8", "CP1250");
-	t   = charset_convert(gaim_request_fields_get_string(fields, "token"),
-			     "UTF-8", "CP1250");
+	cur = charset_convert(
+			gaim_request_fields_get_string(fields, "password_cur"),
+			"UTF-8", "CP1250");
+	p1  = charset_convert(
+			gaim_request_fields_get_string(fields, "password1"),
+			"UTF-8", "CP1250");
+	p2  = charset_convert(
+			gaim_request_fields_get_string(fields, "password2"),
+			"UTF-8", "CP1250");
+	t   = charset_convert(
+			gaim_request_fields_get_string(fields, "token"),
+			"UTF-8", "CP1250");
 
 	account = gaim_connection_get_account(gc);
 
@@ -467,7 +637,8 @@
 	}
 
 	if (g_utf8_collate(p1, p2) != 0) {
-		gaim_notify_error(account, NULL, _("New passwords do not match."), NULL);
+		gaim_notify_error(account, NULL,
+				  _("New passwords do not match."), NULL);
 		goto exit_err;
 	}
 
@@ -479,12 +650,12 @@
 	}
 
 	gaim_debug_info("gg", "change_passwd: old=%s; p1=%s; token=%s\n",
-			cur, p1, info->chpasswd_token->token_id);
+			cur, p1, info->token->id);
 
 	/* XXX: this e-mail should be a pref... */
 	h = gg_change_passwd4(ggp_get_uin(account),
 			      "user@example.net", gaim_account_get_password(account),
-			      p1, info->chpasswd_token->token_id, t, 0);
+			      p1, info->token->id, t, 0);
 
 	if (h == NULL) {
 		gaim_notify_error(account, NULL,
@@ -505,8 +676,68 @@
 	g_free(p1);
 	g_free(p2);
 	g_free(t);
-	g_free(info->chpasswd_token->token_id);
-	g_free(info->chpasswd_token);
+	g_free(info->token->id);
+	g_free(info->token->data);
+	g_free(info->token);
+}
+/* }}} */
+
+/*
+ */
+/* static void ggp_change_passwd_dialog(GaimConnection *gc) {{{ */
+static void ggp_change_passwd_dialog(GaimConnection *gc)
+{
+	GaimRequestFields *fields;
+	GaimRequestFieldGroup *group;
+	GaimRequestField *field;
+
+	GGPInfo *info = gc->proto_data;
+	GGPToken *token = info->token;
+
+	char *msg;
+
+
+	fields = gaim_request_fields_new();
+	group = gaim_request_field_group_new(NULL);
+	gaim_request_fields_add_group(fields, group);
+
+	field = gaim_request_field_string_new("password_cur",
+			_("Current password"), "", FALSE);
+	gaim_request_field_string_set_masked(field, TRUE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("password1",
+			_("Password"), "", FALSE);
+	gaim_request_field_string_set_masked(field, TRUE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("password2",
+			_("Password (retype)"), "", FALSE);
+	gaim_request_field_string_set_masked(field, TRUE);
+	gaim_request_field_group_add_field(group, field);
+
+	field = gaim_request_field_string_new("token",
+			_("Enter current token"), "", FALSE);
+	gaim_request_field_string_set_masked(field, FALSE);
+	gaim_request_field_group_add_field(group, field);
+
+	/* original size: 60x24 */
+	field = gaim_request_field_image_new("token_img",
+			_("Current token"), token->data, token->size);
+	gaim_request_field_group_add_field(group, field);
+
+	msg = g_strdup_printf("%s %d",
+		_("Please, enter your current password and your new password for UIN: "),
+		ggp_get_uin(gaim_connection_get_account(gc)));
+
+	gaim_request_fields(gc,
+		_("Change Gadu-Gadu Password"),
+		_("Change Gadu-Gadu Password"),
+		msg,
+		fields, _("OK"), G_CALLBACK(ggp_callback_change_passwd_ok),
+		_("Cancel"), NULL, gc);
+
+	g_free(msg);
 }
 /* }}} */
 
@@ -516,72 +747,8 @@
 static void ggp_change_passwd(GaimPluginAction *action)
 {
 	GaimConnection *gc = (GaimConnection *)action->context;
-	GGPInfo *info = gc->proto_data;
-	GGPToken *token;
 
-	GaimRequestFields *fields;
-	GaimRequestFieldGroup *group;
-	GaimRequestField *field;
-
-	struct gg_http *req;
-	struct gg_token *t;
-	gchar *msg;
-
-	gaim_debug_info("gg", "token: requested.\n");
-
-	/* TODO: This should be async. */
-	if ((req = gg_token(0)) == NULL) {
-		gaim_notify_error(gaim_connection_get_account(gc),
-						  _("Token Error"),
-						  _("Unable to fetch the token.\n"), NULL);
-		return;
-	}
-
-	t = req->data;
-
-	token = g_new0(GGPToken, 1);
-	token->token_id = g_strdup(t->tokenid);
-	info->chpasswd_token = token;
-
-
-	fields = gaim_request_fields_new();
-	group = gaim_request_field_group_new(NULL);
-	gaim_request_fields_add_group(fields, group);
-
-	field = gaim_request_field_string_new("password_cur", _("Current password"), "", FALSE);
-	gaim_request_field_string_set_masked(field, TRUE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("password1", _("Password"), "", FALSE);
-	gaim_request_field_string_set_masked(field, TRUE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("password2", _("Password (retype)"), "", FALSE);
-	gaim_request_field_string_set_masked(field, TRUE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("token", _("Enter current token"), "", FALSE);
-	gaim_request_field_string_set_masked(field, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	/* original size: 60x24 */
-	field = gaim_request_field_image_new("token_img", _("Current token"), req->body, req->body_size);
-	gaim_request_field_group_add_field(group, field);
-
-	gg_token_free(req);
-
-	msg = g_strdup_printf("%s %d",
-			_("Please, enter your current password and your new password for UIN: "),
-			ggp_get_uin(gaim_connection_get_account(gc)));
-
-	gaim_request_fields(gc,
-		_("Change Gadu-Gadu Password"),
-		_("Change Gadu-Gadu Password"),
-		msg,
-		fields, _("OK"), G_CALLBACK(ggp_callback_change_passwd_ok),
-		_("Cancel"), NULL, gc);
-
-	g_free(msg);
+	ggp_token_request(gc, ggp_change_passwd_dialog);
 }
 /* }}} */
 
@@ -598,13 +765,15 @@
 
 	field = gaim_request_fields_get_field(fields, "name");
 	sel = gaim_request_field_list_get_selected(field);
-	gaim_debug_info("gg", "selected chat %s for buddy %s\n", sel->data, info->tmp_buddy);
+	gaim_debug_info("gg", "selected chat %s for buddy %s\n",
+			sel->data, info->tmp_buddy);
 
 	for (l = info->chats; l != NULL; l = l->next) {
 		GGPChat *chat = l->data;
 
 		if (g_utf8_collate(chat->name, sel->data) == 0) {
-			chat->participants = g_list_append(chat->participants, info->tmp_buddy);
+			chat->participants = g_list_append(chat->participants,
+							   info->tmp_buddy);
 			break;
 		}
 	}
@@ -642,11 +811,13 @@
 	for (l = info->chats; l != NULL; l = l->next) {
 		GGPChat *chat = l->data;
 		gaim_debug_info("gg", "adding chat %s\n", chat->name);
-		gaim_request_field_list_add(field, g_strdup(chat->name), g_strdup(chat->name));
+		gaim_request_field_list_add(field, g_strdup(chat->name),
+					    g_strdup(chat->name));
 	}
 	gaim_request_field_group_add_field(group, field);
 
-	msg = g_strdup_printf(_("Select a chat for buddy: %s"), gaim_buddy_get_name(buddy));
+	msg = g_strdup_printf(_("Select a chat for buddy: %s"),
+			      gaim_buddy_get_name(buddy));
 	gaim_request_fields(gc,
 			_("Add to chat..."),
 			_("Add to chat..."),
@@ -703,7 +874,8 @@
  * @param descr  Description.
  */
 /* static void ggp_generic_status_handler(GaimConnection *gc, uin_t uin, int status, const char *descr) {{{ */
-static void ggp_generic_status_handler(GaimConnection *gc, uin_t uin, int status, const char *descr)
+static void ggp_generic_status_handler(GaimConnection *gc, uin_t uin,
+				       int status, const char *descr)
 {
 	gchar *from;
 	const char *st;
@@ -729,18 +901,103 @@
 			break;
 		default:
 			st = "available";
-			gaim_debug_info("gg", "GG_EVENT_NOTIFY: Unknown status: %d\n", status);
+			gaim_debug_info("gg",
+				"GG_EVENT_NOTIFY: Unknown status: %d\n", status);
 			break;
 	}
 
 	gaim_debug_info("gg", "st = %s\n", st);
 	msg = charset_convert(descr, "CP1250", "UTF-8");
-	gaim_prpl_got_user_status(gaim_connection_get_account(gc), from, st, "message", msg, NULL);
+	gaim_prpl_got_user_status(gaim_connection_get_account(gc),
+				  from, st, "message", msg, NULL);
 	g_free(from);
 	g_free(msg);
 }
 /* }}} */
 
+/*
+ */
+/* static void ggp_pubdir_reply_handler(GaimConnection *gc, gg_pubdir50_t req) {{{ */
+static void ggp_pubdir_reply_handler(GaimConnection *gc, gg_pubdir50_t req)
+{
+	GGPInfo *info = gc->proto_data;
+	GaimNotifySearchResults *results;
+	GaimNotifySearchColumn *column;
+	int res_count = 0;
+	int start;
+	int i;
+
+	res_count = gg_pubdir50_count(req);
+	if (res_count < 1) {
+		gaim_debug_info("gg", "GG_EVENT_PUBDIR50_SEARCH_REPLY: Nothing found\n");
+		return;
+	}
+	res_count = (res_count > 20) ? 20 : res_count;
+
+	results = gaim_notify_searchresults_new();
+
+	column = gaim_notify_searchresults_column_new("UIN");
+	gaim_notify_searchresults_column_add(results, column);
+
+	column = gaim_notify_searchresults_column_new("First name");
+	gaim_notify_searchresults_column_add(results, column);
+
+	column = gaim_notify_searchresults_column_new("Nick name");
+	gaim_notify_searchresults_column_add(results, column);
+
+	column = gaim_notify_searchresults_column_new("City");
+	gaim_notify_searchresults_column_add(results, column);
+
+	column = gaim_notify_searchresults_column_new("Birth year");
+	gaim_notify_searchresults_column_add(results, column);
+
+	gaim_debug_info("gg", "Going with %d entries\n", res_count);
+
+	start = (int)ggp_str_to_uin(gg_pubdir50_get(req, 0, GG_PUBDIR50_START));
+	gaim_debug_info("gg", "start = %d\n", start);
+
+	for (i = 0; i < res_count; i++) {
+		GList *row = NULL;
+		char *birth = ggp_search_get_result(req, i, GG_PUBDIR50_BIRTHYEAR);
+
+		/* TODO: Status will be displayed as an icon. */
+		/* row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_STATUS)); */
+		row = g_list_append(row, ggp_search_get_result(req, i,
+							GG_PUBDIR50_UIN));
+		row = g_list_append(row, ggp_search_get_result(req, i,
+							GG_PUBDIR50_FIRSTNAME));
+		row = g_list_append(row, ggp_search_get_result(req, i,
+							GG_PUBDIR50_NICKNAME));
+		row = g_list_append(row, ggp_search_get_result(req, i,
+							GG_PUBDIR50_CITY));
+		row = g_list_append(row,
+			(birth && strncmp(birth, "0", 1)) ? birth : g_strdup("-"));
+
+		gaim_notify_searchresults_row_add(results, row);
+
+		if (i == res_count - 1) {
+			g_free(info->search_form->last_uin);
+			info->search_form->last_uin = ggp_search_get_result(req, i,
+								GG_PUBDIR50_UIN);
+		}
+	}
+
+	gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_CONTINUE,
+					     ggp_callback_show_next);
+	gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_ADD_BUDDY,
+					     ggp_callback_add_buddy);
+	if (info->searchresults_window == NULL) {
+		void *h = gaim_notify_searchresults(gc,
+				_("Gadu-Gadu Public Directory"),
+				_("Search results"), NULL, results, NULL, NULL);
+		info->searchresults_window = h;
+	} else {
+		gaim_notify_searchresults_new_rows(gc, results,
+				info->searchresults_window, NULL);
+	}
+}
+/* }}} */
+
 /**
  * Dispatch a message received from a buddy.
  *
@@ -761,35 +1018,36 @@
 	from = g_strdup_printf("%lu", (unsigned long int)ev->event.msg.sender);
 
 	msg = charset_convert((const char *)ev->event.msg.message,
-						  "CP1250", "UTF-8");
+			      "CP1250", "UTF-8");
 	gaim_str_strip_char(msg, '\r');
 	tmp = g_markup_escape_text(msg, -1);
 
 	gaim_debug_info("gg", "msg form (%s): %s (class = %d; rcpt_count = %d)\n",
-			from, tmp, ev->event.msg.msgclass, ev->event.msg.recipients_count);
+			from, tmp, ev->event.msg.msgclass,
+			ev->event.msg.recipients_count);
 
-	/*
-	 * Chat between only two presons will be treated as a private message.
-	 * It's due to some broken clients that send private messages
-	 * with msgclass == CHAT
-	 */
 	if (ev->event.msg.recipients_count == 0) {
 		serv_got_im(gc, from, tmp, 0, ev->event.msg.time);
 	} else {
 		chat_name = ggp_confer_find_by_participants(gc,
-									ev->event.msg.recipients,
-									ev->event.msg.recipients_count);
+				ev->event.msg.recipients,
+				ev->event.msg.recipients_count);
 		if (chat_name == NULL) {
 			chat_name = ggp_confer_add_new(gc, NULL);
 			serv_got_joined_chat(gc, info->chats_count, chat_name);
-			ggp_confer_participants_add_uin(gc, chat_name, ev->event.msg.sender);
-			ggp_confer_participants_add(gc, chat_name, ev->event.msg.recipients,
-									  ev->event.msg.recipients_count);
+
+			ggp_confer_participants_add_uin(gc, chat_name,
+							ev->event.msg.sender);
+
+			ggp_confer_participants_add(gc, chat_name,
+						    ev->event.msg.recipients,
+						    ev->event.msg.recipients_count);
 		}
 		conv = ggp_confer_find_by_name(gc, chat_name);
 		chat_id = gaim_conv_chat_get_id(GAIM_CONV_CHAT(conv));
-		serv_got_chat_in(gc, chat_id, ggp_buddy_get_name(gc, ev->event.msg.sender),
-						 0, msg, ev->event.msg.time);
+		serv_got_chat_in(gc, chat_id,
+				 ggp_buddy_get_name(gc, ev->event.msg.sender),
+				 0, msg, ev->event.msg.time);
 	}
 	g_free(msg);
 	g_free(tmp);
@@ -808,7 +1066,8 @@
 	int i;
 
 	if (!(ev = gg_watch_fd(info->session))) {
-		gaim_debug_error("gg", "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n");
+		gaim_debug_error("gg",
+			"ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n");
 		gaim_connection_error(gc, _("Unable to read socket"));
 		return;
 	}
@@ -821,8 +1080,10 @@
 			ggp_recv_message_handler(gc, ev);
 			break;
 		case GG_EVENT_ACK:
-			gaim_debug_info("gg", "message sent to: %ld, delivery status=%d, seq=%d\n",
-					ev->event.ack.recipient, ev->event.ack.status, ev->event.ack.seq);
+			gaim_debug_info("gg",
+				"message sent to: %ld, delivery status=%d, seq=%d\n",
+				ev->event.ack.recipient, ev->event.ack.status,
+				ev->event.ack.seq);
 			break;
 		case GG_EVENT_NOTIFY:
 		case GG_EVENT_NOTIFY_DESCR:
@@ -839,29 +1100,34 @@
 
 				for (; n->uin; n++) {
 					descr = (ev->type == GG_EVENT_NOTIFY) ? NULL
-					      				      : ev->event.notify_descr.descr;
-					gaim_debug_info("gg", "notify: (%d) status: %d; descr: %s\n",
-							n->uin, n->status, descr);
+							: ev->event.notify_descr.descr;
+
+					gaim_debug_info("gg",
+						"notify: (%d) status: %d; descr: %s\n",
+						n->uin, n->status, descr);
 
 					ggp_generic_status_handler(gc,
-							n->uin, n->status, descr);
+						n->uin, n->status, descr);
 				}
 			}
 			break;
 		case GG_EVENT_NOTIFY60:
-			gaim_debug_info("gg", "notify60_pre: (%d) status=%d; version=%d; descr=%s\n",
-					ev->event.notify60->uin, ev->event.notify60->status,
-					ev->event.notify60->version, ev->event.notify60->descr);
+			gaim_debug_info("gg",
+				"notify60_pre: (%d) status=%d; version=%d; descr=%s\n",
+				ev->event.notify60->uin, ev->event.notify60->status,
+				ev->event.notify60->version, ev->event.notify60->descr);
 
 			for (i = 0; ev->event.notify60[i].uin; i++) {
-				gaim_debug_info("gg", "notify60: (%d) status=%d; version=%d; descr=%s\n",
-						ev->event.notify60[i].uin, ev->event.notify60[i].status,
-						ev->event.notify60[i].version, ev->event.notify60[i].descr);
+				gaim_debug_info("gg",
+					"notify60: (%d) status=%d; version=%d; descr=%s\n",
+					ev->event.notify60[i].uin,
+					ev->event.notify60[i].status,
+					ev->event.notify60[i].version,
+					ev->event.notify60[i].descr);
 
-				ggp_generic_status_handler(gc,
-						ev->event.notify60[i].uin,
-						ev->event.notify60[i].status,
-						ev->event.notify60[i].descr);
+				ggp_generic_status_handler(gc, ev->event.notify60[i].uin,
+					ev->event.notify60[i].status,
+					ev->event.notify60[i].descr);
 			}
 			break;
 		case GG_EVENT_STATUS:
@@ -869,103 +1135,119 @@
 					ev->event.status.uin, ev->event.status.status,
 					ev->event.status.descr);
 
-			ggp_generic_status_handler(gc,
-						   ev->event.status.uin,
-						   ev->event.status.status,
-						   ev->event.status.descr);
+			ggp_generic_status_handler(gc, ev->event.status.uin,
+				ev->event.status.status, ev->event.status.descr);
 			break;
 		case GG_EVENT_STATUS60:
-			gaim_debug_info("gg", "status60: (%d) status=%d; version=%d; descr=%s\n",
-					ev->event.status60.uin,
-					ev->event.status60.status,
-					ev->event.status60.version,
-					ev->event.status60.descr);
+			gaim_debug_info("gg",
+				"status60: (%d) status=%d; version=%d; descr=%s\n",
+				ev->event.status60.uin, ev->event.status60.status,
+				ev->event.status60.version, ev->event.status60.descr);
 
-			ggp_generic_status_handler(gc,
-						   ev->event.status60.uin,
-						   ev->event.status60.status,
-						   ev->event.status60.descr);
+			ggp_generic_status_handler(gc, ev->event.status60.uin,
+				ev->event.status60.status, ev->event.status60.descr);
 			break;
 		case GG_EVENT_USERLIST:
 	    		if (ev->event.userlist.type == GG_USERLIST_GET_REPLY) {
 				gaim_debug_info("gg", "GG_USERLIST_GET_REPLY\n");
 				if (ev->event.userlist.reply != NULL) {
-				    ggp_buddylist_load(gc, ev->event.userlist.reply);
+					ggp_buddylist_load(gc, ev->event.userlist.reply);
 				}
-			break;
 			} else {
-				gaim_debug_info("gg", "GG_USERLIST_PUT_REPLY. Userlist stored on the server.\n");
+				gaim_debug_info("gg",
+					"GG_USERLIST_PUT_REPLY. Userlist stored on the server.\n");
 			}
 			break;
 		case GG_EVENT_PUBDIR50_SEARCH_REPLY:
-			{
-				GaimNotifySearchResults *results;
-				GaimNotifySearchColumn *column;
-				gg_pubdir50_t req = ev->event.pubdir50;
-				int res_count = 0;
-				int start;
-				int i;
-
-				res_count = gg_pubdir50_count(req);
-				if (res_count < 1) {
-					gaim_debug_info("gg", "GG_EVENT_PUBDIR50_SEARCH_REPLY: Nothing found\n");
-					return;
-				}
-				res_count = (res_count > 20) ? 20 : res_count;
+			ggp_pubdir_reply_handler(gc, ev->event.pubdir50);
+			break;
+		default:
+			gaim_debug_error("gg",
+				"unsupported event type=%d\n", ev->type);
+			break;
+	}
 
-				results = gaim_notify_searchresults_new();
-
-				column = gaim_notify_searchresults_column_new("UIN");
-				gaim_notify_searchresults_column_add(results, column);
-
-				column = gaim_notify_searchresults_column_new("First name");
-				gaim_notify_searchresults_column_add(results, column);
+	gg_free_event(ev);
+}
+/* }}} */
 
-				column = gaim_notify_searchresults_column_new("Nick name");
-				gaim_notify_searchresults_column_add(results, column);
-
-				column = gaim_notify_searchresults_column_new("City");
-				gaim_notify_searchresults_column_add(results, column);
-
-				column = gaim_notify_searchresults_column_new("Birth year");
-				gaim_notify_searchresults_column_add(results, column);
+/*
+ */
+/* static void ggp_async_login_handler(gpointer _gc, gint fd, GaimInputCondition cond) {{{ */
+static void ggp_async_login_handler(gpointer _gc, gint fd, GaimInputCondition cond)
+{
+	GaimConnection *gc = _gc;
+	GGPInfo *info = gc->proto_data;
+	struct gg_event *ev;
 
-				gaim_debug_info("gg", "Going with %d entries\n", res_count);
-
-				start = (int)ggp_str_to_uin(gg_pubdir50_get(req, 0, GG_PUBDIR50_START));
-				gaim_debug_info("gg", "start = %d\n", start);
+	gaim_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
+			info->session->check, info->session->state);
 
-				for (i = 0; i < res_count; i++) {
-					GList *row = NULL;
-					char *birth = ggp_search_get_result(req, i, GG_PUBDIR50_BIRTHYEAR);
-					
-					/* TODO: Status will be displayed as an icon. */
-					/* row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_STATUS)); */
-					row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_UIN));
-					row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_FIRSTNAME));
-					row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_NICKNAME));
-					row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_CITY));
-					row = g_list_append(row, (birth && strncmp(birth, "0", 1)) ? birth : g_strdup("-"));
-					gaim_notify_searchresults_row_add(results, row);
-					if (i == res_count - 1) {
-						g_free(info->search_form->last_uin);
-						info->search_form->last_uin = ggp_search_get_result(req, i, GG_PUBDIR50_UIN);
-					}
-				}
-
-				gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_CONTINUE, ggp_callback_show_next);
-				gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_ADD_BUDDY, ggp_callback_add_buddy);
-				if (info->searchresults_window == NULL) {
-					void *h = gaim_notify_searchresults(gc, _("Gadu-Gadu Public Directory"),
-											  _("Search results"), NULL, results, NULL, NULL);
-					info->searchresults_window = h;
-				} else {
-					gaim_notify_searchresults_new_rows(gc, results, info->searchresults_window, NULL);
-				}
-			}
+	switch (info->session->state) {
+		case GG_STATE_RESOLVING:
+			gaim_debug_info("gg", "GG_STATE_RESOLVING\n");
+			break;
+		case GG_STATE_CONNECTING_HUB:
+			gaim_debug_info("gg", "GG_STATE_CONNECTING_HUB\n");
+			break;
+		case GG_STATE_READING_DATA:
+			gaim_debug_info("gg", "GG_STATE_READING_DATA\n");
+			break;
+		case GG_STATE_CONNECTING_GG:
+			gaim_debug_info("gg", "GG_STATE_CONNECTING_GG\n");
+			break;
+		case GG_STATE_READING_KEY:
+			gaim_debug_info("gg", "GG_STATE_READING_KEY\n");
+			break;
+		case GG_STATE_READING_REPLY:
+			gaim_debug_info("gg", "GG_STATE_READING_REPLY\n");
 			break;
 		default:
-			gaim_debug_error("gg", "unsupported event type=%d\n", ev->type);
+			gaim_debug_error("gg", "unknown state = %d\n",
+					 info->session->state);
+		break;
+	}
+
+	if (!(ev = gg_watch_fd(info->session))) {
+		gaim_debug_error("gg", "login_handler: gg_watch_fd failed!\n");
+		gaim_connection_error(gc, _("Unable to read socket"));
+		return;
+	}
+	gaim_debug_info("gg", "login_handler: session->fd = %d\n", info->session->fd);
+	gaim_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
+			info->session->check, info->session->state);
+
+	gaim_input_remove(gc->inpa);
+
+	/** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */
+	gc->inpa = gaim_input_add(info->session->fd,
+				  (info->session->check == 1) ? GAIM_INPUT_WRITE
+							      : GAIM_INPUT_READ,
+				  ggp_async_login_handler, gc);
+
+	switch (ev->type) {
+		case GG_EVENT_NONE:
+			/* Nothing happened. */
+			gaim_debug_info("gg", "GG_EVENT_NONE\n");
+			break;
+		case GG_EVENT_CONN_SUCCESS:
+			gaim_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n");
+			gaim_input_remove(gc->inpa);
+			gc->inpa = gaim_input_add(info->session->fd,
+						  GAIM_INPUT_READ,
+						  ggp_callback_recv, gc);
+
+			/* gg_change_status(info->session, GG_STATUS_AVAIL); */
+			gaim_connection_set_state(gc, GAIM_CONNECTED);
+			ggp_buddylist_send(gc);
+			break;
+		case GG_EVENT_CONN_FAILED:
+			gaim_input_remove(gc->inpa);
+			gc->inpa = 0;
+			gaim_connection_error(gc, _("Connection failed."));
+			break;
+		default:
+			gaim_debug_error("gg", "strange event: %d\n", ev->type);
 			break;
 	}
 
@@ -985,7 +1267,8 @@
 /* }}} */
 
 /* static void ggp_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne) {{{ */
-static void ggp_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne)
+static void ggp_list_emblems(GaimBuddy *b, const char **se, const char **sw,
+					   const char **nw, const char **ne)
 {
 	GaimPresence *presence = gaim_buddy_get_presence(b);
 
@@ -1061,12 +1344,12 @@
 		g_free(tmp);
 
 		ret = g_strdup_printf("\n<b>%s:</b> %s: %s",
-							  _("Status"), name, text);
+				      _("Status"), name, text);
 
 		g_free(text);
 	} else {
 		ret = g_strdup_printf("\n<b>%s:</b> %s",
-							  _("Status"), name);
+				      _("Status"), name);
 	}
 
 	return ret;
@@ -1079,38 +1362,33 @@
 	GaimStatusType *type;
 	GList *types = NULL;
 
-	type = gaim_status_type_new_with_attrs(GAIM_STATUS_OFFLINE, "offline", _("Offline"),
-	                                       TRUE, TRUE, FALSE, "message", _("Message"),
-					       gaim_value_new(GAIM_TYPE_STRING), NULL);
+	type = gaim_status_type_new_with_attrs(GAIM_STATUS_OFFLINE, "offline",
+			_("Offline"), TRUE, TRUE, FALSE, "message", _("Message"),
+			gaim_value_new(GAIM_TYPE_STRING), NULL);
 	types = g_list_append(types, type);
 
-	type = gaim_status_type_new_with_attrs(GAIM_STATUS_AVAILABLE, "available", _("Online"),
-	                                       TRUE, TRUE, FALSE, "message", _("Message"),
-					       gaim_value_new(GAIM_TYPE_STRING), NULL);
+	type = gaim_status_type_new_with_attrs(GAIM_STATUS_AVAILABLE, "available",
+			_("Online"), TRUE, TRUE, FALSE, "message", _("Message"),
+			gaim_value_new(GAIM_TYPE_STRING), NULL);
 	types = g_list_append(types, type);
 
 	/*
 	 * Without this selecting Invisible as own status doesn't
 	 * work. It's not used and not needed to show status of buddies.
 	 */
-	type = gaim_status_type_new_with_attrs(GAIM_STATUS_HIDDEN, "invisible", _("Invisible"),
-					       TRUE, TRUE, FALSE, "message", _("Message"),
-					       gaim_value_new(GAIM_TYPE_STRING), NULL);
+	type = gaim_status_type_new_with_attrs(GAIM_STATUS_HIDDEN, "invisible",
+			_("Invisible"), TRUE, TRUE, FALSE, "message", _("Message"),
+			gaim_value_new(GAIM_TYPE_STRING), NULL);
 	types = g_list_append(types, type);
 
-	/* type = gaim_status_type_new_with_attrs(GAIM_STATUS_UNAVAILABLE, "not-available", "Not Available", */
-	/*                                        TRUE, TRUE, FALSE, "message", _("Message"),                */
-	/*                                        gaim_value_new(GAIM_TYPE_STRING), NULL);                   */
-	/* types = g_list_append(types, type);                                                               */
-
-	type = gaim_status_type_new_with_attrs(GAIM_STATUS_AWAY, "away", _("Busy"),
-					       TRUE, TRUE, FALSE, "message", _("Message"),
-					       gaim_value_new(GAIM_TYPE_STRING), NULL);
+	type = gaim_status_type_new_with_attrs(GAIM_STATUS_AWAY, "away",
+			_("Busy"), TRUE, TRUE, FALSE, "message", _("Message"),
+			gaim_value_new(GAIM_TYPE_STRING), NULL);
 	types = g_list_append(types, type);
 
-	type = gaim_status_type_new_with_attrs(GAIM_STATUS_HIDDEN, "blocked", _("Blocked"),
-					       TRUE, TRUE, FALSE, "message", _("Message"),
-					       gaim_value_new(GAIM_TYPE_STRING), NULL);
+	type = gaim_status_type_new_with_attrs(GAIM_STATUS_HIDDEN, "blocked",
+			_("Blocked"), TRUE, TRUE, FALSE, "message", _("Message"),
+			gaim_value_new(GAIM_TYPE_STRING), NULL);
 	types = g_list_append(types, type);
 
 	return types;
@@ -1126,13 +1404,17 @@
 	if (!GAIM_BLIST_NODE_IS_BUDDY(node))
 		return NULL;
 
-	act = gaim_blist_node_action_new(_("Add to chat"), ggp_bmenu_add_to_chat, NULL, NULL);
+	act = gaim_blist_node_action_new(_("Add to chat"),
+					 ggp_bmenu_add_to_chat, NULL, NULL);
 	m = g_list_append(m, act);
 
-	if (gaim_blist_node_get_bool(node, "blocked"))
-		act = gaim_blist_node_action_new(_("Unblock"), ggp_bmenu_block, NULL, NULL);
-	else
-		act = gaim_blist_node_action_new(_("Block"), ggp_bmenu_block, NULL, NULL);
+	if (gaim_blist_node_get_bool(node, "blocked")) {
+		act = gaim_blist_node_action_new(_("Unblock"),
+						 ggp_bmenu_block, NULL, NULL);
+	} else {
+		act = gaim_blist_node_action_new(_("Block"),
+						 ggp_bmenu_block, NULL, NULL);
+	}
 	m = g_list_append(m, act);
 
 	return m;
@@ -1155,26 +1437,26 @@
 }
 /* }}} */
 
-/* static void ggp_login(GaimAccount *account, GaimStatus *status) {{{ */
+/* static void ggp_login(GaimAccount *account) {{{ */
 static void ggp_login(GaimAccount *account)
 {
 	GaimConnection *gc = gaim_account_get_connection(account);
 	struct gg_login_params *glp = g_new0(struct gg_login_params, 1);
 	GGPInfo *info = g_new0(GGPInfo, 1);
 
-	/* Probably this should be move to some *_new() function. */
+	/* Probably this should be moved to *_new() function. */
 	info->session = NULL;
 	info->searchresults_window = NULL;
 	info->chats = NULL;
 	info->chats_count = 0;
+	info->token = NULL;
 
 	gc->proto_data = info;
 
 	glp->uin = ggp_get_uin(account);
 	glp->password = (char *)gaim_account_get_password(account);
 
-	glp->async = 0;
-	/* TODO: Set the status correctly here. */
+	glp->async = 1;
 	glp->status = GG_STATUS_AVAIL;
 	glp->tls = 0;
 
@@ -1184,13 +1466,8 @@
 		g_free(glp);
 		return;
 	}
-	gaim_debug_info("gg", "ggp_login: so far so good.\n");
-
-	gc->inpa = gaim_input_add(info->session->fd, GAIM_INPUT_READ, ggp_callback_recv, gc);
-
-	gg_change_status(info->session, GG_STATUS_AVAIL);
-	gaim_connection_set_state(gc, GAIM_CONNECTED);
-	ggp_buddylist_send(gc);
+	gc->inpa = gaim_input_add(info->session->fd, GAIM_INPUT_READ,
+				  ggp_async_login_handler, gc);
 }
 /* }}} */
 
@@ -1225,7 +1502,8 @@
 /* }}} */
 
 /* static int ggp_send_im(GaimConnection *gc, const char *who, const char *msg, GaimConvImFlags flags) {{{ */
-static int ggp_send_im(GaimConnection *gc, const char *who, const char *msg, GaimConvImFlags flags)
+static int ggp_send_im(GaimConnection *gc, const char *who, const char *msg,
+		       GaimConvImFlags flags)
 {
 	GGPInfo *info = gc->proto_data;
 	char *tmp;
@@ -1237,8 +1515,8 @@
 	tmp = charset_convert(msg, "UTF-8", "CP1250");
 
 	if (tmp != NULL && strlen(tmp) > 0) {
-		if (gg_send_message(info->session, GG_CLASS_CHAT, ggp_str_to_uin(who),
-					        (unsigned char *)tmp) < 0) {
+		if (gg_send_message(info->session, GG_CLASS_CHAT,
+				ggp_str_to_uin(who), (unsigned char *)tmp) < 0) {
 			return -1;
 		}
 	}
@@ -1284,7 +1562,8 @@
 
 	status_id = gaim_status_get_id(status);
 
-	gaim_debug_info("gg", "ggp_set_status: Requested status = %s\n", status_id);
+	gaim_debug_info("gg", "ggp_set_status: Requested status = %s\n",
+			status_id);
 
 	if (strcmp(status_id, "available") == 0) {
 		new_status = GG_STATUS_AVAIL;
@@ -1298,7 +1577,9 @@
 	} else {
 		new_status = GG_STATUS_AVAIL;
 		new_status_descr = GG_STATUS_AVAIL_DESCR;
-		gaim_debug_info("gg", "ggp_set_status: uknown status requested (status_id=%s)\n", status_id);
+		gaim_debug_info("gg",
+			"ggp_set_status: uknown status requested (status_id=%s)\n",
+			status_id);
 	}
 
 	msg = gaim_status_get_attr_string(status, "message");
@@ -1308,9 +1589,11 @@
 		gg_change_status(info->session, new_status);
 	} else {
 		char *tmp = charset_convert(msg, "UTF-8", "CP1250");
-		gaim_debug_info("gg", "ggp_set_status: msg != NULL. msg = %s\n", tmp);
-		gaim_debug_info("gg", "ggp_set_status: gg_change_status_descr() = %d\n",
-				gg_change_status_descr(info->session, new_status_descr, tmp));
+		gaim_debug_info("gg",
+			"ggp_set_status: msg != NULL. msg = %s\n", tmp);
+		gaim_debug_info("gg",
+			"ggp_set_status: gg_change_status_descr() = %d\n",
+			gg_change_status_descr(info->session, new_status_descr, tmp));
 		g_free(tmp);
 	}
 
@@ -1327,7 +1610,8 @@
 /* }}} */
 
 /* static void ggp_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) {{{ */
-static void ggp_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group)
+static void ggp_remove_buddy(GaimConnection *gc, GaimBuddy *buddy,
+						 GaimGroup *group)
 {
 	GGPInfo *info = gc->proto_data;
 
@@ -1355,7 +1639,7 @@
 
 		 if (chat != NULL && g_utf8_collate(chat->name, chat_name) == 0) {
 			 gaim_notify_error(gc, _("Chat error"),
-					 _("This chat name is already in use"), NULL);
+				 _("This chat name is already in use"), NULL);
 			 return;
 		 }
 	}
@@ -1397,7 +1681,8 @@
 	}
 
 	if (chat == NULL) {
-		gaim_debug_error("gg", "ggp_chat_send: Hm... that's strange. No such chat?\n");
+		gaim_debug_error("gg",
+			"ggp_chat_send: Hm... that's strange. No such chat?\n");
 		return -EINVAL;
 	}
 
@@ -1411,12 +1696,14 @@
 	}
 
 	msg = charset_convert(message, "UTF-8", "CP1250");
-	gg_send_message_confer(info->session, GG_CLASS_CHAT, count, uins, (unsigned char *)msg);
+	gg_send_message_confer(info->session, GG_CLASS_CHAT, count, uins,
+			       (unsigned char *)msg);
 	g_free(msg);
 	g_free(uins);
 
-	serv_got_chat_in(gc, id, gaim_account_get_username(gaim_connection_get_account(gc)),
-					 0, message, time(NULL));
+	serv_got_chat_in(gc, id,
+			 gaim_account_get_username(gaim_connection_get_account(gc)),
+			 0, message, time(NULL));
 
 	return 0;
 }
@@ -1441,63 +1728,11 @@
 static void ggp_register_user(GaimAccount *account)
 {
 	GaimConnection *gc = gaim_account_get_connection(account);
-	GaimRequestFields *fields;
-	GaimRequestFieldGroup *group;
-	GaimRequestField *field;
 	GGPInfo *info;
-	GGPToken *token;
-
-	struct gg_http *req;
-	struct gg_token *t;
-
-	gaim_debug_info("gg", "token: requested.\n");
-
-	if ((req = gg_token(0)) == NULL) {
-		gaim_connection_error(gc, _("Token Error: Unable to fetch the token.\n"));
-		return;
-	}
-	t = req->data;
-
-	info = g_new0(GGPInfo, 1);
-	gc->proto_data = info;
-
-	token = g_new0(GGPToken, 1);
-	token->token_id = g_strdup(t->tokenid);
-	info->register_token = token;
-
-	fields = gaim_request_fields_new();
-	group = gaim_request_field_group_new(NULL);
-	gaim_request_fields_add_group(fields, group);
 
-	field = gaim_request_field_string_new("email", _("e-Mail"), "", FALSE);
-	gaim_request_field_string_set_masked(field, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("password1", _("Password"), "", FALSE);
-	gaim_request_field_string_set_masked(field, TRUE);
-	gaim_request_field_group_add_field(group, field);
-
-	field = gaim_request_field_string_new("password2", _("Password (retype)"), "", FALSE);
-	gaim_request_field_string_set_masked(field, TRUE);
-	gaim_request_field_group_add_field(group, field);
+	info = gc->proto_data = g_new0(GGPInfo, 1);
 
-	field = gaim_request_field_string_new("token", _("Enter current token"), "", FALSE);
-	gaim_request_field_string_set_masked(field, FALSE);
-	gaim_request_field_group_add_field(group, field);
-
-	/* original size: 60x24 */
-	field = gaim_request_field_image_new("token_img", _("Current token"), req->body, req->body_size);
-	gaim_request_field_group_add_field(group, field);
-
-	gg_token_free(req);
-
-	gaim_request_fields(account,
-		_("Register New Gadu-Gadu Account"),
-		_("Register New Gadu-Gadu Account"),
-		_("Please, fill in the following fields"),
-		fields, _("OK"), G_CALLBACK(ggp_callback_register_account_ok),
-		_("Cancel"), G_CALLBACK(ggp_callback_register_account_cancel),
-		gc);
+	ggp_token_request(gc, ggp_register_user_dialog);
 }
 /* }}} */
 
@@ -1507,29 +1742,36 @@
 	GList *m = NULL;
 	GaimPluginAction *act;
 
-	act = gaim_plugin_action_new(_("Find buddies"), ggp_find_buddies);
+	act = gaim_plugin_action_new(_("Find buddies"),
+				     ggp_find_buddies);
 	m = g_list_append(m, act);
 
 	m = g_list_append(m, NULL);
 
-	act = gaim_plugin_action_new(_("Change password"), ggp_change_passwd);
+	act = gaim_plugin_action_new(_("Change password"),
+				     ggp_change_passwd);
 	m = g_list_append(m, act);
 
 	m = g_list_append(m, NULL);
 
-	act = gaim_plugin_action_new(_("Upload buddylist to Server"), ggp_action_buddylist_put);
+	act = gaim_plugin_action_new(_("Upload buddylist to Server"),
+				     ggp_action_buddylist_put);
 	m = g_list_append(m, act);
 
-	act = gaim_plugin_action_new(_("Download buddylist from Server"), ggp_action_buddylist_get);
+	act = gaim_plugin_action_new(_("Download buddylist from Server"),
+				     ggp_action_buddylist_get);
 	m = g_list_append(m, act);
 
-	act = gaim_plugin_action_new(_("Delete buddylist from Server"), ggp_action_buddylist_delete);
+	act = gaim_plugin_action_new(_("Delete buddylist from Server"),
+				     ggp_action_buddylist_delete);
 	m = g_list_append(m, act);
 
-	act = gaim_plugin_action_new(_("Save buddylist to file"), ggp_action_buddylist_save);
+	act = gaim_plugin_action_new(_("Save buddylist to file"),
+				     ggp_action_buddylist_save);
 	m = g_list_append(m, act);
 
-	act = gaim_plugin_action_new(_("Load buddylist from file"), ggp_action_buddylist_load);
+	act = gaim_plugin_action_new(_("Load buddylist from file"),
+				     ggp_action_buddylist_load);
 	m = g_list_append(m, act);
 
 	return m;
@@ -1540,62 +1782,62 @@
 static GaimPluginProtocolInfo prpl_info =
 {
 	OPT_PROTO_REGISTER_NOSCREENNAME,
-	NULL,					/* user_splits */
-	NULL,					/* protocol_options */
+	NULL,				/* user_splits */
+	NULL,				/* protocol_options */
 	NO_BUDDY_ICONS,			/* icon_spec */
 	ggp_list_icon,			/* list_icon */
 	ggp_list_emblems,		/* list_emblems */
 	ggp_status_text,		/* status_text */
 	ggp_tooltip_text,		/* tooltip_text */
 	ggp_status_types,		/* status_types */
-	ggp_blist_node_menu,	/* blist_node_menu */
+	ggp_blist_node_menu,		/* blist_node_menu */
 	ggp_chat_info,			/* chat_info */
-	NULL,					/* chat_info_defaults */
-	ggp_login,				/* login */
-	ggp_close,				/* close */
+	NULL,				/* chat_info_defaults */
+	ggp_login,			/* login */
+	ggp_close,			/* close */
 	ggp_send_im,			/* send_im */
-	NULL,					/* set_info */
-	NULL,					/* send_typing */
+	NULL,				/* set_info */
+	NULL,				/* send_typing */
 	ggp_get_info,			/* get_info */
 	ggp_set_status,			/* set_away */
-	NULL,					/* set_idle */
-	NULL,					/* change_passwd */
+	NULL,				/* set_idle */
+	NULL,				/* change_passwd */
 	ggp_add_buddy,			/* add_buddy */
-	NULL,					/* add_buddies */
+	NULL,				/* add_buddies */
 	ggp_remove_buddy,		/* remove_buddy */
-	NULL,					/* remove_buddies */
-	NULL,					/* add_permit */
-	NULL,					/* add_deny */
-	NULL,					/* rem_permit */
-	NULL,					/* rem_deny */
-	NULL,					/* set_permit_deny */
+	NULL,				/* remove_buddies */
+	NULL,				/* add_permit */
+	NULL,				/* add_deny */
+	NULL,				/* rem_permit */
+	NULL,				/* rem_deny */
+	NULL,				/* set_permit_deny */
 	ggp_join_chat,			/* join_chat */
-	NULL,					/* reject_chat */
+	NULL,				/* reject_chat */
 	ggp_get_chat_name,		/* get_chat_name */
-	NULL,					/* chat_invite */
-	NULL,					/* chat_leave */
-	NULL,					/* chat_whisper */
+	NULL,				/* chat_invite */
+	NULL,				/* chat_leave */
+	NULL,				/* chat_whisper */
 	ggp_chat_send,			/* chat_send */
 	ggp_keepalive,			/* keepalive */
 	ggp_register_user,		/* register_user */
-	NULL,					/* get_cb_info */
-	NULL,					/* get_cb_away */
-	NULL,					/* alias_buddy */
-	NULL,					/* group_buddy */
-	NULL,					/* rename_group */
-	NULL,					/* buddy_free */
-	NULL,					/* convo_closed */
-	NULL,					/* normalize */
-	NULL,					/* set_buddy_icon */
-	NULL,					/* remove_group */
-	NULL,					/* get_cb_real_name */
-	NULL,					/* set_chat_topic */
-	NULL,					/* find_blist_chat */
-	NULL,					/* roomlist_get_list */
-	NULL,					/* roomlist_cancel */
-	NULL,					/* roomlist_expand_category */
-	NULL,					/* can_receive_file */
-	NULL					/* send_file */
+	NULL,				/* get_cb_info */
+	NULL,				/* get_cb_away */
+	NULL,				/* alias_buddy */
+	NULL,				/* group_buddy */
+	NULL,				/* rename_group */
+	NULL,				/* buddy_free */
+	NULL,				/* convo_closed */
+	NULL,				/* normalize */
+	NULL,				/* set_buddy_icon */
+	NULL,				/* remove_group */
+	NULL,				/* get_cb_real_name */
+	NULL,				/* set_chat_topic */
+	NULL,				/* find_blist_chat */
+	NULL,				/* roomlist_get_list */
+	NULL,				/* roomlist_cancel */
+	NULL,				/* roomlist_expand_category */
+	NULL,				/* can_receive_file */
+	NULL				/* send_file */
 };
 /* }}} */
 
@@ -1662,8 +1904,10 @@
 {
 	GaimAccountOption *option;
 
-	option = gaim_account_option_string_new(_("Nickname"), "nick", _("Gadu-Gadu User"));
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = gaim_account_option_string_new(_("Nickname"),
+			"nick", _("Gadu-Gadu User"));
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+						   option);
 
 	my_protocol = plugin;
 
@@ -1673,5 +1917,4 @@
 
 GAIM_INIT_PLUGIN(gg, init_plugin, info);
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
-
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/gg.h	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/gg.h	Tue Nov 08 19:45:09 2005 +0000
@@ -26,6 +26,7 @@
 
 #include "lib/libgadu.h"
 #include "search.h"
+#include "connection.h"
 
 typedef struct
 {
@@ -34,9 +35,18 @@
 
 } GGPChat;
 
+typedef void (*GGPTokenCallback)(GaimConnection *);
+
 typedef struct
 {
-	char *token_id;
+	char *id;
+	char *data;
+	unsigned int size;
+
+	struct gg_http *req;
+	guint inpa;
+
+	GGPTokenCallback cb;
 
 } GGPToken;
 
@@ -44,8 +54,7 @@
 
 	struct gg_session *session;
 	GGPSearchForm *search_form;
-	GGPToken *register_token;
-	GGPToken *chpasswd_token;
+	GGPToken *token;
 	GList *chats;
 	void *searchresults_window;
 
@@ -57,4 +66,4 @@
 
 #endif /* _GAIM_GG_H */
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/lib/libgadu.c	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/lib/libgadu.c	Tue Nov 08 19:45:09 2005 +0000
@@ -1,4 +1,4 @@
-/* $Id: libgadu.c 13801 2005-09-14 19:10:39Z datallah $ */
+/* $Id: libgadu.c 14300 2005-11-08 19:45:09Z datallah $ */
 
 /*
  *  (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl>
@@ -81,9 +81,134 @@
 #ifdef __GNUC__
 __attribute__ ((unused))
 #endif
-= "$Id: libgadu.c 13801 2005-09-14 19:10:39Z datallah $";
+= "$Id: libgadu.c 14300 2005-11-08 19:45:09Z datallah $";
 #endif 
 
+#ifdef _WIN32
+/**
+ *  Deal with the fact that you can't select() on a win32 file fd.
+ *  This makes it practically impossible to tie into gaim's event loop.
+ *
+ *  -This is thanks to Tor Lillqvist.
+ *  XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu.
+ */
+static int
+socket_pipe (int *fds)
+{
+	SOCKET temp, socket1 = -1, socket2 = -1;
+	struct sockaddr_in saddr;
+	int len;
+	u_long arg;
+	fd_set read_set, write_set;
+	struct timeval tv;
+
+	temp = socket(AF_INET, SOCK_STREAM, 0);
+
+	if (temp == INVALID_SOCKET) {
+		goto out0;
+	}
+
+	arg = 1;
+	if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out0;
+	}
+
+	memset(&saddr, 0, sizeof(saddr));
+	saddr.sin_family = AF_INET;
+	saddr.sin_port = 0;
+	saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) {
+		goto out0;
+	}
+
+	if (listen(temp, 1) == SOCKET_ERROR) {
+		goto out0;
+	}
+
+	len = sizeof(saddr);
+	if (getsockname(temp, (struct sockaddr *)&saddr, &len)) {
+		goto out0;
+	}
+
+	socket1 = socket(AF_INET, SOCK_STREAM, 0);
+
+	if (socket1 == INVALID_SOCKET) {
+		goto out0;
+	}
+
+	arg = 1;
+	if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out1;
+	}
+
+	if (connect(socket1, (struct sockaddr  *)&saddr, len) != SOCKET_ERROR ||
+			WSAGetLastError() != WSAEWOULDBLOCK) {
+		goto out1;
+	}
+
+	FD_ZERO(&read_set);
+	FD_SET(temp, &read_set);
+
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+
+	if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) {
+		goto out1;
+	}
+
+	if (!FD_ISSET(temp, &read_set)) {
+		goto out1;
+	}
+
+	socket2 = accept(temp, (struct sockaddr *) &saddr, &len);
+	if (socket2 == INVALID_SOCKET) {
+		goto out1;
+	}
+
+	FD_ZERO(&write_set);
+	FD_SET(socket1, &write_set);
+
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+
+	if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) {
+		goto out2;
+	}
+
+	if (!FD_ISSET(socket1, &write_set)) {
+		goto out2;
+	}
+
+	arg = 0;
+	if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out2;
+	}
+
+	arg = 0;
+	if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) {
+		goto out2;
+	}
+
+	fds[0] = socket1;
+	fds[1] = socket2;
+
+	closesocket (temp);
+
+	return 0;
+
+out2:
+	closesocket (socket2);
+out1:
+	closesocket (socket1);
+out0:
+	closesocket (temp);
+	errno = EIO;            /* XXX */
+
+	return -1;
+}
+#endif
+
 /*
  * gg_libgadu_version()
  *
@@ -119,7 +244,7 @@
 		((x & (uint32_t) 0x0000ff00U) << 8) |
 		((x & (uint32_t) 0x00ff0000U) >> 8) |
 		((x & (uint32_t) 0xff000000U) >> 24));
-#endif		
+#endif
 }
 
 /*
@@ -417,7 +542,7 @@
 		return -1;
 	}
 
-	if (pipe(pipes) == -1) {
+	if (socket_pipe(pipes) == -1) {
 		gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
 		return -1;
 	}
--- a/src/protocols/gg/lib/libgadu.h	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/lib/libgadu.h	Tue Nov 08 19:45:09 2005 +0000
@@ -1,4 +1,4 @@
-/* $Id: libgadu.h 13801 2005-09-14 19:10:39Z datallah $ */
+/* $Id: libgadu.h 14300 2005-11-08 19:45:09Z datallah $ */
 
 /*
  *  (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl>
@@ -896,7 +896,7 @@
 
 int gg_resolve(int *fd, int *pid, const char *hostname);
 
-#ifdef __GNUC__
+#if defined __GNUC__ && !defined _WIN32
 char *gg_saprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
 #else
 char *gg_saprintf(const char *format, ...);
--- a/src/protocols/gg/search.c	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/search.c	Tue Nov 08 19:45:09 2005 +0000
@@ -57,7 +57,8 @@
 	gaim_debug_info("gg", "It's time to perform a search...\n");
 
 	if ((req = gg_pubdir50_new(GG_PUBDIR50_SEARCH)) == NULL) {
-		gaim_debug_error("gg", "ggp_bmenu_show_details: Unable to create req variable.\n");
+		gaim_debug_error("gg",
+			"ggp_bmenu_show_details: Unable to create req variable.\n");
 		return;
 	}
 
@@ -125,4 +126,4 @@
 /* }}} */
 
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/search.h	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/search.h	Tue Nov 08 19:45:09 2005 +0000
@@ -67,11 +67,11 @@
 /*
  * Return converted to the UTF-8 value of the specified field.
  *
- * @param res    Public directory look-up result
- * @param num    Id of the record
- * @param fileld Name of the field
+ * @param res    Public directory look-up result.
+ * @param num    Id of the record.
+ * @param fileld Name of the field.
  * 
- * @return UTF-8 encoded value of the field
+ * @return UTF-8 encoded value of the field.
  */
 char *
 ggp_search_get_result(gg_pubdir50_t res, int num, const char *field);
@@ -79,4 +79,4 @@
 
 #endif /* _GAIM_GG_SEARCH_H */
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/utils.c	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/utils.c	Tue Nov 08 19:45:09 2005 +0000
@@ -39,7 +39,8 @@
 	if (*text == '\0' || *tmp != '\0')
 		return 0;
 
-	if ((errno == ERANGE || (num == LONG_MAX || num == LONG_MIN)) || num > UINT_MAX || num < 0)
+	if ((errno == ERANGE || (num == LONG_MAX || num == LONG_MIN))
+	    || num > UINT_MAX || num < 0)
 		return 0;
 
 	return (uin_t) num;
@@ -55,10 +56,11 @@
 	if (locstr == NULL)
 		return NULL;
 
-	msg = g_convert_with_fallback(locstr, strlen(locstr), encdst, encsrc, "?", NULL, NULL, &err);
+	msg = g_convert_with_fallback(locstr, strlen(locstr), encdst, encsrc,
+				      "?", NULL, NULL, &err);
 	if (err != NULL) {
 		gaim_debug_error("gg", "Error converting from %s to %s: %s\n",
-						 encsrc, encdst, err->message);
+				 encsrc, encdst, err->message);
 		g_error_free(err);
 	}
 
@@ -96,4 +98,4 @@
 /* }}} */
 
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/src/protocols/gg/utils.h	Tue Nov 08 18:56:15 2005 +0000
+++ b/src/protocols/gg/utils.h	Tue Nov 08 19:45:09 2005 +0000
@@ -83,4 +83,4 @@
 
 #endif /* _GAIM_GG_UTILS_H */
 
-/* vim: set ts=4 sts=0 sw=4 noet: */
+/* vim: set ts=8 sts=0 sw=8 noet: */