diff -U 3 -H -B -d -i -r -N -- pristine/gaim-0.82.1/plugins/gaim-remote/Makefile.am patched-2/gaim-0.82.1/plugins/gaim-remote/Makefile.am
--- pristine/gaim-0.82.1/plugins/gaim-remote/Makefile.am	2004-09-06 02:40:35.000000000 -0400
+++ patched-2/gaim-0.82.1/plugins/gaim-remote/Makefile.am	2004-09-07 08:54:15.000000000 -0400
@@ -1,16 +1,20 @@
-grincludedir = $(includedir)/gaim
+grincludedir = $(includedir)/gaim/gaim-remote
 
 plugindir = $(libdir)/gaim
 
-lib_LTLIBRARIES = libgaim-remote.la
+lib_LTLIBRARIES = libgaim-remote.la libevogaimremote.la
 
 grinclude_HEADERS = \
 	remote-socket.h \
-	remote.h
+	remote.h \
+	evogaimremote.h
 
 libgaim_remote_la_SOURCES = remote-socket.c
 libgaim_remote_la_LIBADD = $(GLIB_LIBS)
 
+libevogaimremote_la_SOURCES = evogaimremote.c
+libevogaimremote_la_LIBADD = $(GLIB_LIBS) $(EVOLUTION_ADDRESSBOOK_LIBS) libgaim-remote.la
+
 gaim_remote_la_LDFLAGS = -module -avoid-version
 
 if PLUGINS
@@ -18,7 +22,7 @@
 plugin_LTLIBRARIES = gaim-remote.la
 
 gaim_remote_la_SOURCES = remote.c
-gaim_remote_la_LIBADD = libgaim-remote.la $(GLIB_LIBS)
+gaim_remote_la_LIBADD = libgaim-remote.la -lgthread-2.0 $(GLIB_LIBS)
 
 endif
 
@@ -28,5 +32,6 @@
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/plugins \
 	-I$(top_srcdir)/src \
+	$(EVOLUTION_ADDRESSBOOK_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(DEBUG_CFLAGS)
diff -U 3 -H -B -d -i -r -N -- pristine/gaim-0.82.1/plugins/gaim-remote/evogaimremote.c patched-2/gaim-0.82.1/plugins/gaim-remote/evogaimremote.c
--- pristine/gaim-0.82.1/plugins/gaim-remote/evogaimremote.c	1969-12-31 19:00:00.000000000 -0500
+++ patched-2/gaim-0.82.1/plugins/gaim-remote/evogaimremote.c	2004-09-07 08:54:15.000000000 -0400
@@ -0,0 +1,353 @@
+/*
+ * Remote control plugin for Gaim
+ *
+ * Copyright (C) 2004, Praveen Kumar <praveen9@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "evogaimremote.h"
+
+#define	MAX_IM_SLOTS	6
+
+typedef struct {
+	EContact *contact;
+	GRCallbackFunc callback;
+	gpointer data;
+	gint waitfor;
+	GList *buddylist;
+} GRQueryInfo;
+
+typedef struct {
+	GRQueryInfo *qinfo;
+	GIOChannel *channel;
+	guint inpa;
+} GRQuery;
+
+static struct {
+	EContactField  field;
+	gchar         *protocol_id;
+	gchar         *pretty_name;
+} 
+
+im_service [] =
+{
+	{ E_CONTACT_IM_AIM,	  "prpl-aim",		"AIM"       },
+	{ E_CONTACT_IM_JABBER,    "prpl-jabber",	"Jabber"    },
+	{ E_CONTACT_IM_YAHOO,     "prpl-yahoo",		"Yahoo"     },
+	{ E_CONTACT_IM_MSN,       "prpl-msn",		"MSN"       },
+	{ E_CONTACT_IM_ICQ,       "prpl-icq",		"ICQ"       },
+	{ E_CONTACT_IM_GROUPWISE, "prpl-novell",	"GroupWise" }
+};
+
+gboolean gaim_remote_read_response (GIOChannel *source, GIOCondition cond, gpointer data);
+void _gaim_remote_get_buddy_info_name (const char *screenname, const char *protocol_id, GRQueryInfo *qinfo);
+
+void gaim_remote_free_buddy_info (GRBuddyInfo *buddy)
+{
+	if (!buddy)
+		return;
+
+	if (buddy->name)
+		g_free(buddy->name);
+	if (buddy->alias)
+		g_free(buddy->alias);
+	if (buddy->server_alias)
+		g_free(buddy->server_alias);
+	if (buddy->icon)
+		g_free(buddy->icon);
+	if (buddy->protocol_id)
+		g_free(buddy->protocol_id);
+	
+	g_free(buddy);
+
+	return;
+}
+
+void gaim_remote_get_buddy_info (EContact *contact, GRCallbackFunc cbfunc, gpointer data)
+{
+	g_return_if_fail (contact != NULL);
+	g_return_if_fail (cbfunc != NULL);
+
+	GList *im_attr_list;
+	GList *l;
+    
+	gint   record_n;
+	gint   i;
+	gboolean found = FALSE;
+
+	for (record_n = 1, i = 0; i < G_N_ELEMENTS (im_service); i++) {
+		im_attr_list = e_contact_get_attributes (contact, im_service [i].field);
+		
+		if (g_list_length(im_attr_list) < 1)
+			continue;
+		
+		GRQueryInfo *qinfo = g_new(GRQueryInfo, 1);
+		g_object_ref(contact);
+		qinfo->contact = contact;
+		qinfo->callback = cbfunc;
+		qinfo->data = data;
+		qinfo->buddylist = NULL;
+		qinfo->waitfor = g_list_length(im_attr_list);
+
+		for (l = im_attr_list; l ; l = g_list_next (l)) {
+			EVCardAttribute *attr = l->data;
+			gchar           *im_name = e_vcard_attribute_get_value (attr);
+			
+			found = TRUE;
+			_gaim_remote_get_buddy_info_name(im_name, im_service[i].protocol_id, qinfo); 
+			record_n++;
+		}
+	}
+
+	/* If we could not find even one screen name from contact return an empty buddylist */
+	if (!found) {
+		g_object_ref (contact);
+		(* cbfunc)(contact, NULL, data);
+		g_object_unref (contact);
+	}
+		
+	return;
+}
+
+void gaim_remote_get_buddy_info_name (const char *screenname, const char *protocol, GRCallbackFunc cbfunc, gpointer data)
+{
+	g_return_if_fail (screenname != NULL);
+	g_return_if_fail (cbfunc != NULL);
+
+	GRQueryInfo *qinfo = g_new(GRQueryInfo, 1);
+	qinfo->contact = NULL;
+	qinfo->callback = cbfunc;
+	qinfo->data = data;
+	qinfo->waitfor = 1;
+
+	_gaim_remote_get_buddy_info_name (screenname, protocol, qinfo);
+}
+
+void _gaim_remote_get_buddy_info_name (const char *screenname, const char *protocol, GRQueryInfo *qinfo)
+{
+	/* Find the status of the user */
+	int fd = 0;
+	GaimRemotePacket *p = NULL;
+	
+	fd = gaim_remote_session_connect (0);
+	if (fd<0) {
+		qinfo->waitfor--;
+
+		if (!qinfo->waitfor) {
+			/* Call the callback function */
+			(* qinfo->callback)(qinfo->contact, NULL, qinfo->data);
+	
+			g_object_unref (qinfo->contact);
+			/* We are done with the query info struct delete it */
+			g_free(qinfo);
+		}
+		return;
+	}
+	GRQuery *query = g_new0(GRQuery, 1);
+	query->qinfo = qinfo;
+
+	p = gaim_remote_packet_new (CUI_TYPE_REMOTE, CUI_REMOTE_STATE);
+	gaim_remote_packet_append_string (p, screenname);
+	if (protocol)
+		gaim_remote_packet_append_string (p, protocol);
+	gaim_remote_session_send_packet (fd, p);
+
+	query->channel = g_io_channel_unix_new(fd);
+	query->inpa = g_io_add_watch (query->channel, G_IO_IN | G_IO_HUP | G_IO_ERR, gaim_remote_read_response, query);
+	g_io_channel_unref (query->channel);
+
+	gaim_remote_packet_free(p);
+}
+
+const char* gaim_remote_get_protocol (char *protocol_id)
+{
+	int i;
+	
+	if (!protocol_id)
+		return NULL;
+        
+	for (i = 0; i < G_N_ELEMENTS (im_service); i++) {
+		if (!strcmp(protocol_id, im_service [i].protocol_id))
+		{
+			return(im_service [i].pretty_name); 
+			break;
+		}
+	}
+	
+	return NULL;
+}
+
+gboolean gaim_remote_read_response (GIOChannel *source, GIOCondition cond, gpointer data)
+{
+	int fd = g_io_channel_unix_get_fd(source);
+
+	GError *error = NULL;
+	GRBuddyInfo *buddyinfo = NULL;
+	int i = 0;
+ 
+	GRQuery *query = (GRQuery *)data;
+	GRQueryInfo *qinfo = query->qinfo;
+	
+	if (!(cond & G_IO_IN))
+		goto shutdown_query;
+
+	GaimRemotePacket *response = gaim_remote_session_read_packet (fd);
+
+	if ((!response) || (response->numpackets != 9))
+		goto continue_loop;
+
+	/* Create GRBuddy info from response */
+	GaimRemotePacketData *packet;
+	GList *plist = g_list_first(response->packets);
+	buddyinfo = g_new(GRBuddyInfo, 1);
+
+	for (i = 0;  plist && (i < 9) ; i++, plist = g_list_next(plist)) {
+		packet = (GaimRemotePacketData *)plist->data;
+		switch(i) {
+			case 0:
+				buddyinfo->name = g_strndup (packet->data, packet->length);
+				break;
+			case 1:
+				buddyinfo->alias = g_strndup (packet->data, packet->length);
+				break;
+			case 2:
+				buddyinfo->server_alias = g_strndup (packet->data, packet->length);
+				break;
+			case 3:
+				buddyinfo->present = strtol (packet->data, NULL, 10);
+				break;
+			case 4:
+				buddyinfo->evil = strtol (packet->data, NULL, 10);
+				break;
+			case 5:
+				buddyinfo->signon = strtol (packet->data, NULL, 10);
+				break;
+			case 6:
+				buddyinfo->idle = strtol (packet->data, NULL, 10);
+				break;
+			case 7:
+				buddyinfo->icon = g_malloc (packet->length);
+				memcpy (buddyinfo->icon, packet->data, packet->length);
+				buddyinfo->ilen = packet->length;
+				break;
+			case 8:
+				buddyinfo->protocol_id = g_strndup (packet->data, packet->length);
+				break;
+			default:
+				break;
+			}	
+	}
+
+    continue_loop:
+	gaim_remote_packet_free (response);
+
+	if (!qinfo) {
+		if (buddyinfo)
+			gaim_remote_free_buddy_info (buddyinfo);
+		goto shutdown_query;
+	}
+	
+	/* Update waitfor */
+	qinfo->waitfor--;
+
+	if ((buddyinfo) && (j == 9) && (buddyinfo->present != 2)) { /* buddyinfo is valid and we know the buddy*/
+			qinfo->buddylist = g_list_append (qinfo->buddylist, buddyinfo);
+	} else if (buddyinfo)
+        	gaim_remote_free_buddy_info (buddyinfo);
+
+	if (qinfo->waitfor == 0) {
+		/* Call the callback function */
+		(* qinfo->callback)(qinfo->contact, qinfo->buddylist, qinfo->data);
+
+		g_object_unref(qinfo->contact);
+
+		/* We are done with the query info struct delete it */
+		g_free(qinfo);
+	}
+	
+    shutdown_query:
+	
+	/* Shutdown the channel */
+	g_io_channel_shutdown(query->channel, TRUE, &error);
+	if (error) {
+		g_error_free(error);
+		error = NULL;
+	}
+	g_source_remove(query->inpa);
+	g_free(query);
+
+	return FALSE;
+}
+
+void 
+gaim_remote_handle_aim_uri (char *uri)
+{
+        int fd = 0;
+        GaimRemotePacket *p = NULL;
+        fd = gaim_remote_session_connect(0);
+        if (fd<0) {
+                return;
+        }
+        p = gaim_remote_packet_new (CUI_TYPE_REMOTE, CUI_REMOTE_URI);
+        gaim_remote_packet_append_string (p, uri);
+        gaim_remote_session_send_packet (fd, p);
+        close (fd);
+        gaim_remote_packet_free (p);
+        return;
+}
+
+/* Copied from Gaim -- thanks to Gaim devs. */
+char *
+gaim_remote_seconds_to_string(guint secs)
+{
+        GString *gstr;
+        const char *prefix = "";
+        guint days, hrs, mins;
+
+	secs = time(NULL) - secs;
+        gstr = g_string_new("");
+
+        if (secs < 60)
+        {
+                g_string_append_printf (gstr, "%d %s", secs, (secs > 1) ? "seconds" : "second");
+                return g_string_free (gstr, FALSE);
+        }
+
+        days = secs / (60 * 60 * 24);
+        secs = secs % (60 * 60 * 24);
+        hrs  = secs / (60 * 60);
+        secs = secs % (60 * 60);
+        mins = secs / 60;
+	secs = secs % 60;
+        if (days > 0) {
+               g_string_append_printf (gstr, "%d %s", days, (days > 1) ? "days" : "day");
+               prefix = ", ";
+        }
+
+        if (hrs > 0) {
+                g_string_append_printf (gstr, "%s%d %s", prefix, hrs, (hrs > 0) ? "hours" : "hour");
+                prefix = ", ";
+        }
+        if (mins > 0) {
+		g_string_append_printf (gstr, "%s%d %s", prefix, mins, (mins > 0) ? "minutes" : "minute");
+        }
+	return g_string_free (gstr, FALSE);
+}
diff -U 3 -H -B -d -i -r -N -- pristine/gaim-0.82.1/plugins/gaim-remote/evogaimremote.h patched-2/gaim-0.82.1/plugins/gaim-remote/evogaimremote.h
--- pristine/gaim-0.82.1/plugins/gaim-remote/evogaimremote.h	1969-12-31 19:00:00.000000000 -0500
+++ patched-2/gaim-0.82.1/plugins/gaim-remote/evogaimremote.h	2004-09-07 08:54:15.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Remote control plugin for Gaim
+ *
+ * Copyright (C) 2004, Praveen Kumar <praveen9@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <gaim-remote/remote.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <libebook/e-contact.h>
+#include <libebook/e-book.h>
+
+/* This is a part of the gaim buddy structure returned in case of buddy related queries */
+
+typedef struct {
+	char *name;		/* The screen name of the buddy  */
+	char *alias;		/* The user-set alias of the buddy */
+	char *server_alias;	/* The server specified alias of the buddy */
+	int present;		/* = 0, buddy is offline; = 1, buddy is online; 
+				   = 2, buddy has recently signed on */
+	int evil;		/* the warning level */
+	long int signon;	/* the signon time */
+	int idle;		/* the idle time for buddy */
+	gpointer icon;		/* The icon data */
+	int ilen;		/* the icon data length  */
+	char *protocol_id;	/* the protocol -- this is the protocol_id
+				   in the GaimAccount struct */
+} GRBuddyInfo;
+
+typedef void (* GRCallbackFunc) (EContact *, GList *buddylist, gpointer data);
+
+/* This will find out all the IM accounts and return the buddy info for the first online 
+ * account/first offline account or NULL otherwise */ 		 
+void gaim_remote_get_buddy_info (EContact *contact, GRCallbackFunc cbfunc, gpointer data);
+
+/* Return the buddy info corresponding to screen name */
+void gaim_remote_get_buddy_info_name (const char *screenname, const char *protocol_id, GRCallbackFunc cbfunc, gpointer data);
+
+void gaim_remote_handle_aim_uri (char *uri);
+
+void gaim_remote_free_buddy_info (GRBuddyInfo *buddy);
+
+/* This will convert protocol id to string like from prpl-yahoo to "Yahoo" */
+const char *gaim_remote_get_protocol (char *protocol_id);
+
+char *gaim_remote_seconds_to_string (guint seconds);
diff -U 3 -H -B -d -i -r -N -- pristine/gaim-0.82.1/plugins/gaim-remote/remote-socket.c patched-2/gaim-0.82.1/plugins/gaim-remote/remote-socket.c
--- pristine/gaim-0.82.1/plugins/gaim-remote/remote-socket.c	2004-09-06 02:40:35.000000000 -0400
+++ patched-2/gaim-0.82.1/plugins/gaim-remote/remote-socket.c	2004-09-07 08:54:15.000000000 -0400
@@ -37,8 +37,18 @@
 void
 gaim_remote_session_send_packet(int fd, GaimRemotePacket *p)
 {
+	GaimRemotePacketData *packet;
+	GList *plist;
+
 	int len = sizeof(p->type) + sizeof(p->subtype) +
-	          sizeof(p->length) + p->length;
+	          sizeof(p->numpackets);
+
+	for (plist = p->packets; plist != NULL; plist = plist->next)
+	{
+		packet = (GaimRemotePacketData *)plist->data;
+		len += (sizeof(packet->length) + packet->length);
+	}
+	
 	char *pack = g_malloc(len);
 	char *a = pack;
 
@@ -46,59 +56,84 @@
 	a = a + sizeof(p->type);
 	memcpy (a, &(p->subtype), sizeof(p->subtype));
 	a = a + sizeof(p->subtype);
-	memcpy (a, &(p->length), sizeof(p->length));
-	a = a + sizeof(p->length);
-	memcpy (a, p->data, p->length);
-	write(fd, pack, len);
+	memcpy (a, &(p->numpackets), sizeof(p->numpackets));
+	a = a + sizeof(p->numpackets);
+	
+	for (plist = p->packets; plist != NULL; plist = plist->next)
+	{
+		packet = (GaimRemotePacketData *)plist->data;
+		memcpy (a, &(packet->length), sizeof(packet->length));
+		a = a + sizeof(packet->length);
+		memcpy (a, packet->data, packet->length);
+		a = a + packet->length;
+	}
+
+	if (write(fd, pack, len) == -1)
+		g_warning("There was an error sending the packet\n");
 	g_free(pack);
 }
 
 void
 gaim_remote_packet_append_string(GaimRemotePacket *p, char *str)
 {
-	int len = p->length + strlen(str);
+	GaimRemotePacketData *packet = g_new0(GaimRemotePacketData, 1);
+	
+	int len = strlen(str);
 	char *k = g_malloc(len);
 
-	memcpy(k, p->data, p->length);
-	memcpy(k + p->length, str, strlen(str));
+	memcpy(k, str, strlen(str));
 
-	if (p->data)
-		g_free(p->data);
+	packet->data = k;
+	packet->length = len;
 
-	p->data = k;
-	p->length = len;
+	p->packets = g_list_append(p->packets, packet);
+	p->numpackets ++;
+}
+
+void 
+gaim_remote_packet_append_int(GaimRemotePacket *p, long int ival)
+{
+	GaimRemotePacketData *packet = g_new0(GaimRemotePacketData, 1);
+	
+	char *str = g_strdup_printf("%ld", ival);
+	
+	packet->data = str;
+	packet->length = strlen(str);
+	
+	p->packets = g_list_append(p->packets, packet);
+	p->numpackets ++;
 }
 
 void
 gaim_remote_packet_append_char(GaimRemotePacket *p, char c)
 {
-	int len = p->length + sizeof(char);
+	GaimRemotePacketData *packet = g_new0(GaimRemotePacketData, 1);
+	
+	int len = sizeof(char);
 	char *k = g_malloc(len);
 
-	memcpy(k, p->data, p->length);
-	k[p->length] = c;
-
-	if (p->data)
-		g_free(p->data);
+	k[0] = c;
+	packet->data = k;
+	packet->length = len;
 
-	p->data = k;
-	p->length = len;
+	p->packets = g_list_append(p->packets, packet);
+	p->numpackets ++;
 }
 
 void
 gaim_remote_packet_append_raw(GaimRemotePacket *p, char *str, int len)
 {
-	int lent = p->length + len;
-	char *k = g_malloc(lent);
+	GaimRemotePacketData *packet = g_new0(GaimRemotePacketData, 1);
+	
+	char *k = g_malloc(len);
 
-	memcpy(k, p->data, p->length);
-	memcpy(k + p->length, str, len);
+	memcpy(k, str, len);
 
-	if (p->data)
-		g_free(p->data);
+	packet->data = k;
+	packet->length = len;
 
-	p->data = k;
-	p->length = lent;
+	p->packets = g_list_append(p->packets, packet);
+	p->numpackets ++;
 }
 
 GaimRemotePacket *
@@ -107,22 +142,34 @@
 	GaimRemotePacket *p = g_new0(GaimRemotePacket, 1);
 	p->type = type;
 	p->subtype = subtype;
-	p->length = 0;
-	p->data = NULL;
+	p->numpackets = 0;
+	p->packets = NULL;
 	return p;
 }
 
 void
 gaim_remote_packet_free(GaimRemotePacket *p)
 {
-	if (p->data)
-		g_free(p->data);
+	GList *plist;
+	GaimRemotePacketData *packet;
+
+	if (!p)
+		return;
+	for (plist = p->packets; plist != NULL; plist = plist->next)
+	{
+		packet = (GaimRemotePacketData *)plist->data;
+		if (packet->data)
+			g_free(packet->data);
+	}
+	
+	g_list_free(p->packets);
 	g_free(p);
 }
 
 GaimRemotePacket *
 gaim_remote_session_read_packet(int fd)
 {
+	int i;
 	GaimRemotePacket *p = g_new0(GaimRemotePacket, 1);
 	char *data = NULL;
 
@@ -136,22 +183,44 @@
 		return NULL;
 	}
 
-	if (!(read(fd, &p->length, sizeof(p->length)))) {
+	if (!(read(fd, &p->numpackets, sizeof(p->numpackets)))) {
 		g_free(p);
 		return NULL;
 	}
 	
-	if (p->length) {
-		data = g_malloc(p->length);
-
-		if (!(read(fd, data, p->length))) {
-			g_free(p);
-			return NULL;
+	if (p->numpackets > 0) {
+		for (i = 0; i < p->numpackets; i++)
+		{
+			GaimRemotePacketData *packet = g_new0(GaimRemotePacketData, 1);
+	
+			if (!(read(fd, &packet->length, sizeof(packet->length)))) {
+				g_free(packet);
+				gaim_remote_packet_free(p);
+				return NULL;
+			}
+	
+			if (packet->length != 0)
+			{	
+				data = g_malloc(packet->length);
+	
+				if (!(read(fd, data, packet->length))) {
+					g_free(packet);
+					gaim_remote_packet_free(p);
+					return NULL;
+				}
+				packet->data = g_malloc(packet->length + 1);
+				memcpy(packet->data, data, packet->length);
+				*(packet->data + packet->length) = '\0';
+				g_free(data);
+			}
+			else {
+				packet->data = NULL;
+			}
+			
+			p->packets = g_list_append(p->packets, packet);
 		}
 	}
 
-	p->data = data;
-
 	return p;
 }
 
diff -U 3 -H -B -d -i -r -N -- pristine/gaim-0.82.1/plugins/gaim-remote/remote-socket.h patched-2/gaim-0.82.1/plugins/gaim-remote/remote-socket.h
--- pristine/gaim-0.82.1/plugins/gaim-remote/remote-socket.h	2004-09-06 02:40:35.000000000 -0400
+++ patched-2/gaim-0.82.1/plugins/gaim-remote/remote-socket.h	2004-09-07 08:54:15.000000000 -0400
@@ -25,11 +25,16 @@
 
 typedef struct
 {
-	unsigned char type;
-	unsigned char subtype;
 	unsigned long length;
 	char *data;
+} GaimRemotePacketData;
 
+typedef struct
+{
+	unsigned char type;
+	unsigned char subtype;
+	unsigned long numpackets;
+	GList *packets;
 } GaimRemotePacket;
 
 void gaim_remote_session_send_packet(int fd, GaimRemotePacket *packet);
@@ -41,6 +46,7 @@
 void gaim_remote_packet_free(GaimRemotePacket *p);
 void gaim_remote_packet_append_string(GaimRemotePacket *p, char *str);
 void gaim_remote_packet_append_char(GaimRemotePacket *p, char c);
+void gaim_remote_packet_append_int(GaimRemotePacket *p, long int ival);
 void gaim_remote_packet_append_raw(GaimRemotePacket *p, char *str, int len);
 
 #endif /* _GAIM_SOCKET_H_ */
diff -U 3 -H -B -d -i -r -N -- pristine/gaim-0.82.1/plugins/gaim-remote/remote.c patched-2/gaim-0.82.1/plugins/gaim-remote/remote.c
--- pristine/gaim-0.82.1/plugins/gaim-remote/remote.c	2004-09-06 02:40:35.000000000 -0400
+++ patched-2/gaim-0.82.1/plugins/gaim-remote/remote.c	2004-09-07 08:54:15.000000000 -0400
@@ -37,6 +37,13 @@
 #include "prpl.h"
 #include "notify.h"
 
+
+/* Added fo libgremote */
+#include "account.h"
+#include "connection.h"
+#include "blist.h"
+#include "util.h"
+
 /* XXX */
 #include "away.h"
 #include "gtkconv.h"
@@ -48,17 +55,15 @@
 
 #define REMOTE_PLUGIN_ID "gtk-remote"
 
-struct UI {
-	GIOChannel *channel;
-	guint inpa;
-};
-
 #ifndef _WIN32
 static gint UI_fd = -1;
 static guint watcher = 0;
 #endif
 static int gaim_session = 0;
-static GSList *uis = NULL;
+
+gpointer start_remote_thread(gpointer data);
+gboolean wait_for_write (int fd);
+void send_packet (int fd, GaimRemotePacket *p);
 
 /* AIM URI's ARE FUN :-D */
 static const char *
@@ -300,7 +305,7 @@
 
 #ifndef _WIN32
 static void
-meta_handler(struct UI *ui, guchar subtype, gchar *data)
+meta_handler(int fd, guchar subtype, gchar *data)
 {
 	GaimRemotePacket *p;
 	GError *error = NULL;
@@ -308,25 +313,13 @@
 	case CUI_META_LIST:
 		break;
 	case CUI_META_QUIT:
-		while (uis) {
-			ui = uis->data;
-			uis = g_slist_remove(uis, ui);
-			g_io_channel_shutdown(ui->channel, TRUE, &error);
-			g_source_remove(ui->inpa);
-			g_free(ui);
-		}
 		g_timeout_add(0, gaim_core_quit_cb, NULL);
 		break;
 	case CUI_META_DETACH:
-		uis = g_slist_remove(uis, ui);
-		g_io_channel_shutdown(ui->channel, TRUE, &error);
-		g_source_remove(ui->inpa);
-		g_free(ui);
 		break;
 	case CUI_META_PING:
 		p = gaim_remote_packet_new(CUI_TYPE_META, CUI_META_ACK);
-		gaim_remote_session_send_packet(g_io_channel_unix_get_fd(ui->channel),
-										p);
+		send_packet (fd,p);
 		gaim_remote_packet_free(p);
 		break;
 	default:
@@ -340,7 +333,7 @@
 }
 
 static void
-plugin_handler(struct UI *ui, guchar subtype, gpointer data)
+plugin_handler(int fd, guchar subtype, gpointer data)
 {
 #ifdef GAIM_PLUGINS
 	guint id;
@@ -369,8 +362,23 @@
 #endif
 }
 
+gboolean
+handle_away (gpointer data)
+{
+	GSList* l;
+        const char* default_away_name = gaim_prefs_get_string("/core/away/default_message");
+
+        for(l = away_messages; l; l = l->next) {
+            if(!strcmp(default_away_name, ((struct away_message *)l->data)->name)) {
+                do_away_message(NULL, l->data);
+                break;
+            }
+        }
+	return FALSE;
+}
+
 static void
-user_handler(struct UI *ui, guchar subtype, gchar *data)
+user_handler(int fd, guchar subtype, gchar *data)
 {
 	guint id;
 	GaimAccount *account;
@@ -396,17 +404,7 @@
 		/* don't need to do anything here because the UI will get updates from other handlers */
 		break;
        case CUI_USER_AWAY:
-                {
-                    GSList* l;
-                    const char* default_away_name = gaim_prefs_get_string("/core/away/default_message");
-
-                    for(l = away_messages; l; l = l->next) {
-                        if(!strcmp(default_away_name, ((struct away_message *)l->data)->name)) {
-                            do_away_message(NULL, l->data);
-                            break;
-                        }
-                    }
-                }
+		g_timeout_add (1, handle_away, NULL);
                 break;
        case CUI_USER_BACK:
                 do_im_back(NULL, NULL);
@@ -419,7 +417,7 @@
 }
 
 static void
-message_handler(struct UI *ui, guchar subtype, gchar *data)
+message_handler(int fd, guchar subtype, gchar *data)
 {
 	switch (subtype) {
 	case CUI_MESSAGE_LIST:
@@ -467,33 +465,32 @@
 	}
 }
 
-static gint
-gaim_recv(GIOChannel *source, gchar *buf, gint len)
+gboolean 
+handle_uri (gpointer data)
 {
-	gint total = 0;
-	guint cur;
-
-	GError *error = NULL;
-
-	while (total < len) {
-		if (g_io_channel_read_chars(source, buf + total, len - total, (gsize *) &cur, &error) != G_IO_STATUS_NORMAL) {
-			if (error)
-				g_error_free(error);
-			return -1;
-		}
-		if (cur == 0)
-			return total;
-		total += cur;
-	}
-
-	return total;
+	const char *resp;
+	resp = gaim_remote_handle_uri((char *)data);
+	return FALSE;
 }
 
 static void
-remote_handler(struct UI *ui, guchar subtype, gchar *data, int len)
+remote_handler(int fd, guchar subtype, GaimRemotePacket *p_in)
 {
-	const char *resp;
 	char *send;
+	char *protocol_id = NULL;
+	char *protocol_req = NULL;
+	
+	GList *connections = NULL;
+	GaimAccount *account = NULL;
+	GaimConnection *connection = NULL;
+	GaimRemotePacket *p = NULL;
+	GaimBuddy *buddy = NULL;
+	
+	GaimRemotePacketData *pd = g_list_first(p_in->packets)->data;
+	gchar *data = pd->data;
+	int len = pd->length;
+
+
 	switch (subtype) {
 	case CUI_REMOTE_CONNECTIONS:
 		break;
@@ -501,10 +498,72 @@
 		send = g_malloc(len + 1);
 		memcpy(send, data, len);
 		send[len] = 0;
-		resp = gaim_remote_handle_uri(send);
+		printf ("The uri is %s\n", send);
+		g_timeout_add (1, handle_uri, send);
 		g_free(send);
 		/* report error */
 		break;
+	case CUI_REMOTE_STATE:
+		/* Check if we have also got a request for checking protocol id */
+		if (g_list_length (p_in->packets) == 2) {
+			pd = g_list_last(p_in->packets)->data;
+			protocol_req = pd->data;
+		}
+
+		for (connections = gaim_connections_get_all(); connections != NULL; connections = connections->next) {
+			connection = (GaimConnection *)connections->data;
+			account = gaim_connection_get_account(connection);
+			buddy = gaim_find_buddy(account, data);
+			if (buddy != NULL) {
+				protocol_id = g_strdup (gaim_account_get_protocol_id(account));
+				if (!strcmp(protocol_id, "prpl-oscar")) {
+					g_free (protocol_id);
+					GaimPluginProtocolInfo *prpl_info;
+					prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(connection->prpl);
+					
+					if (!strcmp("aim", prpl_info->list_icon(account, buddy)))
+						protocol_id = g_strdup ("prpl-aim");
+					else
+						protocol_id = g_strdup ("prpl-icq");
+				}
+					
+				if (!protocol_req || (protocol_req && !strcmp(protocol_id, protocol_req)))
+					break;
+				else
+					buddy = NULL;
+			}
+		}
+		
+		p = gaim_remote_packet_new(CUI_TYPE_REMOTE, CUI_REMOTE_STATE);
+		gaim_remote_packet_append_string(p, data);
+		if (buddy) {
+			if (buddy->alias)
+				gaim_remote_packet_append_string(p, buddy->alias);
+			else
+				gaim_remote_packet_append_string(p, "");
+			if (buddy->server_alias)
+				gaim_remote_packet_append_string(p, buddy->server_alias);
+			else
+				gaim_remote_packet_append_string(p, "");
+			gaim_remote_packet_append_int(p, buddy->present);
+			gaim_remote_packet_append_int(p, buddy->evil);
+			gaim_remote_packet_append_int(p, buddy->signon);
+			gaim_remote_packet_append_int(p, buddy->idle);
+			if (buddy->icon && buddy->icon->data)
+				gaim_remote_packet_append_raw(p, buddy->icon->data, buddy->icon->len);
+			else
+				gaim_remote_packet_append_string(p, "");
+			if (protocol_id)
+				gaim_remote_packet_append_string(p, protocol_id);
+			else
+				gaim_remote_packet_append_string(p, "");
+		}
+		send_packet(fd,p);
+
+		gaim_remote_packet_free(p);
+		if (protocol_id)
+			g_free (protocol_id);
+		break;
 	default:
 		gaim_debug(GAIM_DEBUG_WARNING, "cui",
 				   "Unhandled remote subtype %d\n", subtype);
@@ -513,84 +572,23 @@
 }
 
 static gboolean
-UI_readable(GIOChannel *source, GIOCondition cond, gpointer data)
+UI_readable(int fd, GaimRemotePacket *p)
 {
-	struct UI *ui = data;
-
-	gchar type;
-	gchar subtype;
-	gint len;
-
-	GError *error = NULL;
-
-	gchar *in;
-
-	/* no byte order worries! this'll change if we go to TCP */
-	if (gaim_recv(source, &type, sizeof(type)) != sizeof(type)) {
-		gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n");
-		uis = g_slist_remove(uis, ui);
-		g_io_channel_shutdown(ui->channel, TRUE, &error);
-		if(error) {
-			g_error_free(error);
-			error = NULL;
-		}
-		g_source_remove(ui->inpa);
-		g_free(ui);
-		return FALSE;
-	}
-
-	if (gaim_recv(source, &subtype, sizeof(subtype)) != sizeof(subtype)) {
-		gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n");
-		uis = g_slist_remove(uis, ui);
-		g_io_channel_shutdown(ui->channel, TRUE, &error);
-		if(error) {
-			g_error_free(error);
-			error = NULL;
-		}
-		g_source_remove(ui->inpa);
-		g_free(ui);
-		return FALSE;
-	}
-
-	if (gaim_recv(source, (gchar *)&len, sizeof(len)) != sizeof(len)) {
-		gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n");
-		uis = g_slist_remove(uis, ui);
-		g_io_channel_shutdown(ui->channel, TRUE, &error);
-		if(error) {
-			g_error_free(error);
-			error = NULL;
-		}
-		g_source_remove(ui->inpa);
-		g_free(ui);
-		return FALSE;
-	}
-
-	if (len) {
-		in = g_new0(gchar, len);
-		if (gaim_recv(source, in, len) != len) {
-			gaim_debug(GAIM_DEBUG_ERROR, "cui", "UI has abandoned us!\n");
-			uis = g_slist_remove(uis, ui);
-			g_io_channel_shutdown(ui->channel, TRUE, &error);
-			if(error) {
-				g_error_free(error);
-				error = NULL;
-			}
-			g_source_remove(ui->inpa);
-			g_free(ui);
-			return FALSE;
-		}
-	} else
-		in = NULL;
+	gchar type = p->type;
+	gchar subtype = p->subtype;
 
+	GaimRemotePacketData *pd = g_list_first(p->packets)->data;
+	gchar *in = pd->data;
+	
 	switch (type) {
 		case CUI_TYPE_META:
-			meta_handler(ui, subtype, in);
+			meta_handler(fd, subtype, in);
 			break;
 		case CUI_TYPE_PLUGIN:
-			plugin_handler(ui, subtype, in);
+			plugin_handler(fd, subtype, in);
 			break;
 		case CUI_TYPE_USER:
-			user_handler(ui, subtype, in);
+			user_handler(fd, subtype, in);
 			break;
 			/*
 		case CUI_TYPE_CONN:
@@ -601,7 +599,7 @@
 			break;
 			*/
 		case CUI_TYPE_MESSAGE:
-			message_handler(ui, subtype, in);
+			message_handler(fd, subtype, in);
 			break;
 			/*
 		case CUI_TYPE_CHAT:
@@ -609,7 +607,7 @@
 			break;
 			*/   
 	        case CUI_TYPE_REMOTE:
-			remote_handler(ui, subtype, in, len);
+			remote_handler(fd, subtype, p);
 			break; 
         default:
 			gaim_debug(GAIM_DEBUG_WARNING, "cui",
@@ -617,8 +615,7 @@
 			break;
 	}
 
-	if (in)
-		g_free(in);
+	gaim_remote_packet_free(p);
 	return TRUE;
 }
 
@@ -629,20 +626,61 @@
 	guint len = sizeof(saddr);
 	gint fd;
 
-	struct UI *ui;
-
 	if ((fd = accept(UI_fd, (struct sockaddr *)&saddr, &len)) == -1)
 		return FALSE;
 
-	ui = g_new0(struct UI, 1);
-	uis = g_slist_append(uis, ui);
+	if (g_thread_create(start_remote_thread, GINT_TO_POINTER(fd), FALSE, NULL) != NULL)
+		return TRUE;
+	else
+		return FALSE;
+}
 
-	ui->channel = g_io_channel_unix_new(fd);
-	ui->inpa = g_io_add_watch(ui->channel, G_IO_IN | G_IO_HUP | G_IO_ERR, UI_readable, ui);
-	g_io_channel_unref(ui->channel);
+void send_packet (int fd, GaimRemotePacket *p) 
+{
+        fd_set wfds;
+        struct timeval tv;
+        int retval;
 
-	gaim_debug(GAIM_DEBUG_MISC, "cui", "Got one\n");
-	return TRUE;
+        FD_ZERO(&wfds);
+        FD_SET(fd, &wfds);
+        
+	/* Wait up to five seconds. */
+        tv.tv_sec = 300;
+        tv.tv_usec = 0;
+
+        retval = select(fd+1, NULL, &wfds, NULL, &tv);
+
+        if (retval == 1)
+		gaim_remote_session_send_packet (fd, p);
+}
+
+gpointer
+start_remote_thread(gpointer data)
+{
+	int fd = GPOINTER_TO_INT(data);
+
+	fd_set rfds;
+	struct timeval tv;
+	int retval;
+	
+	GaimRemotePacket *p;
+
+	FD_ZERO(&rfds);
+	FD_SET(fd, &rfds);
+	
+	/* Wait up to five seconds. */
+	tv.tv_sec = 300;
+	tv.tv_usec = 0;
+
+	retval = select(fd+1, &rfds, NULL, NULL, &tv);
+
+	if (retval == 1) {
+		p = gaim_remote_session_read_packet(fd);
+		UI_readable(fd, p);
+	}
+	close(fd);
+
+	return NULL;	
 }
 
 static gint
@@ -693,6 +731,13 @@
 		return FALSE;
 	}
 
+	g_thread_init(NULL);
+	
+	/* Block SIGPIPE */
+	sigset_t sig_to_block;
+	sigaddset(&sig_to_block, SIGPIPE);
+	pthread_sigmask(SIG_BLOCK, &sig_to_block, NULL); 
+
 	channel = g_io_channel_unix_new(UI_fd);
 	watcher = g_io_add_watch(channel, G_IO_IN, socket_readable, NULL);
 	g_io_channel_unref(channel);
