? a.txt
? b.txt
? ft-131105.patch
? ft-161105.patch
? ft.patch
? libgossip/a.txt
? libgossip/b.txt
? protocols/jabber/ft.patch
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gossip/ChangeLog,v
retrieving revision 1.585
diff -u -r1.585 ChangeLog
--- ChangeLog	13 Nov 2005 11:20:30 -0000	1.585
+++ ChangeLog	16 Nov 2005 21:45:26 -0000
@@ -1,3 +1,15 @@
+2005-11-16  Martyn Russell  <martyn@imendio.com>
+
+	* protocols/jabber/gossip-jabber.c (jabber_setup): 
+	- Use the FULL JID instead of a JID without the resource.  We
+	needed this in so many places.
+	(jabber_get_contact_from_jid): 
+	- Now all contacts have their FULL JID 
+
+	* protocols/jabber/gossip-jabber-chatrooms.c
+	(jabber_chatrooms_chatroom_new): 
+	- Now using a ref from own contact on the GossipJabber object.
+
 2005-11-13  Martyn Russell  <martyn@imendio.com>
 
 	* configure.ac: 
@@ -28,6 +40,7 @@
 	- Add Help section using Gnome Help (patch from Brian Pepple).
 	- Fixes bug #155140 (Brian Pepple).
 
+>>>>>>> 1.584
 2005-11-05  Martyn Russell  <martyn@imendio.com>
 
 	* libgossip/gossip-session.[ch]:
Index: libgossip/Makefile.am
===================================================================
RCS file: /cvs/gnome/gossip/libgossip/Makefile.am,v
retrieving revision 1.11
diff -u -r1.11 Makefile.am
--- libgossip/Makefile.am	18 Sep 2005 19:10:43 -0000	1.11
+++ libgossip/Makefile.am	16 Nov 2005 21:45:26 -0000
@@ -1,47 +1,51 @@
-AM_CPPFLAGS =                                             \
-	-I.                                               \
-	-I$(top_srcdir)                                   \
-	-DPROTOCOL_DIR=\""$(libdir)/gossip/protocols"\"   \
+AM_CPPFLAGS =                                           \
+	-I.                                             \
+	-I$(top_srcdir)                                 \
+	-DPROTOCOL_DIR=\""$(libdir)/gossip/protocols"\" \
 	-DDTDDIR=\"$(datadir)/gossip\"			\
-	-I$(top_srcdir)/protocols/jabber                  \
+	-I$(top_srcdir)/protocols/jabber                \
 	$(LIBGOSSIP_CFLAGS)
 
 noinst_LTLIBRARIES = libgossip.la
 
-libgossip_la_SOURCES =             \
-	gossip-account.c           \
-	gossip-account-manager.c   \
-	gossip-chatroom-provider.c \
-	gossip-contact.c           \
-	gossip-event.c             \
-	gossip-event-manager.c     \
-	gossip-message.c           \
-	gossip-presence.c          \
-	gossip-protocol.c          \
-	gossip-session.c           \
-	gossip-time.c              \
-	gossip-utils.c             \
-	gossip-vcard.c             \
-	gossip-version-info.c      \
-	libgossip-marshal-main.c   \
-	gossip-account.h           \
-	gossip-account-manager.h   \
-	gossip-async.h             \
-	gossip-chatroom-provider.h \
-	gossip-contact.h           \
-	gossip-event.h             \
-	gossip-event-manager.h     \
-	gossip-message.h           \
-	gossip-presence.h          \
-	gossip-protocol.h          \
-	gossip-session.h           \
-	gossip-time.h              \
-	gossip-vcard.h             \
-	gossip-version-info.h      \
-	gossip-utils.h
+libgossip_la_SOURCES =             			\
+	gossip-account.c           			\
+	gossip-account.h           			\
+	gossip-account-manager.c   			\
+	gossip-account-manager.h   			\
+	gossip-async.h             			\
+	gossip-chatroom-provider.c 			\
+	gossip-chatroom-provider.h 			\
+	gossip-contact.c           			\
+	gossip-contact.h           			\
+	gossip-event.c             			\
+	gossip-event.h             			\
+	gossip-event-manager.c     			\
+	gossip-event-manager.h     			\
+	gossip-ft.c		 			\
+	gossip-ft.h 					\
+	gossip-ft-provider.c	 			\
+	gossip-ft-provider.h 				\
+	gossip-message.c           			\
+	gossip-message.h           			\
+	gossip-presence.c          			\
+	gossip-presence.h          			\
+	gossip-protocol.c          			\
+	gossip-protocol.h          			\
+	gossip-session.c           			\
+	gossip-session.h           			\
+	gossip-time.c              			\
+	gossip-time.h              			\
+	gossip-utils.c             			\
+	gossip-utils.h					\
+	gossip-vcard.c             			\
+	gossip-vcard.h             			\
+	gossip-version-info.c      			\
+	gossip-version-info.h      			\
+	libgossip-marshal-main.c
 
-libgossip_la_LIBADD =              \
-	$(LIBGOSSIP_LIBS)          \
+libgossip_la_LIBADD =              			\
+	$(LIBGOSSIP_LIBS)          			\
 	$(top_builddir)/protocols/jabber/libgossip-jabber.la
 
 libgossipincludedir = $(includedir)/gossip/
Index: libgossip/gossip-event.h
===================================================================
RCS file: /cvs/gnome/gossip/libgossip/gossip-event.h,v
retrieving revision 1.2
diff -u -r1.2 gossip-event.h
--- libgossip/gossip-event.h	30 Dec 2004 16:26:58 -0000	1.2
+++ libgossip/gossip-event.h	16 Nov 2005 21:45:26 -0000
@@ -43,10 +43,9 @@
 
 typedef enum {
         GOSSIP_EVENT_NEW_MESSAGE,
-        GOSSIP_EVENT_UNFOCUSED_MESSAGE,
 	GOSSIP_EVENT_SUBSCRIPTION_REQUEST,
-	GOSSIP_EVENT_TYPING,
 	GOSSIP_EVENT_SERVER_MESSAGE,
+	GOSSIP_EVENT_FILE_TRANSFER_REQUEST,
 	GOSSIP_EVENT_ERROR
 } GossipEventType;
 
Index: libgossip/gossip-ft-provider.c
===================================================================
RCS file: libgossip/gossip-ft-provider.c
diff -N libgossip/gossip-ft-provider.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgossip/gossip-ft-provider.c	16 Nov 2005 21:45:26 -0000
@@ -0,0 +1,163 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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 <config.h>
+
+#include "libgossip-marshal.h"
+
+#include "gossip-contact.h"
+#include "gossip-ft-provider.h"
+
+static void  ft_provider_base_init (gpointer g_class);
+
+enum {
+	FT_REQUEST,
+	FT_CANCELLED,
+	FT_ERROR,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+GType
+gossip_ft_provider_get_type (void)
+{
+	static GType type = 0;
+
+	if (!type) {
+		static const GTypeInfo info =
+		{
+			sizeof (GossipFTProviderIface),
+			ft_provider_base_init,       
+			NULL,                           
+			NULL,
+			NULL,                          
+			NULL,                          
+			0,
+			0,                              
+			NULL
+		};
+
+		type = g_type_register_static (G_TYPE_INTERFACE, 
+					       "GossipFTProvider",
+					       &info, 0);
+
+		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+	}
+	
+	return type;
+}
+
+static void
+ft_provider_base_init (gpointer g_class)
+{
+	static gboolean initialized = FALSE;
+
+	if (!initialized) {
+		signals[FT_REQUEST] =
+			g_signal_new ("file-transfer-request",
+				      G_TYPE_FROM_CLASS (g_class),
+				      G_SIGNAL_RUN_LAST,
+				      0,
+				      NULL, NULL,
+				      libgossip_marshal_VOID__OBJECT,
+				      G_TYPE_NONE,
+				      1, GOSSIP_TYPE_FT);
+
+		signals[FT_CANCELLED] =
+			g_signal_new ("file-transfer-cancelled",
+				      G_TYPE_FROM_CLASS (g_class),
+				      G_SIGNAL_RUN_LAST,
+				      0,
+				      NULL, NULL,
+				      libgossip_marshal_VOID__INT,
+				      G_TYPE_NONE,
+				      1, G_TYPE_INT);
+
+		signals[FT_ERROR] =
+			g_signal_new ("file-transfer-error",
+				      G_TYPE_FROM_CLASS (g_class),
+				      G_SIGNAL_RUN_LAST,
+				      0,
+				      NULL, NULL,
+				      libgossip_marshal_VOID__OBJECT_POINTER,
+				      G_TYPE_NONE,
+				      2, GOSSIP_TYPE_FT, G_TYPE_POINTER);
+
+		initialized = TRUE;
+	}
+}
+
+GossipFTId
+gossip_ft_provider_send (GossipFTProvider *provider,
+			 GossipContact    *contact,
+			 const gchar      *file)
+{
+	g_return_val_if_fail (GOSSIP_IS_FT_PROVIDER (provider), 0);
+	g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), 0);
+	g_return_val_if_fail (file != NULL, 0);
+
+	if (GOSSIP_FT_PROVIDER_GET_IFACE (provider)->send) {
+		return GOSSIP_FT_PROVIDER_GET_IFACE (provider)->send (provider,
+								      contact,
+								      file);
+	}
+
+	return 0;
+}
+
+void
+gossip_ft_provider_cancel (GossipFTProvider *provider,
+			   GossipFTId        id)
+{
+	g_return_if_fail (GOSSIP_IS_FT_PROVIDER (provider));
+	g_return_if_fail (id > 0);
+
+	if (GOSSIP_FT_PROVIDER_GET_IFACE (provider)->cancel) {
+		GOSSIP_FT_PROVIDER_GET_IFACE (provider)->cancel (provider,
+								 id);
+	}
+}
+
+void
+gossip_ft_provider_accept (GossipFTProvider *provider,
+			   GossipFTId        id)
+{
+	g_return_if_fail (GOSSIP_IS_FT_PROVIDER (provider));
+	g_return_if_fail (id > 0);
+
+	if (GOSSIP_FT_PROVIDER_GET_IFACE (provider)->accept) {
+		GOSSIP_FT_PROVIDER_GET_IFACE (provider)->accept (provider,
+								 id);
+	}
+}
+
+void
+gossip_ft_provider_decline (GossipFTProvider *provider,
+			    GossipFTId        id)
+{
+	g_return_if_fail (GOSSIP_IS_FT_PROVIDER (provider));
+	g_return_if_fail (id > 0);
+
+	if (GOSSIP_FT_PROVIDER_GET_IFACE (provider)->decline) {
+		GOSSIP_FT_PROVIDER_GET_IFACE (provider)->decline (provider,
+								  id);
+	}
+}
Index: libgossip/gossip-ft-provider.h
===================================================================
RCS file: libgossip/gossip-ft-provider.h
diff -N libgossip/gossip-ft-provider.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgossip/gossip-ft-provider.h	16 Nov 2005 21:45:26 -0000
@@ -0,0 +1,68 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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.
+ */
+
+#ifndef __GOSSIP_FT_PROVIDER_H__
+#define __GOSSIP_FT_PROVIDER_H__
+
+#include <glib-object.h>
+
+#include "gossip-ft.h"
+#include "gossip-contact.h"
+
+#define GOSSIP_TYPE_FT_PROVIDER           (gossip_ft_provider_get_type ())
+#define GOSSIP_FT_PROVIDER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOSSIP_TYPE_FT_PROVIDER, GossipFTProvider))
+#define GOSSIP_IS_FT_PROVIDER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOSSIP_TYPE_FT_PROVIDER))
+#define GOSSIP_FT_PROVIDER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GOSSIP_TYPE_FT_PROVIDER, GossipFTProviderIface))
+
+
+typedef struct _GossipFTProvider      GossipFTProvider;
+typedef struct _GossipFTProviderIface GossipFTProviderIface;
+
+struct _GossipFTProviderIface {
+	GTypeInterface g_iface;
+
+	/* Virtual Table */
+	GossipFTId (*send)    (GossipFTProvider *provider,
+			       GossipContact    *contact,
+			       const gchar      *file);
+	void       (*cancel)  (GossipFTProvider *provider,
+			       GossipFTId        id);
+	void       (*accept)  (GossipFTProvider *provider,
+			       GossipFTId        id);
+	void       (*decline) (GossipFTProvider *provider,
+			       GossipFTId        id);
+};
+
+
+GType      gossip_ft_provider_get_type (void) G_GNUC_CONST;
+
+
+GossipFTId gossip_ft_provider_send     (GossipFTProvider *provider,
+				        GossipContact    *contact,
+				        const gchar      *file);
+void       gossip_ft_provider_cancel   (GossipFTProvider *provider,
+				        GossipFTId        id);
+void       gossip_ft_provider_accept   (GossipFTProvider *provider,
+				        GossipFTId        id);
+void       gossip_ft_provider_decline  (GossipFTProvider *provider,
+				        GossipFTId        id);
+
+
+#endif /* __GOSSIP_FT_PROVIDER_H__ */
Index: libgossip/gossip-ft.c
===================================================================
RCS file: libgossip/gossip-ft.c
diff -N libgossip/gossip-ft.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgossip/gossip-ft.c	16 Nov 2005 21:45:26 -0000
@@ -0,0 +1,448 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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 <config.h>
+
+#include "gossip-ft.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_FT, GossipFTPriv))
+
+
+typedef struct _GossipFTPriv GossipFTPriv;
+
+struct _GossipFTPriv {
+	GossipFTId     id;
+	
+	GossipFTType   type;
+
+	GossipContact *contact;
+
+	gchar         *file_name;
+	guint          file_size;
+	gchar         *file_mime_type;
+};
+
+
+static void ft_class_init   (GossipFTClass *class);
+static void ft_init         (GossipFT      *ft);
+static void ft_finalize     (GObject       *object);
+static void ft_get_property (GObject       *object,
+			     guint          param_id,
+			     GValue        *value,
+			     GParamSpec    *pspec);
+static void ft_set_property (GObject       *object,
+			     guint          param_id,
+			     const GValue  *value,
+			     GParamSpec    *pspec);
+
+
+enum {
+	PROP_0,
+	PROP_ID,
+	PROP_TYPE,
+	PROP_CONTACT,
+	PROP_FILE_NAME,
+	PROP_FILE_SIZE,
+	PROP_FILE_MIME_TYPE,
+};
+
+
+static gpointer parent_class = NULL;
+
+
+GType
+gossip_ft_get_gtype (void)
+{
+	static GType type = 0;
+
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (GossipFTClass),
+			NULL, /* base_init */
+			NULL, /* base_finalize */
+			(GClassInitFunc) ft_class_init,
+			NULL, /* class_finalize */
+			NULL, /* class_data */
+			sizeof (GossipFT),
+			0,    /* n_preallocs */
+			(GInstanceInitFunc) ft_init
+		};
+
+		type = g_type_register_static (G_TYPE_OBJECT,
+					       "GossipFT",
+					       &info, 0);
+	}
+
+	return type;
+
+}
+
+static void
+ft_class_init (GossipFTClass *class)
+{
+	GObjectClass *object_class;
+
+	object_class = G_OBJECT_CLASS (class);
+	parent_class = g_type_class_peek_parent (class);
+
+	object_class->finalize     = ft_finalize;
+	object_class->get_property = ft_get_property;
+	object_class->set_property = ft_set_property;
+
+	g_object_class_install_property (object_class,
+					 PROP_ID,
+					 g_param_spec_int ("id",
+							   "Transaction ID",
+							   "The file transfer transaction id",
+							   0, 
+							   G_MAXINT,
+							   0,
+							   G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class,
+					 PROP_TYPE,
+					 g_param_spec_int ("type",
+							   "Transaction Type",
+							   "The type of transaction (send or receive)",
+							   GOSSIP_FT_TYPE_RECEIVING,
+							   GOSSIP_FT_TYPE_SENDING,
+							   GOSSIP_FT_TYPE_RECEIVING,
+							   G_PARAM_READWRITE));
+	
+	g_object_class_install_property (object_class,
+					 PROP_CONTACT,
+					 g_param_spec_object ("contact",
+							      "Transaction Contact",
+							      "The sender or receiver of the file transfer",
+							      GOSSIP_TYPE_CONTACT,
+							      G_PARAM_READWRITE));
+
+
+	g_object_class_install_property (object_class,
+					 PROP_FILE_NAME,
+					 g_param_spec_string ("file-name",
+							      "File Name",
+							      "The file being transferred",
+							      NULL,
+							      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+					 PROP_FILE_SIZE,
+					 g_param_spec_uint64 ("file-size",
+							      "File Size",
+							      "The file size in bytes",
+							      0, 
+							      G_MAXUINT64,
+							      0,
+							      G_PARAM_READWRITE));
+
+	g_object_class_install_property (object_class,
+					 PROP_FILE_MIME_TYPE,
+					 g_param_spec_string ("file-mime-type",
+							      "File Mime Type",
+							      "The mime type (for example text/plain)",
+							      NULL,
+							      G_PARAM_READWRITE));
+
+	g_type_class_add_private (object_class, sizeof (GossipFTPriv));
+
+}
+
+static void
+ft_init (GossipFT *ft)
+{
+	static GossipFTId  id = 1;
+	GossipFTPriv      *priv;
+
+	priv = GET_PRIV (ft);
+
+	priv->id             = id++;
+
+	priv->type           = GOSSIP_FT_TYPE_RECEIVING;
+
+	priv->contact        = NULL;
+
+	priv->file_name      = NULL;
+	priv->file_size      = 0;
+	priv->file_mime_type = NULL;
+}
+
+static void
+ft_finalize (GObject *object)
+{
+	GossipFTPriv *priv;
+
+	priv = GET_PRIV (object);
+	
+	if (priv->contact) {
+		g_object_unref (priv->contact);
+	}
+
+	g_free (priv->file_name);
+	g_free (priv->file_mime_type);
+
+	(* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+static void
+ft_get_property (GObject    *object,
+		      guint       param_id,
+		      GValue     *value,
+		      GParamSpec *pspec)
+{
+	GossipFTPriv *priv;
+	
+	priv = GET_PRIV (object);
+
+	switch (param_id) {
+	case PROP_ID:
+		g_value_set_int (value, priv->id);
+		break;
+	case PROP_TYPE:
+		g_value_set_int (value, priv->type);
+		break;
+	case PROP_CONTACT:
+		g_value_set_object (value, priv->contact);
+		break;
+	case PROP_FILE_NAME:
+		g_value_set_string (value, priv->file_name);
+		break;
+	case PROP_FILE_SIZE:
+		g_value_set_int (value, priv->file_size);
+		break;
+	case PROP_FILE_MIME_TYPE:
+		g_value_set_string (value, priv->file_mime_type);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+		break;
+	};
+}
+
+static void
+ft_set_property (GObject      *object,
+		 guint         param_id,
+		 const GValue *value,
+		 GParamSpec   *pspec)
+{
+	GossipFTPriv *priv;
+	
+	priv = GET_PRIV (object);
+
+	switch (param_id) {
+	case PROP_TYPE:
+		gossip_ft_set_type (GOSSIP_FT (object),
+				    g_value_get_int (value));
+		break;
+	case PROP_CONTACT:
+		gossip_ft_set_contact (GOSSIP_FT (object),
+				       GOSSIP_CONTACT (g_value_get_object (value)));
+		break;
+	case PROP_FILE_NAME:
+		gossip_ft_set_file_name (GOSSIP_FT (object),
+					 g_value_get_string (value));
+		break;
+	case PROP_FILE_SIZE:
+		gossip_ft_set_file_size (GOSSIP_FT (object),
+					 g_value_get_uint64 (value));
+		break;
+	case PROP_FILE_MIME_TYPE:
+		gossip_ft_set_file_mime_type (GOSSIP_FT (object),
+					      g_value_get_string (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+		break;
+	};
+}
+
+GossipFT *
+gossip_ft_new (void)
+{
+	return g_object_new (GOSSIP_TYPE_FT, NULL);
+}
+
+GossipFTId
+gossip_ft_get_id (GossipFT *ft)
+{
+	GossipFTPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_FT (ft), 0);
+
+	priv = GET_PRIV (ft);
+
+	return priv->id;
+}
+
+GossipFTType
+gossip_ft_get_type (GossipFT *ft)
+{
+	GossipFTPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_FT (ft), 0);
+
+	priv = GET_PRIV (ft);
+
+	return priv->type;
+}
+
+void
+gossip_ft_set_type (GossipFT     *ft,
+		    GossipFTType  type)
+{
+	GossipFTPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_FT (ft));
+	g_return_if_fail (type >= GOSSIP_FT_TYPE_RECEIVING || 
+			  type <= GOSSIP_FT_TYPE_SENDING);
+
+	priv = GET_PRIV (ft);
+
+	priv->type = type;
+}
+
+GossipContact *
+gossip_ft_get_contact (GossipFT *ft)
+{
+	GossipFTPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_FT (ft), NULL);
+
+	priv = GET_PRIV (ft);
+
+	return priv->contact;
+}
+
+void
+gossip_ft_set_contact (GossipFT      *ft,
+		       GossipContact *contact)
+{
+	GossipFTPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_FT (ft));
+	g_return_if_fail (GOSSIP_IS_CONTACT (contact));
+
+	priv = GET_PRIV (ft);
+
+	if (priv->contact) {
+		g_object_unref (priv->contact);
+	}
+
+	priv->contact = g_object_ref (contact);
+}
+
+const gchar *
+gossip_ft_get_file_name (GossipFT *ft)
+{
+	GossipFTPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_FT (ft), NULL);
+
+	priv = GET_PRIV (ft);
+
+	return priv->file_name;
+}
+
+void
+gossip_ft_set_file_name (GossipFT    *ft,
+			 const gchar *file_name)
+{
+	GossipFTPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_FT (ft));
+
+	priv = GET_PRIV (ft);
+
+	g_free (priv->file_name);
+	priv->file_name = g_strdup (file_name);
+}
+
+guint64
+gossip_ft_get_file_size (GossipFT *ft)
+{
+	GossipFTPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_FT (ft), 0);
+
+	priv = GET_PRIV (ft);
+
+	return priv->file_size;
+}
+
+void
+gossip_ft_set_file_size (GossipFT *ft,
+			 guint64   file_size)
+{
+	GossipFTPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_FT (ft));
+
+	priv = GET_PRIV (ft);
+
+	priv->file_size = file_size;
+}
+
+const gchar *
+gossip_ft_get_file_mime_type (GossipFT *ft)
+{
+	GossipFTPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_FT (ft), NULL);
+
+	priv = GET_PRIV (ft);
+
+	return priv->file_mime_type;
+}
+
+void
+gossip_ft_set_file_mime_type (GossipFT    *ft,
+			      const gchar *file_mime_type)
+{
+	GossipFTPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_FT (ft));
+
+	priv = GET_PRIV (ft);
+
+	g_free (priv->file_mime_type);
+	priv->file_mime_type = g_strdup (file_mime_type);
+}
+
+gboolean
+gossip_ft_equal (gconstpointer a, 
+		 gconstpointer b)
+{
+	GossipFTPriv *priv1;
+	GossipFTPriv *priv2;
+
+	g_return_val_if_fail (GOSSIP_IS_FT (a), FALSE);
+	g_return_val_if_fail (GOSSIP_IS_FT (b), FALSE);
+
+	priv1 = GET_PRIV (a);
+	priv2 = GET_PRIV (b);
+
+	if (priv1->id == priv2->id) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
Index: libgossip/gossip-ft.h
===================================================================
RCS file: libgossip/gossip-ft.h
diff -N libgossip/gossip-ft.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libgossip/gossip-ft.h	16 Nov 2005 21:45:26 -0000
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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.
+ */
+
+#ifndef __GOSSIP_FT_H__
+#define __GOSSIP_FT_H__
+
+#include <glib-object.h>
+
+#include "gossip-contact.h"
+
+#define GOSSIP_TYPE_FT         (gossip_ft_get_gtype ())
+#define GOSSIP_FT(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_FT, GossipFT))
+#define GOSSIP_FT_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), GOSSIP_TYPE_FT, GossipFTClass))
+#define GOSSIP_IS_FT(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_FT))
+#define GOSSIP_IS_FT_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_FT))
+#define GOSSIP_FT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_FT, GossipFTClass))
+
+typedef struct _GossipFT      GossipFT;
+typedef struct _GossipFTClass GossipFTClass;
+
+typedef gint GossipFTId;
+
+struct _GossipFT {
+	GObject parent;
+};
+
+struct _GossipFTClass {
+	GObjectClass parent_class;
+};
+
+typedef enum {
+	GOSSIP_FT_TYPE_RECEIVING,
+	GOSSIP_FT_TYPE_SENDING
+} GossipFTType;
+
+typedef enum {
+	GOSSIP_FT_ERROR_DECLINED,
+	GOSSIP_FT_ERROR_UNSUPPORTED,
+	GOSSIP_FT_ERROR_UNKNOWN
+} GossipFTError;
+
+
+GType          gossip_ft_get_gtype           (void) G_GNUC_CONST;
+
+GossipFT *     gossip_ft_new                (void);
+GossipFTType   gossip_ft_get_type           (GossipFT      *ft);
+void           gossip_ft_set_type           (GossipFT      *ft,
+					     GossipFTType   type);
+GossipContact *gossip_ft_get_contact        (GossipFT      *ft);
+void           gossip_ft_set_contact        (GossipFT      *ft,
+					     GossipContact *contact);
+GossipFTId     gossip_ft_get_id             (GossipFT      *ft);
+const gchar *  gossip_ft_get_file_name      (GossipFT      *ft);
+void           gossip_ft_set_file_name      (GossipFT      *ft,
+					     const gchar   *file_name);
+guint64        gossip_ft_get_file_size      (GossipFT      *ft);
+void           gossip_ft_set_file_size      (GossipFT      *ft,
+					     guint64        file_size);
+const gchar *  gossip_ft_get_file_mime_type (GossipFT      *ft);
+void           gossip_ft_set_file_mime_type (GossipFT      *ft,
+					     const gchar   *file_mime_type);
+
+gboolean       gossip_ft_equal              (gconstpointer  a, 
+					     gconstpointer  b);
+
+#endif /* __GOSSIP_FT_H__ */
Index: libgossip/gossip-protocol.c
===================================================================
RCS file: /cvs/gnome/gossip/libgossip/gossip-protocol.c,v
retrieving revision 1.18
diff -u -r1.18 gossip-protocol.c
--- libgossip/gossip-protocol.c	1 Nov 2005 00:22:26 -0000	1.18
+++ libgossip/gossip-protocol.c	16 Nov 2005 21:45:27 -0000
@@ -36,7 +36,7 @@
 	CONTACT_REMOVED,
 	COMPOSING_EVENT,
 
-	/* Used for protocols to request information from user */
+	/* use to get password from user */
 	GET_PASSWORD,
 	
 	SUBSCRIPTION_REQUEST,
@@ -60,6 +60,7 @@
 	klass->is_connected        = NULL;
 	klass->send_message        = NULL;
 	klass->send_composing      = NULL;
+	klass->send_file           = NULL;
 	klass->set_presence        = NULL;
         klass->find_contact        = NULL;
         klass->add_contact         = NULL;
@@ -112,6 +113,7 @@
 			      libgossip_marshal_VOID__POINTER,
 			      G_TYPE_NONE,
 			      1, G_TYPE_POINTER);
+
 	signals[CONTACT_UPDATED] = 
 		g_signal_new ("contact-updated",
 			      G_TYPE_FROM_CLASS (klass),
@@ -151,6 +153,7 @@
 			      libgossip_marshal_VOID__POINTER_BOOLEAN,
 			      G_TYPE_NONE,
 			      2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
+
 	signals[GET_PASSWORD] =
 		g_signal_new ("get-password",
 			      G_TYPE_FROM_CLASS (klass),
Index: libgossip/gossip-protocol.h
===================================================================
RCS file: /cvs/gnome/gossip/libgossip/gossip-protocol.h,v
retrieving revision 1.14
diff -u -r1.14 gossip-protocol.h
--- libgossip/gossip-protocol.h	1 Nov 2005 00:22:26 -0000	1.14
+++ libgossip/gossip-protocol.h	16 Nov 2005 21:45:28 -0000
@@ -82,6 +82,9 @@
 	void          (*send_composing)        (GossipProtocol  *protocol,
 						GossipContact   *contact,
 						gboolean         typing);
+	void          (*send_file)             (GossipProtocol  *protocol,
+						GossipContact   *contact,
+						const gchar     *file);
 	void          (*set_presence)          (GossipProtocol  *protocol,
 						GossipPresence  *presence);
 	GossipContact * (*find_contact)        (GossipProtocol  *protocol,
@@ -145,6 +148,9 @@
 void           gossip_protocol_send_composing           (GossipProtocol               *protocol,
 							 GossipContact                *contact,
 							 gboolean                      typing);
+void           gossip_protocol_send_file                (GossipProtocol               *protocol,
+							 GossipContact                *contact,
+							 const gchar                  *file);
 void           gossip_protocol_set_presence             (GossipProtocol               *protocol,
 							 GossipPresence               *presence);
 GossipContact *gossip_protocol_find_contact             (GossipProtocol               *protocol,
Index: libgossip/gossip-session.c
===================================================================
RCS file: /cvs/gnome/gossip/libgossip/gossip-session.c,v
retrieving revision 1.43
diff -u -r1.43 gossip-session.c
--- libgossip/gossip-session.c	5 Nov 2005 12:41:02 -0000	1.43
+++ libgossip/gossip-session.c	16 Nov 2005 21:45:29 -0000
@@ -1283,6 +1283,78 @@
 	}
 }
 
+#if 0
+void
+gossip_session_ft_start (GossipSession  *session,
+			 GossipContact  *contact,
+			 const gchar    *file)
+{
+	GossipSessionPriv *priv;
+	GossipAccount     *account;
+	GossipProtocol    *protocol;
+
+	g_return_if_fail (GOSSIP_IS_SESSION (session));
+
+	priv = GET_PRIV (session);
+
+	account = gossip_session_find_account (session, contact);
+	protocol = g_hash_table_lookup (priv->accounts, 
+					gossip_account_get_name (account));
+	
+	gossip_protocol_ft_start (protocol, contact, file);
+}
+
+void            gossip_session_ft_start                (GossipSession           *session,
+							GossipContact           *contact,
+							const gchar             *file);
+void            gossip_session_ft_accept               (GossipSession           *session,
+							GossipContact           *contact,
+							const gchar             *file);
+void            gossip_session_ft_decline              (GossipSession           *session,
+							GossipContact           *contact,
+							const gchar             *file);
+
+void
+gossip_session_ft_accept (GossipSession  *session,
+			  GossipContact  *contact,
+			  const gchar    *file)
+{
+	GossipSessionPriv *priv;
+	GossipAccount     *account;
+	GossipProtocol    *protocol;
+
+	g_return_if_fail (GOSSIP_IS_SESSION (session));
+
+	priv = GET_PRIV (session);
+
+	account = gossip_session_find_account (session, contact);
+	protocol = g_hash_table_lookup (priv->accounts, 
+					gossip_account_get_name (account));
+	
+	gossip_protocol_ft_accept (protocol, contact, file);
+}
+
+void
+gossip_session_ft_decline (GossipSession  *session,
+			   GossipContact  *contact,
+			   const gchar    *file)
+{
+	GossipSessionPriv *priv;
+	GossipAccount     *account;
+	GossipProtocol    *protocol;
+
+	g_return_if_fail (GOSSIP_IS_SESSION (session));
+
+	priv = GET_PRIV (session);
+
+	account = gossip_session_find_account (session, contact);
+	protocol = g_hash_table_lookup (priv->accounts, 
+					gossip_account_get_name (account));
+	
+	gossip_protocol_ft_accept (protocol, contact, file);
+}
+#endif
+
 GossipPresence *
 gossip_session_get_presence (GossipSession *session)
 {
@@ -1384,6 +1456,26 @@
 	g_return_val_if_fail (GOSSIP_IS_PROTOCOL (protocol), NULL);
 
 	return GOSSIP_CHATROOM_PROVIDER (protocol);
+}
+
+GossipFTProvider *
+gossip_session_get_ft_provider (GossipSession *session,
+				GossipAccount *account)
+{
+	GossipSessionPriv *priv;
+	GossipProtocol    *protocol;
+
+	g_return_val_if_fail (GOSSIP_IS_SESSION (session), NULL);
+	g_return_val_if_fail (GOSSIP_IS_ACCOUNT (account), NULL);
+
+	priv = GET_PRIV (session);
+
+	protocol = g_hash_table_lookup (priv->accounts, 
+					gossip_account_get_name (account));
+
+	g_return_val_if_fail (GOSSIP_IS_PROTOCOL (protocol), NULL);
+
+	return GOSSIP_FT_PROVIDER (protocol);
 }
 
 GossipContact *
Index: libgossip/gossip-session.h
===================================================================
RCS file: /cvs/gnome/gossip/libgossip/gossip-session.h,v
retrieving revision 1.20
diff -u -r1.20 gossip-session.h
--- libgossip/gossip-session.h	5 Nov 2005 12:41:02 -0000	1.20
+++ libgossip/gossip-session.h	16 Nov 2005 21:45:30 -0000
@@ -28,6 +28,7 @@
 #include "gossip-async.h"
 #include "gossip-chatroom-provider.h"
 #include "gossip-contact.h"
+#include "gossip-ft-provider.h"
 #include "gossip-message.h"
 #include "gossip-presence.h"
 #include "gossip-vcard.h"
@@ -99,9 +100,12 @@
 const gchar *   gossip_session_get_active_resource     (GossipSession           *session,
 							GossipContact           *contact);
 
-/* misc */
+/* providers */
 GossipChatroomProvider *
 gossip_session_get_chatroom_provider                    (GossipSession           *session,
+							 GossipAccount           *account);
+GossipFTProvider *
+gossip_session_get_ft_provider                          (GossipSession           *session,
 							 GossipAccount           *account);
 
 /* contact management */
Index: libgossip/libgossip-marshal.list
===================================================================
RCS file: /cvs/gnome/gossip/libgossip/libgossip-marshal.list,v
retrieving revision 1.2
diff -u -r1.2 libgossip-marshal.list
--- libgossip/libgossip-marshal.list	1 Nov 2005 00:22:26 -0000	1.2
+++ libgossip/libgossip-marshal.list	16 Nov 2005 21:45:30 -0000
@@ -4,8 +4,10 @@
 VOID:POINTER,POINTER
 VOID:POINTER,POINTER,POINTER
 VOID:POINTER,BOOLEAN
+VOID:INT
 VOID:INT,OBJECT
 VOID:INT,STRING
 VOID:OBJECT
+VOID:OBJECT,POINTER
 STRING:POINTER
 
Index: protocols/jabber/Makefile.am
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/Makefile.am,v
retrieving revision 1.4
diff -u -r1.4 Makefile.am
--- protocols/jabber/Makefile.am	24 Aug 2005 13:22:35 -0000	1.4
+++ protocols/jabber/Makefile.am	16 Nov 2005 21:45:30 -0000
@@ -11,9 +11,13 @@
 libgossip_jabber_la_SOURCES =                   \
 	gossip-jabber.c                         \
 	gossip-jabber.h                         \
-	gossip-jabber-private.h                 \
 	gossip-jabber-chatrooms.c               \
 	gossip-jabber-chatrooms.h               \
+	gossip-jabber-ft.c			\
+	gossip-jabber-ft.h			\
+	gossip-jabber-ft-utils.c		\
+	gossip-jabber-ft-utils.h		\
+	gossip-jabber-private.h                 \
 	gossip-jabber-vcard.c			\
 	gossip-jabber-vcard.h			\
 	gossip-jabber-services.c		\
Index: protocols/jabber/gossip-jabber-chatrooms.c
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-jabber-chatrooms.c,v
retrieving revision 1.21
diff -u -r1.21 gossip-jabber-chatrooms.c
--- protocols/jabber/gossip-jabber-chatrooms.c	24 Aug 2005 13:22:35 -0000	1.21
+++ protocols/jabber/gossip-jabber-chatrooms.c	16 Nov 2005 21:45:31 -0000
@@ -27,9 +27,10 @@
 
 #include <libgossip/gossip-utils.h>
 
-#include "gossip-jid.h"
 #include "gossip-jabber-chatrooms.h"
+#include "gossip-jid.h"
 #include "gossip-jabber-utils.h"
+#include "gossip-jabber-private.h"
 
 #define d(x)
 
@@ -47,7 +48,7 @@
 
 
 typedef struct {
-	gint              id;
+	GossipChatroomId  id;
 	GossipJID        *jid;
 	gchar            *name;
 
@@ -93,6 +94,69 @@
 							      GossipJabberChatrooms  *chatrooms);
 
 
+
+GossipJabberChatrooms *
+gossip_jabber_chatrooms_init (GossipJabber *jabber)
+{
+	GossipJabberChatrooms *chatrooms;
+	LmConnection          *connection;
+	LmMessageHandler      *handler;
+
+	g_return_val_if_fail (GOSSIP_IS_JABBER (jabber), NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+	g_return_val_if_fail (connection != NULL, NULL);
+
+	chatrooms = g_new0 (GossipJabberChatrooms, 1);
+	
+	chatrooms->jabber     = g_object_ref (jabber);
+	chatrooms->connection = lm_connection_ref (connection);
+	chatrooms->presence   = NULL;
+	chatrooms->room_id_hash = g_hash_table_new (NULL, NULL);
+	chatrooms->room_jid_hash = g_hash_table_new_full (gossip_jid_hash,
+							  gossip_jid_equal,
+							  (GDestroyNotify) gossip_jid_unref,
+							  NULL);
+
+	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_chatrooms_message_handler,
+					  chatrooms, NULL);
+
+	lm_connection_register_message_handler (chatrooms->connection,
+						handler, 
+						LM_MESSAGE_TYPE_MESSAGE,
+						LM_HANDLER_PRIORITY_NORMAL);
+	lm_message_handler_unref (handler);
+	
+	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_chatrooms_presence_handler,
+					  chatrooms, NULL);
+
+	lm_connection_register_message_handler (chatrooms->connection,
+						handler, 
+						LM_MESSAGE_TYPE_PRESENCE,
+						LM_HANDLER_PRIORITY_FIRST);
+	lm_message_handler_unref (handler);
+
+	return chatrooms;
+}	
+
+void
+gossip_jabber_chatrooms_finalize (GossipJabberChatrooms *chatrooms)
+{
+	g_return_if_fail (chatrooms != NULL);
+
+	g_hash_table_destroy (chatrooms->room_id_hash);
+	g_hash_table_destroy (chatrooms->room_jid_hash);
+
+	if (chatrooms->presence) {
+		g_object_unref (chatrooms->presence);
+	}
+
+	lm_connection_unref (chatrooms->connection);
+	g_object_unref (chatrooms->jabber);
+	
+	g_free (chatrooms);
+}
+
 static JabberChatroom *
 jabber_chatrooms_chatroom_new (GossipJabberChatrooms *chatrooms,
 			       const gchar           *room_name, 
@@ -101,15 +165,13 @@
 {
 	GossipJabber   *jabber;
 	GossipContact  *own_contact;
-	GossipAccount  *account;
 	JabberChatroom *room;
 	gchar          *jid_str;
 	static int      id = 1;
 
-	/* FIXME: can we use the own contact instead of creating a new one? */
 	jabber = chatrooms->jabber;
+
 	own_contact = gossip_jabber_get_own_contact (jabber);
-	account = gossip_contact_get_account (own_contact);
 
 	room = g_new0 (JabberChatroom, 1);
 
@@ -122,10 +184,7 @@
 
 	room->contacts = NULL;
 	
-	room->own_contact = gossip_contact_new_full (GOSSIP_CONTACT_TYPE_USER,
-						     account,
-						     gossip_jid_get_full (room->jid),
-						     gossip_jid_get_resource (room->jid));
+	room->own_contact = g_object_ref (own_contact);
 
 	return room;
 }
@@ -353,63 +412,6 @@
 	room->contacts = g_slist_prepend (room->contacts, c);
 
 	return c;
-}
-
-GossipJabberChatrooms *
-gossip_jabber_chatrooms_new (GossipJabber   *jabber,
-			     LmConnection   *connection)
-{
-	GossipJabberChatrooms *chatrooms;
-	LmMessageHandler      *handler;
-
-	g_return_val_if_fail (jabber != NULL, NULL);
-	g_return_val_if_fail (connection != NULL, NULL);
-
-	chatrooms = g_new0 (GossipJabberChatrooms, 1);
-	
-	chatrooms->jabber     = jabber;
-	chatrooms->connection = connection;
-	chatrooms->presence   = NULL;
-	chatrooms->room_id_hash = g_hash_table_new (NULL, NULL);
-	chatrooms->room_jid_hash = g_hash_table_new_full (gossip_jid_hash,
-							  gossip_jid_equal,
-							  (GDestroyNotify) gossip_jid_unref,
-							  NULL);
-
-	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_chatrooms_message_handler,
-					  chatrooms, NULL);
-
-	lm_connection_register_message_handler (connection,
-						handler, 
-						LM_MESSAGE_TYPE_MESSAGE,
-						LM_HANDLER_PRIORITY_NORMAL);
-	lm_message_handler_unref (handler);
-	
-	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_chatrooms_presence_handler,
-					  chatrooms, NULL);
-
-	lm_connection_register_message_handler (connection,
-						handler, 
-						LM_MESSAGE_TYPE_PRESENCE,
-						LM_HANDLER_PRIORITY_FIRST);
-	lm_message_handler_unref (handler);
-
-	return chatrooms;
-}	
-
-void
-gossip_jabber_chatrooms_free (GossipJabberChatrooms *chatrooms)
-{
-	g_return_if_fail (chatrooms != NULL);
-
-	g_hash_table_destroy (chatrooms->room_id_hash);
-	g_hash_table_destroy (chatrooms->room_jid_hash);
-
-	if (chatrooms->presence) {
-		g_object_unref (chatrooms->presence);
-	}
-	
-	g_free (chatrooms);
 }
 
 GossipChatroomId
Index: protocols/jabber/gossip-jabber-chatrooms.h
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-jabber-chatrooms.h,v
retrieving revision 1.8
diff -u -r1.8 gossip-jabber-chatrooms.h
--- protocols/jabber/gossip-jabber-chatrooms.h	15 Jul 2005 17:27:44 -0000	1.8
+++ protocols/jabber/gossip-jabber-chatrooms.h	16 Nov 2005 21:45:31 -0000
@@ -33,9 +33,8 @@
 typedef struct _GossipJabberChatrooms GossipJabberChatrooms;
 
 
-GossipJabberChatrooms *gossip_jabber_chatrooms_new                 (GossipJabber          *jabber,
-								    LmConnection          *connection);
-void                   gossip_jabber_chatrooms_free                (GossipJabberChatrooms *chatrooms);
+GossipJabberChatrooms *gossip_jabber_chatrooms_init                (GossipJabber          *jabber);
+void                   gossip_jabber_chatrooms_finalize            (GossipJabberChatrooms *chatrooms);
 GossipChatroomId       gossip_jabber_chatrooms_join                (GossipJabberChatrooms *chatroom,
 								    const gchar           *room,
 								    const gchar           *server,
Index: protocols/jabber/gossip-jabber-ft-utils.c
===================================================================
RCS file: protocols/jabber/gossip-jabber-ft-utils.c
diff -N protocols/jabber/gossip-jabber-ft-utils.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ protocols/jabber/gossip-jabber-ft-utils.c	16 Nov 2005 21:45:31 -0000
@@ -0,0 +1,298 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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 <config.h>
+
+#include <string.h>
+
+#include "gossip-jabber-ft-utils.h"
+
+#define d(x) x
+
+
+static void base64_init (void);
+
+
+/*
+ * taken from libgsf
+ */
+
+static guint8 base64_rank[256];
+static char const *base64_alphabet =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* line length for base64 encoding, must be a multiple of 4. */
+enum { BASE64_LINE_LEN = 76 };
+
+
+static void
+base64_init (void)
+{
+	static gboolean inited = FALSE;
+	int             i;
+
+	if (inited) {
+		return;
+	} else {
+		inited = TRUE;
+	}
+
+	memset (base64_rank, 0xff, sizeof (base64_rank));
+	for (i = 0; i < 64; i++) {
+		base64_rank[(unsigned int)base64_alphabet[i]] = i;
+	}
+
+	base64_rank['='] = 0;
+}
+
+/* call this when finished encoding everything, to
+   flush off the last little bit */
+size_t
+gossip_jabber_ft_base64_encode_close (guint8 const *in, 
+				      size_t        inlen,
+				      gboolean      break_lines, 
+				      guint8       *out, 
+				      int          *state,
+				      unsigned int *save)
+{
+	int     c1, c2;
+	guint8 *outptr = out;
+
+ 	base64_init ();
+
+	if (inlen > 0) {
+		outptr += gossip_jabber_ft_base64_encode_step (in, inlen, 
+							       break_lines, outptr, 
+							       state, save);
+	}
+
+	c1 = ((guint8 *)save)[1];
+	c2 = ((guint8 *)save)[2];
+	
+	d(g_print("Base64: mode = %d\nc1 = %c\nc2 = %c\n",
+		 (int)((char *)save)[0],
+		 (int)((char *)save)[1],
+		 (int)((char *)save)[2]));
+
+	switch (((char *)save)[0]) {
+	case 2:
+		outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
+		g_assert(outptr[2] != 0);
+		goto skip;
+	case 1:
+		outptr[2] = '=';
+	skip:
+		outptr[0] = base64_alphabet[ c1 >> 2 ];
+		outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )];
+		outptr[3] = '=';
+		outptr += 4;
+		++*state;
+		break;
+	}
+	if (break_lines && *state > 0)
+		*outptr++ = '\n';
+
+	*save = 0;
+	*state = 0;
+
+	return outptr-out;
+}
+
+/*
+  performs an 'encode step', only encodes blocks of 3 characters to the
+  output at a time, saves left-over state in state and save (initialise to
+  0 on first invocation).
+*/
+size_t
+gossip_jabber_ft_base64_encode_step (guint8 const *in, 
+				     size_t        len,
+				     gboolean      break_lines, 
+				     guint8       *out, 
+				     int          *state, 
+				     unsigned int *save)
+{
+	register guint8 const *inptr;
+	register guint8       *outptr;
+
+ 	base64_init ();
+
+	if (len <= 0) {
+		return 0;
+	}
+
+	inptr = in;
+	outptr = out;
+
+	d(g_print("Base64: we have %d chars, and %d saved chars\n", len, ((char *)save)[0]));
+
+	if (len + ((char *)save)[0] > 2) {
+		guint8 const *inend = in+len-2;
+		register      int c1, c2, c3;
+		register      int already;
+
+		already = *state;
+
+		switch (((char *)save)[0]) {
+		case 1:	c1 = ((guint8 *)save)[1]; goto skip1;
+		case 2:	c1 = ((guint8 *)save)[1];
+			c2 = ((guint8 *)save)[2]; goto skip2;
+		}
+		
+		/* yes, we jump into the loop, no i'm not going to change it, it's beautiful! */
+		while (inptr < inend) {
+			c1 = *inptr++;
+		skip1:
+			c2 = *inptr++;
+		skip2:
+			c3 = *inptr++;
+			*outptr++ = base64_alphabet[ c1 >> 2 ];
+			*outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ];
+			*outptr++ = base64_alphabet[ ((c2 &0x0f) << 2 ) | (c3 >> 6) ];
+			*outptr++ = base64_alphabet[ c3 & 0x3f ];
+
+			/* this is a bit ugly ... */
+			if (break_lines && (++already) * 4 >= BASE64_LINE_LEN) {
+				*outptr++ = '\n';
+				already = 0;
+			}
+		}
+
+		((char *)save)[0] = 0;
+		len = 2-(inptr-inend);
+		*state = already;
+	}
+
+	d(g_print("Base64: state = %d, len = %d\n",
+		 (int)((char *)save)[0], len));
+
+	if (len > 0) {
+		register char *saveout;
+
+		/* points to the slot for the next char to save */
+		saveout = & (((char *)save)[1]) + ((char *)save)[0];
+
+		/* len can only be 0 1 or 2 */
+		switch(len) {
+		case 2:	*saveout++ = *inptr++;
+		case 1:	*saveout++ = *inptr++;
+		}
+		((char*)save)[0] += len;
+	}
+
+	d(g_print("Base64: mode = %d\nc1 = %c\nc2 = %c\n",
+		 (int)((char *)save)[0],
+		 (int)((char *)save)[1],
+		 (int)((char *)save)[2]));
+
+	return outptr-out;
+}
+
+size_t
+gossip_jabber_ft_base64_decode_step (guint8 const *in, 
+				     size_t        len,
+				     guint8       *out,
+				     int          *state, 
+				     guint        *save)
+{
+	register guint8 const *inptr;
+	register guint8       *outptr, c;
+	register unsigned int  v;
+	guint8 const          *inend;
+	int                    i;
+
+ 	base64_init ();
+
+	inend = in+len;
+	outptr = out;
+
+	/* convert 4 base64 bytes to 3 normal bytes */
+	v = *save;
+	i = *state;
+	inptr = in;
+
+	while (inptr < inend) {
+		c = base64_rank[*inptr++];
+		if (c != 0xff) {
+			v = (v << 6) | c;
+			i++;
+			if (i == 4) {
+				*outptr++ = v >> 16;
+				*outptr++ = v >> 8;
+				*outptr++ = v;
+				i = 0;
+			}
+		}
+	}
+
+	*save = v;
+	*state = i;
+
+	/* quick scan back for '=' on the end somewhere */
+	/* fortunately we can drop 1 output char for each trailing = (upto 2) */
+	i = 2;
+	while (inptr > in && i) {
+		inptr--;
+		if (base64_rank[*inptr] != 0xff) {
+			if (*inptr == '=' && outptr > out)
+				outptr--;
+			i--;
+		}
+	}
+
+	/* if i!= 0 then there is a truncation error! */
+	return outptr-out;
+}
+
+guint8 *
+gossip_jabber_ft_base64_encode_simple (guint8 const *data, 
+				       size_t        len)
+{
+	guint8       *out;
+	int           state = 0, outlen;
+	unsigned int  save = 0;
+	gboolean      break_lines = TRUE;
+
+ 	base64_init ();
+
+	outlen = len * 4 / 3 + 5;
+	if (break_lines) {
+		outlen += outlen / BASE64_LINE_LEN + 1;
+	}
+
+	out = g_new (guint8, outlen);
+	outlen = gossip_jabber_ft_base64_encode_close (data, len, break_lines,
+						       out, &state, &save);
+	out [outlen] = '\0';
+	return out;
+}
+
+size_t
+gossip_jabber_ft_base64_decode_simple (guint8 *data, 
+				       size_t  len)
+{
+	int          state = 0;
+	unsigned int save = 0;
+
+	base64_init ();
+
+	return gossip_jabber_ft_base64_decode_step (data, len, data, &state, &save);
+}
+
+
Index: protocols/jabber/gossip-jabber-ft-utils.h
===================================================================
RCS file: protocols/jabber/gossip-jabber-ft-utils.h
diff -N protocols/jabber/gossip-jabber-ft-utils.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ protocols/jabber/gossip-jabber-ft-utils.h	16 Nov 2005 21:45:31 -0000
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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.
+ */
+
+#ifndef __GOSSIP_JABBER_FT_UTILS_H__
+#define __GOSSIP_JABBER_FT_UTILS_H__
+
+#include <glib.h>
+
+
+size_t  gossip_jabber_ft_base64_encode_close  (guint8 const *in,
+					       size_t        inlen,
+					       gboolean      break_lines,
+					       guint8       *out,
+					       int          *state,
+					       unsigned int *save);
+size_t  gossip_jabber_ft_base64_encode_step   (guint8 const *in,
+					       size_t        len,
+					       gboolean      break_lines,
+					       guint8       *out,
+					       int          *state,
+					       unsigned int *save);
+size_t  gossip_jabber_ft_base64_decode_step   (guint8 const *in,
+					       size_t        len,
+					       guint8       *out,
+					       int          *state,
+					       guint        *save);
+guint8 *gossip_jabber_ft_base64_encode_simple (guint8 const *data,
+					       size_t        len);
+size_t  gossip_jabber_ft_base64_decode_simple (guint8       *data,
+					       size_t        len);
+
+
+#endif /* __GOSSIP_JABBER_FT_UTILS_H__ */
Index: protocols/jabber/gossip-jabber-ft.c
===================================================================
RCS file: protocols/jabber/gossip-jabber-ft.c
diff -N protocols/jabber/gossip-jabber-ft.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ protocols/jabber/gossip-jabber-ft.c	16 Nov 2005 21:45:32 -0000
@@ -0,0 +1,883 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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 <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <loudmouth/loudmouth.h>
+#include <libgnomevfs/gnome-vfs.h>
+
+#include "gossip-jabber-ft.h"
+#include "gossip-jabber-private.h"
+#include "gossip-jid.h"
+
+#define d(x) x
+
+#define XMPP_FILE_TRANSFER_XMLNS        "http://jabber.org/protocol/si"
+#define XMPP_FILE_TRANSFER_PROFILE      "http://jabber.org/protocol/si/profile/file-transfer"
+
+#define XMPP_FILE_XMLNS                 "http://jabber.org/protocol/si/profile/file-transfer"
+#define XMPP_FEATURE_XMLNS              "http://jabber.org/protocol/feature-neg"
+
+#define XMPP_BYTESTREAMS_PROTOCOL       "http://jabber.org/protocol/bytestreams"
+#define XMPP_IBB_PROTOCOL               "http://jabber.org/protocol/ibb"
+
+#define XMPP_AMP_XMLNS                  "http://jabber.org/protocol/amp"
+
+#define IMPP_ERROR_XMLNS                "urn:ietf:params:xml:ns:xmpp-stanzas"
+
+
+struct _GossipJabberFTs {
+	GossipJabber   *jabber;
+	LmConnection   *connection;
+
+ 	GHashTable     *str_ids; 
+	GHashTable     *ft_ids;
+	GHashTable     *remote_ids;
+};
+
+
+static LmHandlerResult jabber_ft_iq_si_handler        (LmMessageHandler  *handler,
+						       LmConnection      *conn,
+						       LmMessage         *message,
+						       GossipJabber      *jabber);
+static void            jabber_ft_handle_request       (GossipJabber      *jabber,
+						       LmMessage         *m);
+static void            jabber_ft_handle_error         (GossipJabber      *jabber,
+						       LmMessage         *m);
+static void            jabber_ft_error                (GossipJabber      *jabber,
+						       const gchar       *signal,
+						       GossipFT          *ft,
+						       GossipFTError      code,
+						       const gchar       *reason);
+static gboolean        jabber_ft_get_file_details     (const gchar       *uri,
+						       gchar            **file_name,
+						       gchar            **file_size,
+						       gchar            **mime_type);
+static gchar *         jabber_ft_get_contact_last_jid (GossipContact     *contact);
+
+
+GossipJabberFTs *
+gossip_jabber_ft_init (GossipJabber *jabber)
+{
+	GossipJabberFTs  *fts;
+	LmConnection     *connection;
+ 	LmMessageHandler *handler;
+
+	g_return_val_if_fail (GOSSIP_IS_JABBER (jabber), NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+
+	fts = g_new0 (GossipJabberFTs, 1);
+
+	fts->jabber     = g_object_ref (jabber);
+	fts->connection = g_object_ref (connection);
+
+	fts->str_ids = g_hash_table_new_full (g_int_hash,
+					      g_int_equal,
+					      NULL,
+					      g_free);
+
+	fts->ft_ids = g_hash_table_new_full (g_str_hash,
+					     g_str_equal,
+					     g_free,
+					     g_object_unref);
+
+	fts->remote_ids = g_hash_table_new_full (g_int_hash,
+						 g_int_equal,
+						 NULL,
+						 g_free);
+	
+	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_ft_iq_si_handler,
+					  jabber, NULL);
+	lm_connection_register_message_handler (connection,
+						handler,
+						LM_MESSAGE_TYPE_IQ,
+						LM_HANDLER_PRIORITY_NORMAL);
+	lm_message_handler_unref (handler);
+
+	return fts;
+}
+
+void
+gossip_jabber_ft_finalize (GossipJabberFTs *fts)
+{
+	g_return_if_fail (fts != NULL);
+
+ 	g_hash_table_destroy (fts->str_ids); 
+ 	g_hash_table_destroy (fts->ft_ids); 
+ 	g_hash_table_destroy (fts->remote_ids); 
+
+	g_object_unref (fts->connection);
+	g_object_unref (fts->jabber);
+	
+	g_free (fts);
+}
+
+static LmHandlerResult
+jabber_ft_iq_si_handler (LmMessageHandler *handler,
+			 LmConnection     *conn,
+			 LmMessage        *m,
+			 GossipJabber     *jabber)
+{
+	GossipJabberPriv *priv;
+	LmMessageSubType  subtype;
+	LmMessageNode    *node;
+	const gchar      *xmlns;
+
+	priv = jabber->priv;
+	
+	subtype = lm_message_get_sub_type (m);
+
+	if (subtype != LM_MESSAGE_SUB_TYPE_GET &&
+	    subtype != LM_MESSAGE_SUB_TYPE_SET &&
+	    subtype != LM_MESSAGE_SUB_TYPE_RESULT &&
+	    subtype != LM_MESSAGE_SUB_TYPE_ERROR) {
+		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+	}
+
+	if (subtype == LM_MESSAGE_SUB_TYPE_ERROR) {
+		/* handle it */
+		jabber_ft_handle_error (jabber, m);
+		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+	}
+
+	node = lm_message_node_get_child (m->node, "si");
+	if (!node) {
+		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+	}
+
+	xmlns = lm_message_node_get_attribute (node, "xmlns");
+
+	if (xmlns && strcmp (xmlns, XMPP_FILE_TRANSFER_XMLNS) == 0) {
+		const gchar *profile;
+
+		profile = lm_message_node_get_attribute (node, "profile");
+		if (profile && strcmp (profile, XMPP_FILE_TRANSFER_PROFILE) == 0) {
+			jabber_ft_handle_request (jabber, m);
+			return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+		}
+	}
+
+	/* if a get, return error for unsupported IQ */
+	if (subtype == LM_MESSAGE_SUB_TYPE_GET ||
+	    subtype == LM_MESSAGE_SUB_TYPE_SET) {
+		/* do something:
+		   no Jabber spec for this that I could see (mjr) */
+		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+	}
+
+	return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+}
+
+/*
+ * receiving
+ */
+static void
+jabber_ft_handle_request (GossipJabber *jabber, 
+			  LmMessage    *m)
+{
+	GossipJabberFTs *fts;
+	const gchar     *id_str;
+	const gchar     *from_str;
+	GossipContact   *from;
+	GossipFT        *ft;
+	GossipFTId       id;             
+	LmMessageNode   *node;
+	const gchar     *file_name;
+	const gchar     *file_size;
+	const gchar     *file_mime;
+
+	fts = gossip_jabber_get_fts (jabber);
+	g_return_if_fail (fts != NULL);
+
+	id_str = lm_message_node_get_attribute (m->node, "id");
+
+	from_str = lm_message_node_get_attribute (m->node, "from");
+	from = gossip_jabber_get_contact_from_jid (jabber, from_str, NULL);	
+
+	node = lm_message_node_find_child (m->node, "si");
+	file_mime = lm_message_node_get_attribute (node, "mime-type"); 
+	
+	node = lm_message_node_find_child (m->node, "file");
+	file_name = lm_message_node_get_attribute (node, "name"); 
+	file_size = lm_message_node_get_attribute (node, "size"); 
+
+	d(g_print("ProtocolFT: File transfer request from:'%s' with file:'%s', size:'%s'\n", 
+		  from_str,
+		  file_name,
+		  file_size));
+	
+	ft = g_object_new (GOSSIP_TYPE_FT, 
+			   "type", GOSSIP_FT_TYPE_RECEIVING,
+			   "contact", from,
+			   "file-name", file_name, 
+			   "file-size", g_ascii_strtoull (file_size, NULL, 10),
+			   "file-mime-type", file_mime,
+			   NULL);
+	
+	g_object_get (ft, "id", &id, NULL);
+
+	g_hash_table_insert (fts->str_ids, &id, g_strdup (id_str));
+	g_hash_table_insert (fts->ft_ids, g_strdup (id_str), ft);
+	g_hash_table_insert (fts->remote_ids, &id, g_strdup (from_str));
+
+	/* signal */
+	g_signal_emit_by_name (fts->jabber, 
+			       "file-transfer-request", 
+			       ft);
+}
+
+static void
+jabber_ft_handle_error (GossipJabber *jabber, 
+			LmMessage    *m)
+{
+	GossipJabberFTs *fts;
+	GossipFT        *ft;
+	GossipFTError    error_code;
+	const gchar     *error_code_str;
+	const gchar     *error_reason;
+	const gchar     *id_str;
+	const gchar     *from_str;
+	GossipContact   *from;
+	LmMessageNode   *node;
+
+	fts = gossip_jabber_get_fts (jabber);
+	g_return_if_fail (fts != NULL);
+
+	id_str = lm_message_node_get_attribute (m->node, "id");
+
+	from_str = lm_message_node_get_attribute (m->node, "from");
+	from = gossip_jabber_get_contact_from_jid (jabber, from_str, NULL);	
+
+	node = lm_message_node_find_child (m->node, "error");
+	error_reason = lm_message_node_get_value (node);
+	error_code_str = lm_message_node_get_attribute (node, "code"); 
+
+	d(g_print("ProtocolFT: File transfer error from:'%s' with code:'%s', reason:'%s' \n", 
+		  from_str,
+		  error_code_str,
+		  error_reason));
+	
+
+	ft = g_hash_table_lookup (fts->ft_ids, id_str);
+	if (!ft) {
+		g_warning ("Could not find GossipFT* from id:'%s'", 
+			   id_str);
+		return;
+	}
+
+	switch (atoi (error_code_str)) {
+	case 400:
+		error_code = GOSSIP_FT_ERROR_UNSUPPORTED;
+		break;
+	case 403:
+		error_code = GOSSIP_FT_ERROR_DECLINED;
+		break;
+	default:
+		error_code = GOSSIP_FT_ERROR_UNKNOWN;
+		break;
+	}
+
+	/* signal */
+	jabber_ft_error (fts->jabber, 
+			 "file-transfer-error", 
+			 ft,
+			 error_code,
+			 error_reason ? error_reason : "");
+}
+
+static void
+jabber_ft_error (GossipJabber  *jabber,
+		 const gchar   *signal,
+		 GossipFT      *ft,
+		 GossipFTError  code,
+		 const gchar   *reason)
+{
+	GError        *error;
+	static GQuark  quark = 0;
+
+	g_return_if_fail (GOSSIP_IS_JABBER (jabber));
+	g_return_if_fail (GOSSIP_IS_FT (ft));
+	g_return_if_fail (signal != NULL);
+	g_return_if_fail (reason != NULL);
+
+	if (!quark) {
+		quark = g_quark_from_static_string ("gossip-jabber-ft");
+	}
+
+	error = g_error_new_literal (quark, code, reason);
+	g_signal_emit_by_name (jabber, signal, ft, error);
+ 	g_error_free (error); 
+}
+
+/*
+ * utils
+ */
+static gboolean
+jabber_ft_get_file_details (const gchar  *uri,
+			    gchar       **file_name,
+			    gchar       **file_size,
+			    gchar       **mime_type)
+{
+	GnomeVFSFileInfo file_info;
+	GnomeVFSResult   result;
+	/*  	GnomeVFSURI      *uri;  */
+
+	d(g_print("ProtocolFT: Getting file info for URI:'%s'\n", uri));
+
+	/*  	uri = gnome_vfs_uri_new (file_name); */
+
+	/* 	if (!gnome_vfs_uri_exists (uri)) { */
+	/* 		d(g_print("ProtocolFT: URI:'%s' does not exist\n", file_name)); */
+	/* 		gnome_vfs_uri_unref (uri); */
+	/* 		return; */
+	/* 	} */
+
+	result = gnome_vfs_get_file_info (uri,
+					  &file_info, 
+					  GNOME_VFS_FILE_INFO_DEFAULT);
+
+	if (result != GNOME_VFS_OK) {
+		g_warning ("ProtocolFT: Could not get file info for URI:'%s'", uri);
+		return FALSE;
+	}
+	
+	if (file_name) {
+		*file_name = g_strdup (file_info.name);
+	}
+
+	if (file_size) {
+		*file_size = g_strdup_printf ("%d", (guint)file_info.size);
+	}
+
+	if (mime_type) {
+		gchar *s;
+
+		s = gnome_vfs_get_mime_type (uri);
+		*mime_type = s;
+
+		if (!s) {
+			*mime_type = g_strdup (GNOME_VFS_MIME_TYPE_UNKNOWN);
+		} 
+	}
+
+	gnome_vfs_file_info_unref (&file_info);
+	
+	return TRUE;
+}
+
+static gchar *
+jabber_ft_get_contact_last_jid (GossipContact *contact)
+{
+	GossipPresence *presence;
+	const gchar    *resource;
+	gchar          *to;
+
+	/* note: this function gets the JID for the contact based on
+	   the last resource they sent a message to us from, so it
+	   makes sure we send the request or do things with the JID at
+	   the last location they spoke to us from */
+
+	presence = gossip_contact_get_active_presence (contact);
+	resource = gossip_presence_get_resource (presence);
+
+	to = g_strdup_printf ("%s/%s", 
+			      gossip_contact_get_id (contact),
+			      resource);
+
+	return to;
+}
+
+/*
+ * sending
+ */
+
+GossipFTId 
+gossip_jabber_ft_send (GossipJabberFTs *fts,
+		       GossipContact   *contact,
+		       const gchar     *file)
+{
+	GossipFT      *ft;
+	GossipFTId     id;
+	const gchar   *id_str;
+	GossipContact *own_contact;
+	LmConnection  *connection;
+	LmMessage     *m;
+	LmMessageNode *node, *si_node, *field_node;
+	gchar         *to;
+	gchar         *file_size;
+	gchar         *file_name;
+	gchar         *mime_type;
+	gboolean       ok;
+
+	g_return_val_if_fail (fts != NULL, 0);
+	g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), 0);
+	g_return_val_if_fail (file != NULL, 0);
+
+	connection = gossip_jabber_get_connection (fts->jabber);
+	own_contact = gossip_jabber_get_own_contact (fts->jabber);
+
+	to = jabber_ft_get_contact_last_jid (contact);
+
+	ok = jabber_ft_get_file_details (file, 
+					 &file_name, 
+					 &file_size,
+					 &mime_type);
+	if (!ok) {
+		return 0;
+	}
+
+	m = lm_message_new_with_sub_type (to,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_SET);
+	node = m->node;
+
+	id_str = lm_message_node_get_attribute (m->node, "id");
+
+	lm_message_node_set_attribute (node, "from", 
+				       gossip_contact_get_id (own_contact));
+
+	node = lm_message_node_add_child (node, "si", NULL);
+	lm_message_node_set_attributes (node, 
+					"profile", XMPP_FILE_TRANSFER_PROFILE,
+ 					"mime-type", mime_type, 
+					"id", "ft1",
+					"xmlns", XMPP_FILE_TRANSFER_XMLNS,
+					NULL);
+
+	si_node = node;
+
+	node = lm_message_node_add_child (si_node, "file", NULL);
+	lm_message_node_set_attributes (node, 
+					"size", file_size,
+					"name", file_name,
+					"xmlns", XMPP_FILE_XMLNS,
+					NULL);
+
+	node = lm_message_node_add_child (si_node, "feature", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_FEATURE_XMLNS,
+					NULL);
+
+	node = lm_message_node_add_child (node, "x", NULL);
+	lm_message_node_set_attributes (node, 
+					"type", "form",
+					"xmlns", "jabber:x:data",
+					NULL);
+
+	node = lm_message_node_add_child (node, "field", NULL);
+	lm_message_node_set_attributes (node, 
+					"type", "list-single",
+					"var", "stream-method",
+					NULL);
+
+	field_node = node;
+
+	/* we do not support this yet */
+/*  	node = lm_message_node_add_child (field_node, "option", NULL);  */
+/*  	lm_message_node_add_child (node, "value", XMPP_BYTESTREAMS_PROTOCOL);  */
+
+ 	node = lm_message_node_add_child (field_node, "option", NULL);
+ 	lm_message_node_add_child (node, "value", XMPP_IBB_PROTOCOL); 
+
+	/* send */
+	d(g_print("ProtocolFT: Sending file transfer request for URI:'%s'\n", file));
+
+ 	lm_connection_send (connection, m, NULL); 
+
+	/* create object */
+	ft = g_object_new (GOSSIP_TYPE_FT, 
+			   "type", GOSSIP_FT_TYPE_SENDING,
+			   "contact", contact,
+			   "file-name", file_name, 
+			   "file-size", g_ascii_strtoull (file_size, NULL, 10),
+			   "file-mime-type", mime_type,
+			   NULL);
+	
+	g_object_get (ft, "id", &id, NULL);
+
+	g_hash_table_insert (fts->str_ids, &id, g_strdup (id_str));
+	g_hash_table_insert (fts->ft_ids, g_strdup (id_str), ft);
+	g_hash_table_insert (fts->remote_ids, &id, to);
+
+	/* clean up */
+	lm_message_unref (m);
+
+	g_free (file_name);
+	g_free (file_size);
+	g_free (mime_type);
+
+	return id;
+}
+
+void 
+gossip_jabber_ft_accept (GossipJabberFTs *fts,
+			 GossipFTId       id) 
+{
+	GossipContact *own_contact;
+	const gchar   *id_str;
+	const gchar   *to_str;
+	LmConnection  *connection;
+	LmMessage     *m;
+	LmMessageNode *node;
+	
+	g_return_if_fail (fts != NULL);
+
+	d(g_print("ProtocolFT: Accepting file transfer for GossipFTId:%d\n", id));
+
+	connection = gossip_jabber_get_connection (fts->jabber);
+	own_contact = gossip_jabber_get_own_contact (fts->jabber);
+
+	to_str = g_hash_table_lookup (fts->remote_ids, &id);
+	id_str = g_hash_table_lookup (fts->str_ids, &id);
+
+	if (!to_str) {
+		g_warning ("ProtocolFT: Could not get remote JID from GossipFTId:%d", id);
+		return;
+	}
+
+	if (!id_str) {
+		g_warning ("ProtocolFT: Could not get original message id from GossipFTId:%d", id);
+		return;
+	}
+
+	m = lm_message_new_with_sub_type (to_str,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_RESULT);
+	node = m->node;
+	lm_message_node_set_attributes (node, 
+					"id", id_str,
+					"from", gossip_contact_get_id (own_contact),
+					NULL);
+
+	node = lm_message_node_add_child (node, "si", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_FILE_TRANSFER_XMLNS,
+					NULL);
+
+	node = lm_message_node_add_child (node, "feature", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_FEATURE_XMLNS,
+					NULL);
+
+	node = lm_message_node_add_child (node, "x", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", "jabber:x:data",
+					"type", "submit",
+					NULL);
+
+	node = lm_message_node_add_child (node, "field", NULL);
+	lm_message_node_set_attributes (node, 
+					"var", "stream-method",
+					NULL);
+
+	/* choose method here, currently we only support one */
+	lm_message_node_add_child (node, "value", XMPP_IBB_PROTOCOL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);
+}
+
+void 
+gossip_jabber_ft_decline (GossipJabberFTs *fts,
+			  GossipFTId       id) 
+{
+	GossipContact *own_contact;
+	const gchar   *id_str;
+	const gchar   *to_str;
+	LmConnection  *connection;
+	LmMessage     *m;
+	LmMessageNode *node;
+
+	g_return_if_fail (fts != NULL);
+
+	d(g_print("ProtocolFT: Declining file transfer for GossipFTId:%d\n", id));
+
+	connection = gossip_jabber_get_connection (fts->jabber);
+	own_contact = gossip_jabber_get_own_contact (fts->jabber);
+
+	to_str = g_hash_table_lookup (fts->remote_ids, &id);
+	id_str = g_hash_table_lookup (fts->str_ids, &id);
+
+	if (!to_str) {
+		g_warning ("ProtocolFT: Could not get remote JID from GossipFTId:%d", id);
+		return;
+	}
+
+	if (!id_str) {
+		g_warning ("ProtocolFT: Could not get original message id from GossipFTId:%d", id);
+		return;
+	}
+
+	m = lm_message_new_with_sub_type (to_str,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_ERROR);
+	node = m->node;
+
+	lm_message_node_set_attributes (node, 
+					"id", id_str,	
+					"from", gossip_contact_get_id (own_contact),
+					NULL);
+
+	node = lm_message_node_add_child (node, "error", "Declined");
+	lm_message_node_set_attributes (node, 
+					"code", "403",
+					NULL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);	
+
+	/* FIXME: clean up hash tables */
+	
+}
+
+void
+gossip_jabber_ft_cancel (GossipJabberFTs *fts,
+			 GossipFTId       id)
+{
+	g_return_if_fail (fts != NULL);
+
+/* 	room = (JabberChatroom*) g_hash_table_lookup (chatrooms->room_id_hash,  */
+/* 						       GINT_TO_POINTER (id)); */
+}
+		
+
+/*
+ * stream stuff
+ */
+
+void
+gossip_jabber_ft_iib_start (GossipJabber *jabber,
+			    const gchar  *to)
+{
+	LmConnection *connection;
+	LmMessage     *m;
+	LmMessageNode *node;
+
+	const gchar   *sid = "test";
+	const gchar   *block_size = "4096";
+
+	g_return_if_fail (to != NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+
+	m = lm_message_new_with_sub_type (to,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_SET);
+	node = m->node;
+
+	node = lm_message_node_add_child (node, "open", NULL);
+	lm_message_node_set_attributes (node, 
+					"sid", sid,
+					"block-size", block_size,
+					"xmlns", XMPP_IBB_PROTOCOL,
+					NULL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_start_response (GossipJabber *jabber,
+				     const gchar  *to,
+				     const gchar  *id)
+{
+	LmConnection *connection;
+	LmMessage    *m;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (id != NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+
+	m = lm_message_new_with_sub_type (to,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_RESULT);
+	lm_message_node_set_attributes (m->node, 
+					"id", id,
+					NULL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);
+}
+
+
+void
+gossip_jabber_ft_iib_error (GossipJabber *jabber,
+			    const gchar  *to,
+			    const gchar  *id,
+			    const gchar  *error_code,
+			    const gchar  *error_type)
+{
+	LmConnection *connection;
+	LmMessage     *m;
+	LmMessageNode *node;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (id != NULL);
+	g_return_if_fail (error_code != NULL);
+	g_return_if_fail (error_type != NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+
+	m = lm_message_new_with_sub_type (to,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_ERROR);
+
+	node = m->node;
+
+	lm_message_node_set_attributes (node, 
+					"id", id,
+					NULL);
+
+	node = lm_message_node_add_child (node, "error", NULL);
+	lm_message_node_set_attributes (node, 
+					"code", error_code,
+					"type", error_type,
+					NULL);
+
+	node = lm_message_node_add_child (node, "feature-not-implemented", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", IMPP_ERROR_XMLNS,
+					NULL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_send (GossipJabber *jabber,
+			   const gchar  *to,
+			   const gchar  *sid,
+			   const gchar  *data,
+			   const gchar  *seq)
+{
+	LmConnection *connection;
+	LmMessage     *m;
+	LmMessageNode *node, *amp_node;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (sid != NULL);
+	g_return_if_fail (data != NULL);
+	g_return_if_fail (seq != NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+
+	m = lm_message_new (to, LM_MESSAGE_TYPE_MESSAGE);
+
+	node = m->node;
+
+	node = lm_message_node_add_child (node, "data", data);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_IBB_PROTOCOL,
+					"sid", sid, 
+					"seq", seq,
+					NULL);
+
+	node = lm_message_node_add_child (node, "amp", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_AMP_XMLNS,
+					NULL);
+	
+	amp_node = node;
+
+	node = lm_message_node_add_child (amp_node, "rule", NULL);
+	lm_message_node_set_attributes (node, 
+					"condition", "deliver-at",
+					"value", "stored",
+					"action", "error",
+					NULL);
+
+	node = lm_message_node_add_child (amp_node, "rule", NULL);
+	lm_message_node_set_attributes (node, 
+					"condition", "match-resource",
+					"value", "exact",
+					"action", "error",
+					NULL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_finish (GossipJabber *jabber,
+			     const gchar  *to,
+			     const gchar  *sid)
+{
+	LmConnection *connection;
+	LmMessage     *m;
+	LmMessageNode *node;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (sid != NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+
+	m = lm_message_new_with_sub_type (to, 
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_SET);
+
+	node = m->node;
+
+	node = lm_message_node_add_child (node, "close", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_IBB_PROTOCOL,
+					"sid", sid, 
+					NULL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_finish_response (GossipJabber *jabber,
+				      const gchar  *to,
+				      const gchar  *id)
+{
+	LmConnection *connection;
+	LmMessage    *m;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (id != NULL);
+
+	connection = gossip_jabber_get_connection (jabber);
+
+	m = lm_message_new_with_sub_type (to,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_RESULT);
+	lm_message_node_set_attributes (m->node, 
+					"id", id,
+					NULL);
+
+	/* send */
+ 	lm_connection_send (connection, m, NULL); 
+	lm_message_unref (m);
+}
+
Index: protocols/jabber/gossip-jabber-ft.h
===================================================================
RCS file: protocols/jabber/gossip-jabber-ft.h
diff -N protocols/jabber/gossip-jabber-ft.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ protocols/jabber/gossip-jabber-ft.h	16 Nov 2005 21:45:32 -0000
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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.
+ */
+
+#ifndef __GOSSIP_JABBER_FT_H__
+#define __GOSSIP_JABBER_FT_H__
+
+#include <glib.h>
+
+#include <libgossip/gossip-ft-provider.h>
+
+#include "gossip-jabber.h"
+
+typedef struct _GossipJabberFTs GossipJabberFTs;
+
+
+GossipJabberFTs *gossip_jabber_ft_init                (GossipJabber    *jabber);
+void             gossip_jabber_ft_finalize            (GossipJabberFTs *fts);
+GossipFTId       gossip_jabber_ft_send                (GossipJabberFTs *fts,
+						       GossipContact   *contact,
+						       const gchar     *file_name);
+void             gossip_jabber_ft_accept              (GossipJabberFTs *fts,
+						       GossipFTId       id);
+void             gossip_jabber_ft_decline             (GossipJabberFTs *fts,
+						       GossipFTId       id);
+void             gossip_jabber_ft_cancel              (GossipJabberFTs *fts,
+						       GossipFTId       id);
+void             gossip_jabber_ft_send_response       (GossipJabber    *jabber,
+						       const gchar     *to,
+						       const gchar     *id);
+
+/*
+ * stream API
+ */
+void             gossip_jabber_ft_iib_start           (GossipJabber    *jabber,
+						       const gchar     *to);
+void             gossip_jabber_ft_iib_start_response  (GossipJabber    *jabber,
+						       const gchar     *to,
+						       const gchar     *id);
+void             gossip_jabber_ft_iib_error           (GossipJabber    *jabber,
+						       const gchar     *to,
+						       const gchar     *id,
+						       const gchar     *error_code,
+						       const gchar     *error_type);
+void             gossip_jabber_ft_iib_send            (GossipJabber    *jabber,
+						       const gchar     *to,
+						       const gchar     *sid,
+						       const gchar     *data,
+						       const gchar     *seq);
+void             gossip_jabber_ft_iib_finish          (GossipJabber    *jabber,
+						       const gchar     *to,
+						       const gchar     *sid);
+void             gossip_jabber_ft_iib_finish_response (GossipJabber    *jabber,
+						       const gchar     *to,
+						       const gchar     *id);
+
+
+#endif /* __GOSSIP_JABBER_FT_H__ */
Index: protocols/jabber/gossip-jabber-private.h
===================================================================
RCS file: protocols/jabber/gossip-jabber-private.h
diff -N protocols/jabber/gossip-jabber-private.h
--- protocols/jabber/gossip-jabber-private.h	30 Apr 2005 11:43:52 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,31 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2005 Imendio AB
- *
- * 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.
- */
-
-#ifndef __GOSSIP_JABBER_PRIVATE_H__
-#define __GOSSIP_JABBER_PRIVATE_H__
-
-#include <loudmouth/loudmouth.h> 
-
-#include "gossip-jabber.h"
-
-LmConnection * _gossip_jabber_get_connection (GossipJabber  *jabber);
-
-#endif
-
Index: protocols/jabber/gossip-jabber.c
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-jabber.c,v
retrieving revision 1.45
diff -u -r1.45 gossip-jabber.c
--- protocols/jabber/gossip-jabber.c	1 Nov 2005 00:22:27 -0000	1.45
+++ protocols/jabber/gossip-jabber.c	16 Nov 2005 21:45:34 -0000
@@ -38,16 +38,20 @@
 #include <libgossip/gossip-vcard.h>
 #include <libgossip/gossip-utils.h>
 #include <libgossip/gossip-chatroom-provider.h>
+#include <libgossip/gossip-ft-provider.h>
 
 #include "gossip-jabber-chatrooms.h"
-#include "gossip-jabber-private.h"
+#include "gossip-jabber-ft.h"
 #include "gossip-jabber-vcard.h"
 #include "gossip-jabber-services.h"
 #include "gossip-jabber-utils.h"
 #include "gossip-transport-accounts.h"
 #include "gossip-jabber.h"
+#include "gossip-jabber-private.h"
 
-#define d(x)
+#define d(x) x
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_JABBER, GossipJabberPriv))
 
 #define XMPP_VERSION_XMLNS  "jabber:iq:version"
 #define XMPP_ROSTER_XMLNS   "jabber:iq:roster"
@@ -67,7 +71,9 @@
 
 	GHashTable            *contacts;
 
+	/* extended parts */
 	GossipJabberChatrooms *chatrooms;
+	GossipJabberFTs       *fts;
 
 	/* used to hold a list of composing message ids, this is so we
 	   can send the cancelation to the last message id */
@@ -108,7 +114,6 @@
 							     GossipAccount                *account);
 static void             jabber_login                        (GossipProtocol               *protocol);
 static gboolean         jabber_login_timeout_cb             (GossipJabber                 *jabber);
-
 static void             jabber_logout                       (GossipProtocol               *protocol);
 static gboolean         jabber_logout_contact_foreach       (gpointer                      key,
 							     GossipContact                *contact,
@@ -173,9 +178,6 @@
 							     GossipContact                *contact,
 							     RenameGroupData              *rg);
 static GossipPresence * jabber_get_presence                 (LmMessage                    *message);
-static GossipContact *  jabber_get_contact_from_jid         (GossipJabber                 *jabber,
-							     const gchar                  *jid,
-							     gboolean                     *new_item);
 static const GList *    jabber_get_contacts                 (GossipProtocol               *protocol);
 static const gchar *    jabber_get_active_resource          (GossipProtocol               *protocol,
 							     GossipContact                *contact);
@@ -207,7 +209,7 @@
 							     LmConnection                 *conn,
 							     LmMessage                    *message,
 							     GossipJabber                 *jabber);
-static LmHandlerResult  jabber_iq_handler                   (LmMessageHandler             *handler,
+static LmHandlerResult  jabber_iq_query_handler             (LmMessageHandler             *handler,
 							     LmConnection                 *conn,
 							     LmMessage                    *message,
 							     GossipJabber                 *jabber);
@@ -223,6 +225,8 @@
 							     LmMessage                    *m);
 
 
+
+
 /* chatrooms */
 static void             jabber_chatroom_init                (GossipChatroomProviderIface  *iface);
 static GossipChatroomId jabber_chatroom_join                (GossipChatroomProvider       *provider,
@@ -258,11 +262,30 @@
 static GList *          jabber_chatroom_get_rooms           (GossipChatroomProvider       *provider);
 
 
+
+
+/* fts */
+static void             jabber_ft_init                      (GossipFTProviderIface        *iface);
+static GossipFTId       jabber_ft_send                      (GossipFTProvider             *provider,
+							     GossipContact                *contact,
+							     const gchar                  *file);
+static void             jabber_ft_cancel                    (GossipFTProvider             *provider,
+							     GossipFTId                    id);
+static void             jabber_ft_accept                    (GossipFTProvider             *provider,
+							     GossipFTId                    id);
+static void             jabber_ft_decline                   (GossipFTProvider             *provider,
+							     GossipFTId                    id);
+
+
 extern GConfClient *gconf_client;
 
+
 G_DEFINE_TYPE_WITH_CODE (GossipJabber, gossip_jabber, GOSSIP_TYPE_PROTOCOL,
 			 G_IMPLEMENT_INTERFACE (GOSSIP_TYPE_CHATROOM_PROVIDER,
-						jabber_chatroom_init));
+						jabber_chatroom_init);
+			 G_IMPLEMENT_INTERFACE (GOSSIP_TYPE_FT_PROVIDER,
+						jabber_ft_init));
+
 
 static void
 gossip_jabber_class_init (GossipJabberClass *klass)
@@ -293,15 +316,16 @@
 	protocol_class->get_vcard           = jabber_get_vcard;
 	protocol_class->set_vcard           = jabber_set_vcard;
 	protocol_class->get_version         = jabber_get_version;
+
+	g_type_class_add_private (object_class, sizeof (GossipJabberPriv));
 }
 
 static void
 gossip_jabber_init (GossipJabber *jabber)
 {
-	GossipJabberPriv *priv;
+ 	GossipJabberPriv *priv; 
 
-	priv = g_new0 (GossipJabberPriv, 1);
-	jabber->priv = priv;
+	priv = GET_PRIV (jabber);
 
 	priv->contacts = 
 		g_hash_table_new_full (g_str_hash,
@@ -323,13 +347,15 @@
  	GossipJabberPriv *priv;
 
  	jabber = GOSSIP_JABBER (obj);
- 	priv   = jabber->priv;
+ 	priv = GET_PRIV (jabber);
 
  	g_object_unref (priv->account);
 	
  	g_hash_table_destroy (priv->contacts);
 
- 	gossip_jabber_chatrooms_free (priv->chatrooms);
+	/* finalize extended modules */
+ 	gossip_jabber_chatrooms_finalize (priv->chatrooms);
+	gossip_jabber_ft_finalize (priv->fts);
 
  	g_hash_table_destroy (priv->composing_ids);
 
@@ -351,34 +377,34 @@
  	GossipJabber     *jabber;
  	GossipJabberPriv *priv;
  	LmMessageHandler *handler;
-	const gchar      *jid_str;
+	const gchar      *id;
+	const gchar      *host;
 	gchar            *name;
-	gchar            *host;
- 	gchar            *id;
+	GossipJID        *jid;
 	
  	g_return_if_fail (GOSSIP_IS_JABBER (protocol));
-  	g_return_if_fail (account != NULL);
+  	g_return_if_fail (GOSSIP_IS_ACCOUNT (account));
 	
  	jabber = GOSSIP_JABBER (protocol);
- 	priv   = jabber->priv;
+ 	priv = GET_PRIV (jabber);
  	
  	priv->account = g_object_ref (account);
  
  	priv->contact = gossip_contact_new (GOSSIP_CONTACT_TYPE_USER,
 					    priv->account);
  
-	jid_str = gossip_account_get_id (account);
-	name = gossip_utils_jid_str_get_part_name (jid_str);
-	host = gossip_utils_jid_str_get_part_host (jid_str);
+	id = gossip_account_get_id (account);
+	jid = gossip_jid_new (id);
+
+	name = gossip_jid_get_part_name (jid);
+	host = gossip_jid_get_part_host (jid);
 
-	id = g_strdup_printf ("%s@%s", name, host);
 	g_object_set (priv->contact,
-		      "id", id,
+		      "id", id,          /* we need FULL JID here */
 		      "name", name,
 		      NULL);
 
 	g_free (name);
-	g_free (host);
 
 	priv->connection = lm_connection_new (gossip_account_get_server (account));
 
@@ -390,8 +416,9 @@
 					       jabber, NULL);
 
 	lm_connection_set_port (priv->connection, gossip_account_get_port (account));
-	lm_connection_set_jid (priv->connection, id);
-	g_free (id);
+	lm_connection_set_jid (priv->connection, gossip_jid_get_without_resource (jid));
+
+	gossip_jid_unref (jid);
 
 	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_message_handler,
 					  jabber, NULL);
@@ -409,7 +436,7 @@
 						LM_HANDLER_PRIORITY_NORMAL);
 	lm_message_handler_unref (handler);
 
-	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_iq_handler,
+	handler = lm_message_handler_new ((LmHandleMessageFunction) jabber_iq_query_handler,
 					  jabber, NULL);
 	lm_connection_register_message_handler (priv->connection,
 						handler,
@@ -417,8 +444,9 @@
 						LM_HANDLER_PRIORITY_NORMAL);
 	lm_message_handler_unref (handler);
 
-	priv->chatrooms = gossip_jabber_chatrooms_new (jabber, 
-						       priv->connection);
+	/* initiate extended modules */
+	priv->chatrooms = gossip_jabber_chatrooms_init (jabber);
+	priv->fts = gossip_jabber_ft_init (jabber);
 
 #ifdef USE_TRANSPORTS
 	/* initialise the jabber accounts module which is necessary to
@@ -427,14 +455,6 @@
 #endif
 }
 
-LmConnection *
-_gossip_jabber_get_connection (GossipJabber *jabber)
-{
-	g_return_val_if_fail (GOSSIP_IS_JABBER (jabber), NULL);
-
-	return jabber->priv->connection;
-}
-
 static void
 jabber_login (GossipProtocol *protocol)
 {
@@ -446,7 +466,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (protocol));
 	
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	d(g_print ("Protocol: Logging in Jabber\n"));
 
@@ -528,7 +548,7 @@
 {
 	GossipJabberPriv *priv;
 
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	priv->connection_timeout_id = 0;
 
@@ -548,7 +568,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (protocol));
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	if (priv->connection_timeout_id != 0) {
 		g_source_remove (priv->connection_timeout_id);
@@ -586,7 +606,7 @@
 	g_return_if_fail (reason != NULL);
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	if (!quark) {
 		quark = g_quark_from_static_string ("gossip-jabber");
@@ -610,7 +630,7 @@
 	const gchar      *resource;
 	gchar            *password = NULL;
 	
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	if (priv->connection_timeout_id != 0) {
 		g_source_remove (priv->connection_timeout_id);
@@ -648,6 +668,8 @@
 
 	id = gossip_utils_jid_str_get_part_name (jid_str);
 	resource = gossip_utils_jid_str_locate_resource (jid_str);
+
+	d(g_print ("Protocol: Using JabberID:'%s'\n", jid_str));
 	
 	lm_connection_authenticate (priv->connection,
 				    id,
@@ -669,7 +691,7 @@
 	LmMessage        *m;
 	LmMessageNode    *node;
 	
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	if (result == FALSE) {
 		jabber_error (GOSSIP_PROTOCOL (jabber), 
@@ -708,7 +730,7 @@
 {
 	GossipJabberPriv *priv;
 
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	if (priv->connection_timeout_id != 0) {
 		g_source_remove (priv->connection_timeout_id);
@@ -780,7 +802,7 @@
 	g_return_val_if_fail (callback != NULL, FALSE);
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	ra = g_new0 (RegisterAccountData, 1);
 	
@@ -984,7 +1006,7 @@
 	g_return_val_if_fail (GOSSIP_IS_JABBER (protocol), FALSE);
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	if (priv->connection == NULL) {
 		return FALSE;
@@ -1008,7 +1030,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (protocol));
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	recipient = gossip_message_get_recipient (message);
 
@@ -1065,7 +1087,7 @@
 	g_return_if_fail (GOSSIP_IS_CONTACT (contact));
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	contact_id = gossip_contact_get_id (contact);
 
@@ -1124,7 +1146,7 @@
 	const gchar         *priority;
 	
 	jabber = GOSSIP_JABBER (protocol);
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	if (priv->presence) {
 		g_object_unref (priv->presence);
@@ -1206,7 +1228,7 @@
 	GossipContact    *contact;
 
         jabber = GOSSIP_JABBER (protocol);
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	jid = gossip_jid_new (id);
 	contact = g_hash_table_lookup (priv->contacts, 
@@ -1230,7 +1252,7 @@
         LmMessageNode    *node;
 
         jabber = GOSSIP_JABBER (protocol);
-        priv   = jabber->priv;
+        priv = GET_PRIV (jabber);
 
         /* Request subscription */
         m = lm_message_new_with_sub_type (id, LM_MESSAGE_TYPE_PRESENCE,
@@ -1273,7 +1295,7 @@
 	GList            *l; 
 	
 	jabber = GOSSIP_JABBER (protocol);
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	m = lm_message_new_with_sub_type (NULL, 
 					  LM_MESSAGE_TYPE_IQ,
@@ -1312,7 +1334,7 @@
         LmMessageNode    *node;
 	
 	jabber = GOSSIP_JABBER (protocol);
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	m = lm_message_new_with_sub_type (NULL,
  					  LM_MESSAGE_TYPE_IQ,
@@ -1361,7 +1383,7 @@
 	RenameGroupData  *rg;
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	rg = g_new0 (RenameGroupData, 1);
 	
@@ -1390,7 +1412,7 @@
 	GList            *l; 
 	gboolean          found = FALSE;
 
-	priv = rg->jabber->priv;
+	priv = GET_PRIV (rg->jabber);
 
         for (l = gossip_contact_get_groups (contact); l && !found; l = l->next) {
 		gchar *group = (gchar*)l->data;
@@ -1482,52 +1504,6 @@
 	return presence;
 }
 
-static GossipContact *
-jabber_get_contact_from_jid (GossipJabber *jabber, 
-			     const gchar  *jid_str,
-			     gboolean     *new_item)
-{
-	GossipJabberPriv *priv;
-	GossipContact    *contact;
-	GossipJID        *jid;
-	gchar            *name;
-	gboolean          tmp_new_item = FALSE;
-
-	/* FIXME: Lookup contact in hash table */
-	priv = jabber->priv;
-
-	jid = gossip_jid_new (jid_str);
-	d(g_print ("Protocol: Get contact: %s\n", gossip_jid_get_without_resource (jid)));
-
-	contact = g_hash_table_lookup (priv->contacts, 
-				       gossip_jid_get_without_resource (jid));
-
-	if (!contact) {
-		d(g_print ("Protocol: New contact\n"));
-		contact = gossip_contact_new (GOSSIP_CONTACT_TYPE_TEMPORARY,
-					      priv->account);
-		gossip_contact_set_id (contact, 
-				       gossip_jid_get_without_resource (jid));
-
-		name = gossip_jid_get_part_name (jid);
-		gossip_contact_set_name (contact, name);
-		g_free (name);
-		tmp_new_item = TRUE;
-
-		g_hash_table_insert (priv->contacts, 
-				     g_strdup (gossip_contact_get_id (contact)),
-				     g_object_ref (contact));
-	}
-
-	gossip_jid_unref (jid);
-
-	if (new_item) {
-		*new_item = tmp_new_item;
-	}
-
-	return contact;
-}
-
 static const GList *
 jabber_get_contacts (GossipProtocol *protocol)
 {
@@ -1551,7 +1527,7 @@
 	GList            *list = NULL;
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	g_hash_table_foreach (priv->contacts, 
 			      (GHFunc)jabber_get_groups_foreach_cb, 
@@ -1599,7 +1575,7 @@
 	GossipJabberPriv *priv; 
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	return gossip_jabber_services_get_version (priv->connection,
 						   contact,
@@ -1619,7 +1595,7 @@
 	const gchar      *jid_str;
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	if (contact) {
 		jid_str = gossip_contact_get_id (contact);
@@ -1643,7 +1619,7 @@
 	GossipJabberPriv *priv; 
 
 	jabber = GOSSIP_JABBER (protocol);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	return gossip_jabber_vcard_set (priv->connection,
 					vcard,
@@ -1719,7 +1695,7 @@
 	const gchar      *body = "";
 	LmMessageNode    *node;
 
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	d(g_print ("Protocol: New message from: %s\n", 
 		   lm_message_node_get_attribute (m->node, "from")));
@@ -1730,7 +1706,7 @@
 	case LM_MESSAGE_SUB_TYPE_CHAT:
 	case LM_MESSAGE_SUB_TYPE_HEADLINE: /* For now, fixes #120009 */
 		from_str = lm_message_node_get_attribute (m->node, "from");
-		from = jabber_get_contact_from_jid (jabber, from_str, NULL);
+		from = gossip_jabber_get_contact_from_jid (jabber, from_str, NULL);
 		
 		message = gossip_message_new (GOSSIP_MESSAGE_TYPE_NORMAL,
 					      priv->contact);
@@ -1795,7 +1771,7 @@
 	const gchar      *type;
 	gboolean          new_item = FALSE;
 
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	from = lm_message_node_get_attribute (m->node, "from");
         d(g_print ("Protocol: New presence from: %s\n", 
@@ -1806,7 +1782,7 @@
 		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
 	}
 	
-	contact = jabber_get_contact_from_jid (jabber, from, &new_item); 
+	contact = gossip_jabber_get_contact_from_jid (jabber, from, &new_item); 
 
 	type = lm_message_node_get_attribute (m->node, "type");
 	if (!type) {
@@ -1859,10 +1835,10 @@
 }
 
 static LmHandlerResult
-jabber_iq_handler (LmMessageHandler *handler,
-		   LmConnection     *conn,
-		   LmMessage        *m,
-		   GossipJabber     *jabber)
+jabber_iq_query_handler (LmMessageHandler *handler,
+			 LmConnection     *conn,
+			 LmMessage        *m,
+			 GossipJabber     *jabber)
 {
 	GossipJabberPriv *priv;
 	LmMessageNode    *node;
@@ -1882,13 +1858,12 @@
 	}
 
 	xmlns = lm_message_node_get_attribute (node, "xmlns");
-
-	if (!xmlns || strcmp (xmlns, XMPP_ROSTER_XMLNS) == 0) {
+	if (xmlns && strcmp (xmlns, XMPP_ROSTER_XMLNS) == 0) {
 		jabber_request_roster (jabber, m);
 		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
 	}
 
-	if (!xmlns || strcmp (xmlns, XMPP_REGISTER_XMLNS) == 0) {
+	if (xmlns && strcmp (xmlns, XMPP_REGISTER_XMLNS) == 0) {
 		/* do nothing at this point */
 		return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
 	}
@@ -1906,7 +1881,6 @@
 	}
 
 	return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
-        /*return LM_HANDLER_RESULT_REMOVE_MESSAGE; */
 }
 
 static LmHandlerResult
@@ -1966,7 +1940,8 @@
  */
 
 static void
-jabber_request_version (GossipJabber *jabber, LmMessage *m)
+jabber_request_version (GossipJabber *jabber,
+			LmMessage    *m)
 {
 	GossipJabberPriv  *priv;
 	LmMessage         *r;
@@ -1974,7 +1949,7 @@
 	LmMessageNode     *node;
 	GossipVersionInfo *info;
 
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	from = lm_message_node_get_attribute (m->node, "from");
 	id = lm_message_node_get_attribute (m->node, "id");
@@ -2016,12 +1991,13 @@
 }
 
 static void
-jabber_request_roster (GossipJabber *jabber, LmMessage *m)
+jabber_request_roster (GossipJabber *jabber, 
+		       LmMessage    *m)
 {
 	GossipJabberPriv *priv;
 	LmMessageNode    *node;
 	
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 	
 	node = lm_message_node_get_child (m->node, "query");
 	if (!node) {
@@ -2052,7 +2028,7 @@
 			continue;
 		}
 
-		contact = jabber_get_contact_from_jid (jabber, jid_str, &new_item);
+		contact = gossip_jabber_get_contact_from_jid (jabber, jid_str, &new_item);
 		g_object_set (contact, "type", GOSSIP_CONTACT_TYPE_CONTACTLIST, NULL);
 
 		/* groups */
@@ -2133,7 +2109,8 @@
 }
 
 static void
-jabber_request_unknown (GossipJabber *jabber, LmMessage *m)
+jabber_request_unknown (GossipJabber *jabber, 
+			LmMessage    *m)
 {
 	GossipJabberPriv *priv;
 	LmMessageNode    *node;
@@ -2141,7 +2118,7 @@
 	LmMessage         *new_m;
 	const gchar       *from_str, *xmlns;
 
-	priv = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	/* get details */
 	from_str = lm_message_node_get_attribute (m->node, "from");
@@ -2207,7 +2184,7 @@
 	g_return_val_if_fail (GOSSIP_IS_JABBER (provider), 0);
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	return gossip_jabber_chatrooms_join (priv->chatrooms,
 					     room, server, nick, password, 
@@ -2225,15 +2202,15 @@
 	g_return_if_fail (id >= 1);
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	return gossip_jabber_chatrooms_cancel (priv->chatrooms, id);
 }
 
 static void
 jabber_chatroom_send (GossipChatroomProvider *provider,
-		       GossipChatroomId       id,
-		       const gchar           *message)
+		      GossipChatroomId        id,
+		      const gchar            *message)
 {
 	GossipJabber     *jabber;
 	GossipJabberPriv *priv;
@@ -2241,7 +2218,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (provider));
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	gossip_jabber_chatrooms_send (priv->chatrooms, id, message);
 }
@@ -2257,7 +2234,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (provider));
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	gossip_jabber_chatrooms_set_title (priv->chatrooms, id, new_title);
 }
@@ -2273,7 +2250,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (provider));
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	gossip_jabber_chatrooms_change_nick (priv->chatrooms, id, new_nick);
 }
@@ -2288,7 +2265,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (provider));
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	gossip_jabber_chatrooms_leave (priv->chatrooms, id);
 }
@@ -2303,7 +2280,7 @@
 	g_return_val_if_fail (GOSSIP_IS_JABBER (provider), NULL);
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	return gossip_jabber_chatrooms_get_room_name (priv->chatrooms, id);
 }
@@ -2320,7 +2297,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (provider));
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	gossip_jabber_chatrooms_invite (priv->chatrooms, id, contact_id, invite);
 }
@@ -2337,7 +2314,7 @@
 	g_return_if_fail (GOSSIP_IS_JABBER (provider));
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 	gossip_jabber_chatrooms_invite_accept (priv->chatrooms, 
 					       callback, 
@@ -2354,7 +2331,7 @@
 	g_return_val_if_fail (GOSSIP_IS_JABBER (provider), NULL);
 
 	jabber = GOSSIP_JABBER (provider);
-	priv   = jabber->priv;
+	priv = GET_PRIV (jabber);
 
 /* 	g_hash_table_foreach (priv->chatrooms->room_id_hash,  */
 /* 			      (GHFunc) jabber_chatrooms_foreach_set_presence, */
@@ -2364,33 +2341,173 @@
 	return gossip_jabber_chatrooms_get_rooms (priv->chatrooms);
 }
 
+/*
+ * ft
+ */
+
+static void
+jabber_ft_init (GossipFTProviderIface *iface)
+{
+	iface->send    = jabber_ft_send;
+	iface->cancel  = jabber_ft_cancel;
+	iface->accept  = jabber_ft_accept;
+	iface->decline = jabber_ft_decline;
+}
+
+static GossipFTId
+jabber_ft_send (GossipFTProvider *provider,
+		GossipContact    *contact,
+		const gchar      *file)
+{
+	GossipJabber     *jabber;
+	GossipJabberPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_JABBER (provider), 0);
+	g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), 0);
+	g_return_val_if_fail (file != NULL, 0);
+
+	jabber = GOSSIP_JABBER (provider);
+	priv = GET_PRIV (jabber);
+
+	return gossip_jabber_ft_send (priv->fts, contact, file);
+}
+
+static void
+jabber_ft_cancel (GossipFTProvider *provider,
+		  GossipFTId        id)
+{
+	GossipJabber     *jabber;
+	GossipJabberPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_JABBER (provider));
+	g_return_if_fail (id >= 1);
+
+	jabber = GOSSIP_JABBER (provider);
+	priv = GET_PRIV (jabber);
+
+	return gossip_jabber_ft_cancel (priv->fts, id);
+}
+
+static void
+jabber_ft_accept (GossipFTProvider *provider,
+		  GossipFTId        id)
+{
+	GossipJabber     *jabber;
+	GossipJabberPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_JABBER (provider));
+	g_return_if_fail (id >= 1);
+
+	jabber = GOSSIP_JABBER (provider);
+	priv = GET_PRIV (jabber);
+
+	return gossip_jabber_ft_accept (priv->fts, id);
+}
+
+static void
+jabber_ft_decline (GossipFTProvider *provider,
+		   GossipFTId        id)
+{
+	GossipJabber     *jabber;
+	GossipJabberPriv *priv;
+
+	g_return_if_fail (GOSSIP_IS_JABBER (provider));
+	g_return_if_fail (id >= 1);
+
+	jabber = GOSSIP_JABBER (provider);
+	priv = GET_PRIV (jabber);
+
+	return gossip_jabber_ft_decline (priv->fts, id);
+}
+
 /* 
  * external functions 
  */ 
 
+GossipAccount *
+gossip_jabber_get_account (GossipJabber *jabber)
+{
+	GossipJabberPriv *priv;
+	
+        g_return_val_if_fail (GOSSIP_IS_JABBER (jabber), NULL);
+	
+	priv = GET_PRIV (jabber);
+	
+	return priv->account;
+}
+
 GossipContact *
 gossip_jabber_get_own_contact (GossipJabber *jabber)
 {
+	GossipJabberPriv *priv;
+
 	g_return_val_if_fail (GOSSIP_IS_JABBER (jabber), NULL);
 
-	return jabber->priv->contact;
+	priv = GET_PRIV (jabber);
+
+	return priv->contact;
+}
+
+GossipContact *
+gossip_jabber_get_contact_from_jid (GossipJabber *jabber, 
+				    const gchar  *jid_str,
+				    gboolean     *new_item)
+{
+	GossipJabberPriv *priv;
+	GossipContact    *contact;
+	GossipJID        *jid;
+	gchar            *name;
+	gboolean          tmp_new_item = FALSE;
+
+	/* FIXME: Lookup contact in hash table */
+	priv = GET_PRIV (jabber);
+
+	jid = gossip_jid_new (jid_str);
+	d(g_print ("Protocol: Get contact: %s\n", gossip_jid_get_without_resource (jid)));
+
+	contact = g_hash_table_lookup (priv->contacts, 
+				       gossip_jid_get_without_resource (jid));
+
+	if (!contact) {
+		d(g_print ("Protocol: New contact\n"));
+		contact = gossip_contact_new (GOSSIP_CONTACT_TYPE_TEMPORARY,
+					      priv->account);
+		gossip_contact_set_id (contact, 
+				       gossip_jid_get_without_resource (jid));
+
+		name = gossip_jid_get_part_name (jid);
+		gossip_contact_set_name (contact, name);
+		g_free (name);
+
+		tmp_new_item = TRUE;
+
+		g_hash_table_insert (priv->contacts, 
+				     g_strdup (gossip_contact_get_id (contact)),
+				     g_object_ref (contact));
+	}
+
+	gossip_jid_unref (jid);
+
+	if (new_item) {
+		*new_item = tmp_new_item;
+	}
+
+	return contact;
 }
 
 void
 gossip_jabber_subscription_allow_all (GossipJabber *jabber)
 {
 	GossipJabberPriv *priv;
-	LmConnection     *connection;
 	LmMessageHandler *handler;
 
-	g_return_if_fail (jabber != NULL);
+	g_return_if_fail (GOSSIP_IS_JABBER (jabber));
 	
-	priv = jabber->priv;
-	connection = _gossip_jabber_get_connection (jabber);
+	priv = GET_PRIV (jabber);
 
 	handler = priv->subscription_handler;
 	if (handler) {
-		lm_connection_unregister_message_handler (connection, 
+		lm_connection_unregister_message_handler (priv->connection, 
 							  handler,
 							  LM_MESSAGE_TYPE_PRESENCE);
 		priv->subscription_handler = NULL;
@@ -2400,7 +2517,7 @@
 	handler = lm_message_handler_new ((LmHandleMessageFunction)jabber_subscription_message_handler, 
 					  jabber, NULL);
 
-	lm_connection_register_message_handler (connection,
+	lm_connection_register_message_handler (priv->connection,
 						handler,
 						LM_MESSAGE_TYPE_PRESENCE,
 						LM_HANDLER_PRIORITY_NORMAL);
@@ -2412,16 +2529,13 @@
 gossip_jabber_subscription_disallow_all (GossipJabber *jabber)
 {
 	GossipJabberPriv *priv;
-	LmConnection     *connection;
-
-	g_return_if_fail (jabber != NULL);
 
-	priv = jabber->priv;
+	g_return_if_fail (GOSSIP_IS_JABBER (jabber));
 
-	connection = _gossip_jabber_get_connection (jabber);
+	priv = GET_PRIV (jabber);
 
 	if (priv->subscription_handler) {
-		lm_connection_unregister_message_handler (connection, 
+		lm_connection_unregister_message_handler (priv->connection, 
 							  priv->subscription_handler,
 							  LM_MESSAGE_TYPE_PRESENCE);
 		priv->subscription_handler = NULL;
@@ -2432,21 +2546,22 @@
 gossip_jabber_send_subscribed (GossipJabber  *jabber,
 			       GossipContact *contact)
 {
-	LmConnection *connection;
-	LmMessage    *m;
-	const gchar  *id;
+	GossipJabberPriv *priv;
+	LmMessage        *m;
+	const gchar      *id;
+
+	g_return_if_fail (GOSSIP_IS_JABBER (jabber));
+	g_return_if_fail (GOSSIP_IS_CONTACT (contact));
 
-	g_return_if_fail (jabber != NULL);
-	g_return_if_fail (contact != NULL);
+	priv = GET_PRIV (jabber);
 
 	id = gossip_contact_get_id (contact);
-	connection = _gossip_jabber_get_connection (jabber);
 
 	m = lm_message_new_with_sub_type (id, 
 					  LM_MESSAGE_TYPE_PRESENCE,
 					  LM_MESSAGE_SUB_TYPE_SUBSCRIBED);
 
-	lm_connection_send (connection, m, NULL);
+	lm_connection_send (priv->connection, m, NULL);
 	lm_message_unref (m);
 }
 
@@ -2454,21 +2569,49 @@
 gossip_jabber_send_unsubscribed (GossipJabber  *jabber,
 				 GossipContact *contact)
 {
-	LmConnection *connection;
-	LmMessage    *m;
-	const gchar  *id;
+	GossipJabberPriv *priv;
+	LmMessage        *m;
+	const gchar      *id;
 
-	g_return_if_fail (jabber != NULL);
-	g_return_if_fail (contact != NULL);
+	g_return_if_fail (GOSSIP_IS_JABBER (jabber));
+	g_return_if_fail (GOSSIP_IS_CONTACT (contact));
 
+	priv = GET_PRIV (jabber);
+	
 	id = gossip_contact_get_id (contact);
-	connection = _gossip_jabber_get_connection (jabber);
 
 	m = lm_message_new_with_sub_type (id, 
 					  LM_MESSAGE_TYPE_PRESENCE,
 					  LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED);
 
-	lm_connection_send (connection, m, NULL);
+	lm_connection_send (priv->connection, m, NULL);
 	lm_message_unref (m);
 }
 
+/*
+ * private functions 
+ */
+
+LmConnection *
+gossip_jabber_get_connection (GossipJabber *jabber)
+{
+	GossipJabberPriv *priv;
+	
+        g_return_val_if_fail (GOSSIP_IS_JABBER (jabber), NULL);
+	
+	priv = GET_PRIV (jabber);
+	
+	return priv->connection;
+}
+
+GossipJabberFTs *
+gossip_jabber_get_fts (GossipJabber *jabber)
+{
+	GossipJabberPriv *priv;
+
+	g_return_val_if_fail (GOSSIP_IS_JABBER (jabber), NULL);
+
+	priv = GET_PRIV (jabber);
+	
+	return priv->fts;
+}
Index: protocols/jabber/gossip-jabber.h
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-jabber.h,v
retrieving revision 1.9
diff -u -r1.9 gossip-jabber.h
--- protocols/jabber/gossip-jabber.h	24 Aug 2005 13:22:35 -0000	1.9
+++ protocols/jabber/gossip-jabber.h	16 Nov 2005 21:45:34 -0000
@@ -24,30 +24,21 @@
 #include <libgossip/gossip-async.h>
 #include <libgossip/gossip-presence.h>
 #include <libgossip/gossip-protocol.h>
+#include <libgossip/gossip-account.h>
 
 #define GOSSIP_TYPE_JABBER         (gossip_jabber_get_type ())
-#define GOSSIP_JABBER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), \
- 			            GOSSIP_TYPE_JABBER, GossipJabber))
-#define GOSSIP_JABBER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), \
-				    GOSSIP_TYPE_JABBER, \
-			            GossipJabberClass))
-#define GOSSIP_IS_JABBER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o),\
-			            GOSSIP_TYPE_JABBER))
-#define GOSSIP_IS_JABBER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), \
-				    GOSSIP_TYPE_JABBER))
-#define GOSSIP_JABBER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o),\
-				    GOSSIP_TYPE_JABBER, \
-				    GossipJabberClass))
-
+#define GOSSIP_JABBER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_JABBER, GossipJabber))
+#define GOSSIP_JABBER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GOSSIP_TYPE_JABBER, GossipJabberClass))
+#define GOSSIP_IS_JABBER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_JABBER))
+#define GOSSIP_IS_JABBER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_JABBER))
+#define GOSSIP_JABBER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_JABBER, GossipJabberClass))
 
 typedef struct _GossipJabber      GossipJabber;
 typedef struct _GossipJabberClass GossipJabberClass;
 typedef struct _GossipJabberPriv  GossipJabberPriv;
 
-
 struct _GossipJabber {
 	GossipProtocol    parent;
-
 	GossipJabberPriv *priv;
 };
 
@@ -57,18 +48,25 @@
 };
 
   
-GType               gossip_jabber_get_type                  (void) G_GNUC_CONST;
+GType          gossip_jabber_get_type                  (void) G_GNUC_CONST;
+gboolean       gossip_jabber_get_vcard                 (GossipJabber        *jabber,
+							GossipContact       *contact,
+							GossipVCardCallback  callback);
+GossipAccount *gossip_jabber_get_account               (GossipJabber        *jabber);
+
+GossipContact *gossip_jabber_get_own_contact           (GossipJabber        *jabber);
+GossipContact *gossip_jabber_get_contact_from_jid      (GossipJabber        *jabber,
+							const gchar         *jid,
+							gboolean            *new_item);
+void           gossip_jabber_send_subscribed           (GossipJabber        *jabber,
+							GossipContact       *contact);
+void           gossip_jabber_send_unsubscribed         (GossipJabber        *jabber,
+							GossipContact       *contact);
+void           gossip_jabber_subscription_allow_all    (GossipJabber        *jabber);
+void           gossip_jabber_subscription_disallow_all (GossipJabber        *jabber);
+
+
 
-gboolean            gossip_jabber_get_vcard                 (GossipJabber        *jabber,
-							     GossipContact       *contact,
-							     GossipVCardCallback  callback);
-GossipContact *     gossip_jabber_get_own_contact           (GossipJabber        *jabber);
-void                gossip_jabber_send_subscribed           (GossipJabber        *jabber,
-							     GossipContact       *contact);
-void                gossip_jabber_send_unsubscribed         (GossipJabber        *jabber,
-							     GossipContact       *contact);
-void                gossip_jabber_subscription_allow_all    (GossipJabber        *jabber);
-void                gossip_jabber_subscription_disallow_all (GossipJabber        *jabber);
 
 
 #endif /* __GOSSIP_JABBER_H__ */
Index: protocols/jabber/gossip-transport-accounts.c
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-transport-accounts.c,v
retrieving revision 1.8
diff -u -r1.8 gossip-transport-accounts.c
--- protocols/jabber/gossip-transport-accounts.c	24 Aug 2005 13:22:35 -0000	1.8
+++ protocols/jabber/gossip-transport-accounts.c	16 Nov 2005 21:45:35 -0000
@@ -560,7 +560,7 @@
 	g_return_if_fail (account != NULL);
 
 	jabber = transport_account_get_jabber (account);
-	connection = _gossip_jabber_get_connection (jabber);
+	connection = gossip_jabber_get_connection (jabber);
 
 	service_jid = gossip_transport_account_get_jid (account);
 	own_contact = gossip_jabber_get_own_contact (jabber);
Index: protocols/jabber/gossip-transport-discover.c
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-transport-discover.c,v
retrieving revision 1.6
diff -u -r1.6 gossip-transport-discover.c
--- protocols/jabber/gossip-transport-discover.c	17 Aug 2005 14:53:59 -0000	1.6
+++ protocols/jabber/gossip-transport-discover.c	16 Nov 2005 21:45:36 -0000
@@ -136,7 +136,7 @@
 
 	disco->jabber = g_object_ref (jabber);
 
-	connection = _gossip_jabber_get_connection (jabber);
+	connection = gossip_jabber_get_connection (jabber);
 
 	handler = lm_message_handler_new (transport_disco_message_handler, disco, NULL);
 	disco->message_handler = handler;
@@ -371,7 +371,7 @@
 	d(g_print ("disco items to: %s\n", 
 		   gossip_jid_get_full (disco->to)));
 	
-	connection = _gossip_jabber_get_connection (disco->jabber);
+	connection = gossip_jabber_get_connection (disco->jabber);
 
 	lm_message_node_add_child (m->node, "query", NULL);
 	node = lm_message_node_get_child (m->node, "query");
@@ -486,7 +486,7 @@
 	GList        *l;
 	GossipJID    *jid;
 	
-	connection = _gossip_jabber_get_connection (disco->jabber);
+	connection = gossip_jabber_get_connection (disco->jabber);
 	jid = gossip_jid_new ("users.jabber.org");
 
 	disco->items_total = disco->items_remaining = g_list_length (disco->items);
@@ -695,7 +695,7 @@
 
 	disco->destroying = TRUE;
 
-        connection = _gossip_jabber_get_connection (disco->jabber);
+        connection = gossip_jabber_get_connection (disco->jabber);
 
         handler = disco->message_handler;
         if (handler) {
@@ -754,7 +754,7 @@
 	disco->jabber = g_object_ref (jabber);
 
 	/* set up handler */
-	connection = _gossip_jabber_get_connection (jabber);
+	connection = gossip_jabber_get_connection (jabber);
 
 	handler = lm_message_handler_new (transport_disco_message_handler, disco, NULL);
 	disco->message_handler = handler;
Index: protocols/jabber/gossip-transport-protocol.c
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-transport-protocol.c,v
retrieving revision 1.6
diff -u -r1.6 gossip-transport-protocol.c
--- protocols/jabber/gossip-transport-protocol.c	17 Aug 2005 14:53:59 -0000	1.6
+++ protocols/jabber/gossip-transport-protocol.c	16 Nov 2005 21:45:37 -0000
@@ -662,7 +662,7 @@
 	pi = transport_protocol_id_new (id, protocol, func, user_data);
 
 	/* set up message handler */
-	connection = _gossip_jabber_get_connection (jabber);
+	connection = gossip_jabber_get_connection (jabber);
 
 	handler = lm_message_handler_new (transport_protocol_message_handler, 
 					  pi, 
Index: protocols/jabber/gossip-transport-register.c
===================================================================
RCS file: /cvs/gnome/gossip/protocols/jabber/gossip-transport-register.c,v
retrieving revision 1.5
diff -u -r1.5 gossip-transport-register.c
--- protocols/jabber/gossip-transport-register.c	17 Aug 2005 14:53:59 -0000	1.5
+++ protocols/jabber/gossip-transport-register.c	16 Nov 2005 21:45:37 -0000
@@ -119,7 +119,6 @@
 			     gpointer                       user_data)
 {
 	TransportUnregister *tu;
-
 	LmConnection        *connection;
 	LmMessageHandler    *handler;
         LmMessage           *m;
@@ -144,7 +143,7 @@
 		   gossip_jid_get_full (jid)));
 
 	/* set up handler */
-	connection = _gossip_jabber_get_connection (jabber);
+	connection = gossip_jabber_get_connection (jabber);
 
 	handler = lm_message_handler_new (transport_unregister_message_handler, 
 					  NULL, NULL);
@@ -356,7 +355,7 @@
 	g_hash_table_insert (requirements, trq->jid, trq);
 
 	/* set up handler */
-	connection = _gossip_jabber_get_connection (jabber);
+	connection = gossip_jabber_get_connection (jabber);
 
 	handler = lm_message_handler_new (transport_requirements_message_handler, 
 					  NULL, NULL);
@@ -574,7 +573,7 @@
 	g_hash_table_insert (registers, trg->jid, trg);
 
 	/* set up handler */
-	connection = _gossip_jabber_get_connection (jabber);
+	connection = gossip_jabber_get_connection (jabber);
 
 	handler = lm_message_handler_new (transport_register_message_handler, 
 					  NULL, NULL);
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/gossip/src/Makefile.am,v
retrieving revision 1.52
diff -u -r1.52 Makefile.am
--- src/Makefile.am	1 Nov 2005 19:11:39 -0000	1.52
+++ src/Makefile.am	16 Nov 2005 21:45:37 -0000
@@ -50,6 +50,7 @@
 	gossip-contact-info.c              gossip-contact-info.h                \
 	gossip-favorite.c  	           gossip-favorite.h			\
 	gossip-edit-favorite-dialog.c      gossip-edit-favorite-dialog.h	\
+	gossip-ft-window.c		   gossip-ft-window.h			\
 	gossip-group-chat.c	           gossip-group-chat.h			\
 	gossip-idle.c		           gossip-idle.h			\
 	gossip-join-dialog.c	           gossip-join-dialog.h			\
@@ -67,6 +68,7 @@
 	gossip-spell.c                     gossip-spell.h                       \
 	gossip-spell-dialog.c 		   gossip-spell-dialog.h                \
 	gossip-status-presets.c		   gossip-status-presets.h	       	\
+	gossip-subscription-dialog.c       gossip-subscription-dialog.h		\
 	gossip-ui-utils.c	           gossip-ui-utils.h			\
 	gossip-edit-groups-dialog.c        gossip-edit-groups-dialog.h		\
 	gossip-vcard-dialog.c	    	   gossip-vcard-dialog.h		\
Index: src/gossip-app.c
===================================================================
RCS file: /cvs/gnome/gossip/src/gossip-app.c,v
retrieving revision 1.192
diff -u -r1.192 gossip-app.c
--- src/gossip-app.c	12 Nov 2005 11:49:35 -0000	1.192
+++ src/gossip-app.c	16 Nov 2005 21:45:40 -0000
@@ -36,32 +36,34 @@
 #include <libgossip/gossip-contact.h>
 #include <libgossip/gossip-protocol.h>
 #include <libgossip/gossip-utils.h>
-
 #include <libgossip/gossip-contact.h>
 #include <libgossip/gossip-presence.h>
+#include <libgossip/gossip-ft.h>
 
-#include "eggtrayicon.h"
-#include "gossip-vcard-dialog.h"
+#include "gossip-about.h"
+#include "gossip-account-button.h"
+#include "gossip-accounts-dialog.h"
 #include "gossip-add-contact.h"
-#include "gossip-ui-utils.h"
-#include "gossip-group-chat.h"
+#include "gossip-app.h"
 #include "gossip-chat.h"
-#include "gossip-private-chat.h"
 #include "gossip-contact-list.h"
-#include "gossip-join-dialog.h"
-#include "gossip-sound.h"
+#include "gossip-ft-window.h"
+#include "gossip-group-chat.h"
 #include "gossip-idle.h"
+#include "gossip-join-dialog.h"
 #include "gossip-marshal.h"
 #include "gossip-new-account-window.h"
 #include "gossip-preferences.h"
 #include "gossip-presence-chooser.h"
-#include "gossip-status-presets.h"
 #include "gossip-private-chat.h"
-#include "gossip-accounts-dialog.h"
-#include "gossip-account-button.h"
+#include "gossip-private-chat.h"
+#include "gossip-sound.h"
+#include "gossip-status-presets.h"
 #include "gossip-stock.h"
-#include "gossip-about.h"
-#include "gossip-app.h"
+#include "gossip-subscription-dialog.h"
+#include "gossip-ui-utils.h"
+#include "gossip-vcard-dialog.h"
+#include "eggtrayicon.h"
 
 #ifdef HAVE_DBUS
 #include "gossip-dbus.h"
@@ -165,13 +167,6 @@
 } CompleteNameData;
 
 
-typedef struct {
-	GossipProtocol *protocol;
-	GossipContact  *contact;
-	GossipVCard    *vcard;
-} SubscriptionData;
-
-
 enum {
 	CONNECTED,
 	DISCONNECTED,
@@ -227,8 +222,6 @@
 							     GossipApp            *app);
 static void            app_preferences_cb                   (GtkWidget            *widget,
 							     GossipApp            *app);
-static void            app_configure_transports_cb          (GtkWidget            *widget,
-							     GossipApp            *app);
 static void            app_about_cb                         (GtkWidget            *widget,
 							     GossipApp            *app);
 static void	       app_help_cb			    (GtkWidget		  *widget,
@@ -304,18 +297,7 @@
 static void            app_contact_activated_cb             (GossipContactList    *contact_list,
 							     GossipContact        *contact,
 							     gpointer              unused);
-static void            app_subscription_request_cb          (GossipProtocol       *protocol,
-							     GossipContact        *contact,
-							     gpointer              user_data);
-static void            app_subscription_event_activated_cb  (GossipEventManager   *event_manager,
-							     GossipEvent          *event,
-							     GossipProtocol       *protocol);
-static void            app_subscription_vcard_cb            (GossipResult          result,
-							     GossipVCard          *vcard,
-							     SubscriptionData     *data);
-static void            app_subscription_request_dialog_cb   (GtkWidget            *dialog,
-							     gint                  response,
-							     SubscriptionData     *data);
+
 
 
 static guint         signals[LAST_SIGNAL] = { 0 };
@@ -393,21 +375,55 @@
 		g_source_remove (priv->status_flash_timeout_id);
 	}
 
+	g_list_free (priv->widgets_connected_all);
+	g_list_free (priv->widgets_connected);
+	g_list_free (priv->widgets_disconnected);
+
 	manager = gossip_session_get_account_manager (priv->session);
 	
 	g_signal_handlers_disconnect_by_func (manager,
 					      app_accounts_account_added_cb, 
 					      NULL);
-
 	g_signal_handlers_disconnect_by_func (manager,
 					      app_accounts_account_removed_cb, 
 					      NULL);
+	g_signal_handlers_disconnect_by_func (manager,
+					      app_accounts_account_enabled_cb, 
+					      NULL);
 
+	g_signal_handlers_disconnect_by_func (priv->session,
+					      app_session_protocol_connected_cb, 
+					      NULL);
+	g_signal_handlers_disconnect_by_func (priv->session,
+					      app_session_protocol_disconnected_cb, 
+					      NULL);
+	g_signal_handlers_disconnect_by_func (priv->session,
+					      app_session_get_password_cb, 
+					      NULL);
+
+	g_signal_handlers_disconnect_by_func (priv->event_manager,
+					      app_event_added_cb, 
+					      NULL);
+	g_signal_handlers_disconnect_by_func (priv->event_manager,
+					      app_event_removed_cb, 
+					      NULL);
 
-	g_list_free (priv->widgets_connected_all);
-	g_list_free (priv->widgets_connected);
-	g_list_free (priv->widgets_disconnected);
 	
+	if (priv->event_manager) {
+		g_object_unref (priv->event_manager);
+	}
+
+	if (priv->chat_manager) {
+		g_object_unref (priv->chat_manager);
+	}
+
+	/* call init session dependent modules */
+	gossip_ft_window_finalize (priv->session);
+	gossip_subscription_dialog_finalize (priv->session);
+
+/* 	gossip_galago_finalize (priv->session); */
+/*      gossip_dbus_finalize (priv->session); */
+
 	g_free (priv);
 	app->priv = NULL;
 
@@ -444,6 +460,10 @@
 	gossip_galago_init (priv->session);
 #endif
 
+	/* call init session dependent modules */
+	gossip_subscription_dialog_init (priv->session);
+	gossip_ft_window_init (priv->session);
+
 	/* do we need first time start up druid? */
 	if (gossip_new_account_window_is_needed ()) {
 		gossip_new_account_window_show ();
@@ -511,7 +531,6 @@
 			      "actions_send_chat_message", "activate", app_new_message_cb,
 			      "actions_add_contact", "activate", app_add_contact_cb,
 			      "actions_show_offline", "toggled", app_show_offline_cb,
-			      "actions_configure_transports", "activate", app_configure_transports_cb,
 			      "edit_accounts", "activate", app_accounts_cb,
 			      "edit_personal_information", "activate", app_personal_information_cb,
 			      "edit_preferences", "activate", app_preferences_cb,
@@ -691,23 +710,19 @@
 				continue;
 			}
 			
-			if (i == GOSSIP_EVENT_TYPING) {
-				continue;
-			}
-
 			switch (i) {
 			case GOSSIP_EVENT_NEW_MESSAGE: 
 				str_single = "%d New message";
 				str_plural = "%d New messages";
 				break;
-			case GOSSIP_EVENT_UNFOCUSED_MESSAGE: 
-				str_single = "%d Unfocused message";
-				str_plural = "%d Unfocused messages";
-				break;
 			case GOSSIP_EVENT_SUBSCRIPTION_REQUEST: 
 				str_single = "%d Subscription request";
 				str_plural = "%d Subscription requests";
 				break;
+			case GOSSIP_EVENT_FILE_TRANSFER_REQUEST: 
+				str_single = "%d File transfer request";
+				str_plural = "%d File transfer requests";
+				break;
 			case GOSSIP_EVENT_SERVER_MESSAGE: 
 				str_single = "%d Server message";
 				str_plural = "%d Server messages";
@@ -830,12 +845,6 @@
 
 	app_connection_items_update ();
 	app_presence_updated ();
-
-	/* is this the right place for setting up protocol signals? */
-	g_signal_connect (protocol,
-                          "subscription-request",
-                          G_CALLBACK (app_subscription_request_cb),
-                          session);
 }
 
 static void
@@ -850,11 +859,6 @@
 	
  	app_connection_items_update ();
 	app_presence_updated ();
-
-	/* FIXME: implement */
-	g_signal_handlers_disconnect_by_func (protocol, 
-					      app_subscription_request_cb, 
-					      session);
 }
 
 static gchar * 
@@ -1197,14 +1201,6 @@
 	gossip_preferences_show ();
 }
 
-static void
-app_configure_transports_cb (GtkWidget *widget, GossipApp *app)
-{
-#if 0 /* TRANSPORTS */
-	gossip_transport_accounts_window_show ();
-#endif
-}
-
 static gboolean
 app_idle_check_cb (GossipApp *app)
 {
@@ -2391,207 +2387,6 @@
 	priv = app->priv;
 
 	gossip_chat_manager_show_chat (priv->chat_manager, contact);
-}
-
-static void
-app_subscription_request_cb (GossipProtocol *protocol,
-			     GossipContact  *contact,
-			     gpointer        user_data)
-{
-	GossipEvent      *event;
-	gchar            *str;
-
-	event = gossip_event_new (GOSSIP_EVENT_SUBSCRIPTION_REQUEST);
-
-	str = g_strdup_printf (_("New subscription request from %s"), 
-			       gossip_contact_get_name (contact));
-
-	g_object_set (event, 
-		      "message", str, 
-		      "data", contact,
-		      NULL);
-	g_free (str);
-
-	gossip_event_manager_add (gossip_app_get_event_manager (),
-				  event, 
-				  (GossipEventActivatedFunction)app_subscription_event_activated_cb,
-				  G_OBJECT (protocol));
-}
-
-static void
-app_subscription_event_activated_cb (GossipEventManager *event_manager,
-				     GossipEvent        *event,
-				     GossipProtocol     *protocol)
-{
-	GossipContact    *contact;
-	SubscriptionData *data;
-
-	contact = GOSSIP_CONTACT (gossip_event_get_data (event));
-
-	data = g_new0 (SubscriptionData, 1);
-
-	data->protocol = g_object_ref (protocol);
-	data->contact = g_object_ref (contact);
-
-	gossip_session_get_vcard (gossip_app_get_session (),
-				  NULL,
-				  data->contact,
-				  (GossipVCardCallback) app_subscription_vcard_cb,
-				  data, 
-				  NULL);
-}
-
-static void
-app_subscription_vcard_cb (GossipResult      result,
-			   GossipVCard       *vcard,
-			   SubscriptionData  *data)
-{
-	GtkWidget   *dialog;
-	GtkWidget   *who_label;
-	GtkWidget   *question_label;
-	GtkWidget   *jid_label;
- 	GtkWidget   *website_label;
- 	GtkWidget   *personal_table;
-	const gchar *name = NULL;
-	const gchar *url = NULL;
-	gchar       *who;
-	gchar       *question;
-	gchar       *str;
-	gint         num_matches = 0;
-
-	if (GOSSIP_IS_VCARD (vcard)) {
-		data->vcard = g_object_ref (vcard);
-
-		name = gossip_vcard_get_name (vcard);
-		url = gossip_vcard_get_url (vcard);
-	}
-
-	gossip_glade_get_file_simple (GLADEDIR "/main.glade",
-				      "subscription_request_dialog",
-				      NULL,
-				      "subscription_request_dialog", &dialog,
-				      "who_label", &who_label,
-				      "question_label", &question_label,
-				      "jid_label", &jid_label,
-				      "website_label", &website_label,
-				      "personal_table", &personal_table,
-				      NULL);
-
-	if (name) {
-		who = g_strdup_printf (_("%s wants to be added to your contact list."), 
-				       name);
-		question = g_strdup_printf (_("Do you want to add %s to your contact list?"),
-					    name);
-	} else {
-		who = g_strdup (_("Someone wants to be added to your contact list."));
-		question = g_strdup (_("Do you want to add this person to your contact list?"));
-	}
-
-	str = g_strdup_printf ("<span weight='bold' size='larger'>%s</span>", who);
-	gtk_label_set_markup (GTK_LABEL (who_label), str);
-	gtk_label_set_use_markup (GTK_LABEL (who_label), TRUE);
-	g_free (str);
-	g_free (who);
-
-	gtk_label_set_text (GTK_LABEL (question_label), question);
-	g_free (question);
-
-	gtk_label_set_text (GTK_LABEL (jid_label), gossip_contact_get_id (data->contact));
-
-	if (url && strlen (url) > 0) {
-		GArray *start, *end;
-
-		start = g_array_new (FALSE, FALSE, sizeof (gint));
-		end = g_array_new (FALSE, FALSE, sizeof (gint));
-		
-		num_matches = gossip_utils_url_regex_match (url, start, end);
-	}
-
-	if (num_matches > 0) {
-		GtkWidget *href;
-		GtkWidget *alignment;
-
-		href = gnome_href_new (url, url);
-
-		alignment = gtk_alignment_new (0, 1, 0, 0.5);
-		gtk_container_add (GTK_CONTAINER (alignment), href);
-
-		gtk_table_attach (GTK_TABLE (personal_table),
-				  alignment, 
-				  1, 2,
-				  1, 2,
-				  GTK_FILL, GTK_FILL,
-				  0, 0);
-		
-		gtk_widget_show_all (personal_table);
-	} else {
-		gtk_widget_hide (website_label);
-	}
-
-	g_signal_connect (dialog,
-			  "response",
-			  G_CALLBACK (app_subscription_request_dialog_cb),
-			  data);
-
-	gtk_widget_show (dialog);
-}
-
-static void
-app_subscription_request_dialog_cb (GtkWidget        *dialog,
-				    gint              response,
-				    SubscriptionData *data)
-{
-	gboolean add_user;
-
-	g_return_if_fail (GTK_IS_DIALOG (dialog));
-
-	g_return_if_fail (GOSSIP_IS_PROTOCOL (data->protocol));
-	g_return_if_fail (GOSSIP_IS_CONTACT (data->contact));
-
-	add_user = (gossip_contact_get_type (data->contact) == GOSSIP_CONTACT_TYPE_TEMPORARY);
-
-	gtk_widget_destroy (dialog);
-	
-	if (response == GTK_RESPONSE_YES ||
-	    response == GTK_RESPONSE_NO) {
-		gboolean subscribe;
-
-		subscribe = (response == GTK_RESPONSE_YES);
-		gossip_protocol_set_subscription (data->protocol, 
-						  data->contact, 
-						  subscribe);
-
-		if (subscribe && add_user) {
-			const gchar *id, *name, *message;
-			
-			id = gossip_contact_get_id (data->contact);
-			if (data->vcard) {
-				name = gossip_vcard_get_name (data->vcard);
-			} else {
-				name = id;
-			}
-			
-			message = _("I would like to add you to my contact list.");
-					
-			/* FIXME: how is session related to an IM account? */
-			/* micke, hmm .. this feels a bit wrong, should be
-			 * signalled from the protocol when we do 
-			 * set_subscribed
-			 */
-			gossip_protocol_add_contact (data->protocol,
-						     id, name, NULL,
-						     message);
-		}
-	}
-	
-	g_object_unref (data->protocol);
-	g_object_unref (data->contact);
-
-	if (data->vcard) {
-		g_object_unref (data->vcard);
-	}
-	
-	g_free (data);
 }
 
 GossipSession *
Index: src/gossip-contact-list.c
===================================================================
RCS file: /cvs/gnome/gossip/src/gossip-contact-list.c,v
retrieving revision 1.35
diff -u -r1.35 gossip-contact-list.c
--- src/gossip-contact-list.c	1 Nov 2005 19:11:39 -0000	1.35
+++ src/gossip-contact-list.c	16 Nov 2005 21:45:42 -0000
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Copyright (C) 2004 Imendio AB
+ * Copyright (C) 2005 Imendio AB
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -29,15 +29,16 @@
 
 #include "gossip-app.h"
 #include "gossip-cell-renderer-text.h"
+#include "gossip-chat-invite.h"
+#include "gossip-contact-groups.h"
 #include "gossip-contact-info.h"
+#include "gossip-contact-list.h"
 #include "gossip-edit-groups-dialog.h"
+#include "gossip-ft-window.h"
 #include "gossip-log.h"
 #include "gossip-marshal.h"
-#include "gossip-stock.h"
-#include "gossip-contact-groups.h"
-#include "gossip-contact-list.h"
 #include "gossip-sound.h"
-#include "gossip-chat-invite.h"
+#include "gossip-stock.h"
 
 #define d(x)
 
@@ -236,6 +237,9 @@
 static void            contact_list_item_menu_edit_groups_cb    (gpointer                data,
 								 guint                   action,
 								 GtkWidget              *widget);
+static void            contact_list_item_menu_send_file_cb      (gpointer                data,
+								 guint                   action,
+								 GtkWidget              *widget);
 static void            contact_list_item_menu_log_cb            (gpointer                data,
 								 guint                   action,
 								 GtkWidget              *widget);
@@ -291,6 +295,7 @@
         ITEM_MENU_EDIT_GROUPS,
         ITEM_MENU_REMOVE,
 	ITEM_MENU_INVITE,
+	ITEM_MENU_SEND_FILE,
         ITEM_MENU_LOG
 };
 
@@ -353,6 +358,18 @@
 	  0,
 	  "<Separator>",
 	  NULL },
+	{ N_("/_Send File..."),
+	  NULL,
+	  GIF_CB (contact_list_item_menu_send_file_cb),
+	  ITEM_MENU_SEND_FILE,
+	  "<Item>",
+	  NULL },
+	{ "/sep3",
+	  NULL,
+	  NULL,
+	  0,
+	  "<Separator>",
+	  NULL },
 	{ N_("/Show _Log"),
 	  NULL,
 	  GIF_CB (contact_list_item_menu_log_cb),
@@ -1980,6 +1997,21 @@
         }
 
         gossip_edit_groups_new (contact);
+}
+
+static void
+contact_list_item_menu_send_file_cb (gpointer   data,
+				     guint      action,
+				     GtkWidget *widget)
+{
+        GossipContact *contact;
+
+        contact = gossip_contact_list_get_selected (GOSSIP_CONTACT_LIST (data));
+        if (!contact) {
+                return;
+        }
+	
+        gossip_ft_window_send_file (contact);
 }
 
 static void
Index: src/gossip-ft-window.c
===================================================================
RCS file: src/gossip-ft-window.c
diff -N src/gossip-ft-window.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/gossip-ft-window.c	16 Nov 2005 21:45:42 -0000
@@ -0,0 +1,462 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2003-2004 Imendio AB
+ *
+ * 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/gi18n.h>
+#include <libgnomeui/libgnomeui.h>
+#include <libgnomevfs/gnome-vfs.h>
+
+#include <libgossip/gossip-event-manager.h>
+#include <libgossip/gossip-ft.h>
+#include <libgossip/gossip-protocol.h>
+#include <libgossip/gossip-utils.h>
+
+#include "gossip-ft-window.h"
+#include "gossip-app.h"
+
+#define d(x) x
+
+
+typedef struct {
+	GossipProtocol *protocol;
+	GossipFT       *ft;
+	GossipVCard    *vcard;
+} FTData;
+
+
+static void ft_window_protocol_connected_cb    (GossipSession      *session,
+						GossipAccount      *account,
+						GossipProtocol     *protocol,
+						gpointer            user_data);
+static void ft_window_protocol_disconnected_cb (GossipSession      *session,
+						GossipAccount      *account,
+						GossipProtocol     *protocol,
+						gpointer            user_data);
+static void ft_window_request_cb               (GossipProtocol     *protocol,
+						GossipFT           *ft,
+						gpointer            user_data);
+static void ft_window_error_cb                 (GossipProtocol     *protocol,
+						GossipFT           *ft,
+						GError             *error,
+						gpointer            user_data);
+static void ft_window_event_activated_cb       (GossipEventManager *event_manager,
+						GossipEvent        *event,
+						GossipProtocol     *protocol);
+static void ft_window_vcard_cb                 (GossipResult        result,
+						GossipVCard        *vcard,
+						FTData             *data);
+static void ft_window_request_dialog_cb        (GtkWidget          *dialog,
+						gint                response,
+						FTData             *data);
+static void ft_window_filechooser_create       (GossipContact      *contact);
+static void ft_window_filechooser_response_cb  (GtkDialog          *dialog,
+						gint                response_id,
+						GossipContact      *contact);
+
+
+void
+gossip_ft_window_init (GossipSession *session)
+{
+	g_signal_connect (session, 
+			  "protocol-connected",
+			  G_CALLBACK (ft_window_protocol_connected_cb),
+			  NULL);
+
+	g_signal_connect (session, 
+			  "protocol-disconnected",
+			  G_CALLBACK (ft_window_protocol_disconnected_cb),
+			  NULL);
+}
+
+void
+gossip_ft_window_finalize (GossipSession *session)
+{
+ 	g_signal_handlers_disconnect_by_func (session, 
+					      ft_window_protocol_connected_cb, 
+					      NULL);
+ 	g_signal_handlers_disconnect_by_func (session, 
+					      ft_window_protocol_disconnected_cb, 
+					      NULL);
+}
+
+/*
+ * receiving from another contact
+ */
+
+static void
+ft_window_protocol_connected_cb (GossipSession  *session,
+				 GossipAccount  *account,
+				 GossipProtocol *protocol,
+				 gpointer        user_data)
+{
+	g_signal_connect (protocol,
+                          "file-transfer-request",
+                          G_CALLBACK (ft_window_request_cb),
+                          session);
+
+	g_signal_connect (protocol,
+                          "file-transfer-error",
+                          G_CALLBACK (ft_window_error_cb),
+                          session);
+}
+
+static void
+ft_window_protocol_disconnected_cb (GossipSession  *session,
+				    GossipAccount  *account,
+				    GossipProtocol *protocol,
+				    gpointer        user_data)
+{
+ 	g_signal_handlers_disconnect_by_func (protocol, 
+					      ft_window_request_cb, 
+					      session);
+ 	g_signal_handlers_disconnect_by_func (protocol, 
+					      ft_window_error_cb, 
+					      session);
+}
+
+static void
+ft_window_request_cb (GossipProtocol *protocol,
+		      GossipFT       *ft,
+		      gpointer        user_data)
+{
+	GossipEvent   *event;
+	GossipContact *contact;
+	gchar         *str;
+
+	event = gossip_event_new (GOSSIP_EVENT_FILE_TRANSFER_REQUEST);
+	contact = gossip_ft_get_contact (ft);
+
+	str = g_strdup_printf (_("New file transfer request from %s"), 
+			       gossip_contact_get_name (contact));
+
+	g_object_set (event, 
+		      "message", str, 
+		      "data", ft,
+		      NULL);
+	g_free (str);
+
+	gossip_event_manager_add (gossip_app_get_event_manager (),
+				  event, 
+				  (GossipEventActivatedFunction)ft_window_event_activated_cb,
+				  G_OBJECT (protocol));
+}
+
+static void
+ft_window_error_cb (GossipProtocol *protocol,
+		    GossipFT       *ft,
+		    GError         *error,
+		    gpointer        user_data)
+{
+	GtkWidget      *dialog;
+	GtkMessageType  type;
+	const gchar    *str1, *str2;
+	
+	type = GTK_MESSAGE_ERROR;
+
+	str2 = error->message;
+		
+	switch (error->code) {
+	case GOSSIP_FT_ERROR_UNSUPPORTED:
+		type = GTK_MESSAGE_INFO;
+		str1 = _("File transfer is not supported by both parties.");
+		break;
+	case GOSSIP_FT_ERROR_DECLINED:
+		type = GTK_MESSAGE_INFO;
+		str1 = _("Your file transfer offer declined.");
+		str2 = _("The other user decided not to continue.");
+		break;
+		
+	case GOSSIP_FT_ERROR_UNKNOWN:
+	default:
+		str1 = _("Unknown error occured during file transfer."); 
+		break;
+	}
+
+	dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (gossip_app_get_window ()),
+						     GTK_DIALOG_DESTROY_WITH_PARENT,
+						     type,
+						     GTK_BUTTONS_CLOSE,
+						     "<b>%s</b>\n\n%s",
+						     str1,
+						     str2);
+	
+	g_signal_connect_swapped (dialog, "response",
+				  G_CALLBACK (gtk_widget_destroy),
+				  dialog);
+
+	gtk_widget_show (dialog);
+}
+
+static void
+ft_window_event_activated_cb (GossipEventManager *event_manager,
+			      GossipEvent        *event,
+			      GossipProtocol     *protocol)
+{
+	GossipFT *ft;
+	FTData   *data;
+
+	ft = GOSSIP_FT (gossip_event_get_data (event));
+
+	data = g_new0 (FTData, 1);
+
+	data->protocol = g_object_ref (protocol);
+	data->ft = g_object_ref (ft);
+
+	gossip_session_get_vcard (gossip_app_get_session (),
+				  NULL,
+				  gossip_ft_get_contact (ft),
+				  (GossipVCardCallback) ft_window_vcard_cb,
+				  data, 
+				  NULL);
+}
+
+static void
+ft_window_vcard_cb (GossipResult  result,
+		    GossipVCard  *vcard,
+		    FTData       *data)
+{
+	GossipContact *contact;
+	GtkWidget     *dialog;
+	GtkWidget     *who_label;
+	GtkWidget     *id_label;
+ 	GtkWidget     *website_label;
+ 	GtkWidget     *personal_table;
+	GtkWidget     *file_name_label;
+	GtkWidget     *file_size_label;
+	const gchar   *name = NULL;
+	const gchar   *url = NULL;
+	gchar         *who;
+	gchar         *str;
+	gint           num_matches = 0;
+	gchar         *file_size;
+
+	if (GOSSIP_IS_VCARD (vcard)) {
+		data->vcard = g_object_ref (vcard);
+
+		name = gossip_vcard_get_name (vcard);
+		url = gossip_vcard_get_url (vcard);
+	}
+
+	contact = gossip_ft_get_contact (data->ft);
+
+	gossip_glade_get_file_simple (GLADEDIR "/file-transfer.glade",
+				      "file_transfer_dialog",
+				      NULL,
+				      "file_transfer_dialog", &dialog,
+				      "who_label", &who_label,
+				      "id_label", &id_label,
+				      "website_label", &website_label,
+				      "personal_table", &personal_table,
+				      "file_name_label", &file_name_label,
+				      "file_size_label", &file_size_label,
+				      NULL);
+
+	if (name) {
+		who = g_strdup_printf (_("%s would like to send you a file."), 
+				       name);
+	} else {
+		who = g_strdup (_("Someone would like to send you a file."));
+	}
+
+	str = g_strdup_printf ("<span weight='bold' size='larger'>%s</span>", who);
+	gtk_label_set_markup (GTK_LABEL (who_label), str);
+	gtk_label_set_use_markup (GTK_LABEL (who_label), TRUE);
+	g_free (str);
+	g_free (who);
+
+	gtk_label_set_text (GTK_LABEL (file_name_label), gossip_ft_get_file_name (data->ft));
+
+	file_size = gnome_vfs_format_file_size_for_display (gossip_ft_get_file_size (data->ft));
+	gtk_label_set_text (GTK_LABEL (file_size_label), file_size);
+	g_free (file_size);
+
+	gtk_label_set_text (GTK_LABEL (id_label), gossip_contact_get_id (contact));
+
+	if (url && strlen (url) > 0) {
+		GArray *start, *end;
+
+		start = g_array_new (FALSE, FALSE, sizeof (gint));
+		end = g_array_new (FALSE, FALSE, sizeof (gint));
+		
+		num_matches = gossip_utils_url_regex_match (url, start, end);
+	}
+
+	if (num_matches > 0) {
+		GtkWidget *href;
+		GtkWidget *alignment;
+
+		href = gnome_href_new (url, url);
+
+		alignment = gtk_alignment_new (0, 1, 0, 0.5);
+		gtk_container_add (GTK_CONTAINER (alignment), href);
+
+		gtk_table_attach (GTK_TABLE (personal_table),
+				  alignment, 
+				  1, 2,
+				  1, 2,
+				  GTK_FILL, GTK_FILL,
+				  0, 0);
+		
+		gtk_widget_show_all (personal_table);
+	} else {
+		gtk_widget_hide (website_label);
+	}
+
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (ft_window_request_dialog_cb),
+			  data);
+
+	gtk_widget_show (dialog);
+}
+
+static void
+ft_window_request_dialog_cb (GtkWidget *dialog,
+			     gint       response,
+			     FTData    *data)
+{
+	g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+	g_return_if_fail (GOSSIP_IS_PROTOCOL (data->protocol));
+	g_return_if_fail (GOSSIP_IS_FT (data->ft));
+
+	gtk_widget_destroy (dialog);
+	
+/* 	g_return_if_fail (GOSSIP_IS_CONTACT (contact)); */
+/* 	g_return_if_fail (file != NULL && strlen (file) > 0); */
+
+	if (response == GTK_RESPONSE_YES) {
+		gossip_ft_provider_accept (GOSSIP_FT_PROVIDER (data->protocol), 
+					   gossip_ft_get_id (data->ft));
+	} else {
+		gossip_ft_provider_decline (GOSSIP_FT_PROVIDER (data->protocol), 
+					    gossip_ft_get_id (data->ft));
+	}
+	
+	g_object_unref (data->protocol);
+	g_object_unref (data->ft);
+
+	if (data->vcard) {
+		g_object_unref (data->vcard);
+	}
+	
+	g_free (data);
+}
+
+/*
+ * sending with the file chooser 
+ */
+
+void 
+gossip_ft_window_send_file (GossipContact *contact)
+{
+	g_return_if_fail (GOSSIP_IS_CONTACT (contact));
+
+	ft_window_filechooser_create (contact);
+}
+
+void 
+gossip_ft_window_send_file_from_uri (GossipContact *contact,
+				     const gchar   *file)
+{
+	GossipSession    *session;
+	GossipAccount    *account;
+	GossipFTProvider *provider;
+
+	g_return_if_fail (GOSSIP_IS_CONTACT (contact));
+	g_return_if_fail (file != NULL && strlen (file) > 0);
+
+	account = gossip_contact_get_account (contact);
+
+ 	session = gossip_app_get_session (); 
+	provider = gossip_session_get_ft_provider (session, account);
+	
+	gossip_ft_provider_send (provider, contact, file);
+}
+
+static void
+ft_window_filechooser_create (GossipContact *contact)
+{
+	GtkWidget     *dialog;
+	GtkFileFilter *filter;
+
+	d(g_print ("FileTransferWindow: Creating filechooser...\n"));
+
+	dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
+			       "action", GTK_FILE_CHOOSER_ACTION_OPEN,
+			       "select-multiple", FALSE,
+			       NULL);
+	
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Select a file"));
+	gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+				GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+				GTK_STOCK_OPEN, GTK_RESPONSE_OK,
+				NULL);
+
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), 
+					 GTK_RESPONSE_OK);
+
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (ft_window_filechooser_response_cb), 
+			  g_object_ref (contact));
+
+	/* filters */
+	filter = gtk_file_filter_new ();
+	gtk_file_filter_set_name (filter, "All Files");
+	gtk_file_filter_add_pattern (filter, "*");
+	gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
+
+	gtk_widget_show (dialog);
+}
+
+static void
+ft_window_filechooser_response_cb (GtkDialog     *dialog,
+				   gint           response_id,
+				   GossipContact *contact)
+{
+	if (response_id == GTK_RESPONSE_OK) {
+		GSList *list;
+
+		list = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
+
+		if (list) {
+			GSList *l;
+			
+			d(g_print ("FileTransferWindow: File chooser selected files:\n"));
+			
+			for (l = list; l; l = l->next) {
+				gchar *file;
+				
+				file = l->data;
+				
+				d(g_print ("FileTransferWindow: \t%s\n", file));
+				gossip_ft_window_send_file_from_uri (contact, file);
+				
+				g_free (file);
+			}
+			
+			g_slist_free (list);
+		} else {
+			d(g_print ("FileTransferWindow: File chooser had no files selected\n"));
+		}
+	}
+
+	g_object_unref (contact);
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+}
Index: src/gossip-ft-window.h
===================================================================
RCS file: src/gossip-ft-window.h
diff -N src/gossip-ft-window.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/gossip-ft-window.h	16 Nov 2005 21:45:42 -0000
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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.
+ */
+
+#ifndef __GOSSIP_FT_WINDOW_H__
+#define __GOSSIP_FT_WINDOW_H__
+
+#include <libgossip/gossip-session.h>
+#include <libgossip/gossip-contact.h>
+
+
+void gossip_ft_window_init               (GossipSession *session);
+void gossip_ft_window_finalize           (GossipSession *session);
+
+void gossip_ft_window_send_file          (GossipContact *account);
+void gossip_ft_window_send_file_from_uri (GossipContact *contact,
+					  const gchar   *file);
+
+#endif /* __GOSSIP_FT_WINDOW_H__ */
Index: src/gossip-join-dialog.c
===================================================================
RCS file: /cvs/gnome/gossip/src/gossip-join-dialog.c,v
retrieving revision 1.22
diff -u -r1.22 gossip-join-dialog.c
--- src/gossip-join-dialog.c	15 Oct 2005 18:42:27 -0000	1.22
+++ src/gossip-join-dialog.c	16 Nov 2005 21:45:43 -0000
@@ -354,7 +354,7 @@
 		if (cancel_join) {
 			GossipSession          *session;
 			GossipAccount          *account;
-		GossipChatroomProvider *provider;
+			GossipChatroomProvider *provider;
 			
 			session = gossip_app_get_session ();
 			account = join_dialog_get_account_selected (dialog);
Index: src/gossip-subscription-dialog.c
===================================================================
RCS file: src/gossip-subscription-dialog.c
diff -N src/gossip-subscription-dialog.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/gossip-subscription-dialog.c	16 Nov 2005 21:45:44 -0000
@@ -0,0 +1,313 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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 <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <libgnomeui/libgnomeui.h>
+
+#include <libgossip/gossip-protocol.h>
+#include <libgossip/gossip-contact.h>
+#include <libgossip/gossip-event-manager.h>
+#include <libgossip/gossip-vcard.h>
+#include <libgossip/gossip-utils.h>
+
+#include "gossip-subscription-dialog.h"
+#include "gossip-app.h"
+
+
+typedef struct {
+	GossipProtocol *protocol;
+	GossipContact  *contact;
+	GossipVCard    *vcard;
+} SubscriptionData;
+
+
+static void subscription_dialog_protocol_connected_cb    (GossipSession      *session,
+							  GossipAccount      *account,
+							  GossipProtocol     *protocol, 
+							  gpointer            user_data);
+static void subscription_dialog_protocol_disconnected_cb (GossipSession      *session,
+							  GossipAccount      *account,
+							  GossipProtocol     *protocol,
+							  gpointer            user_data);
+static void subscription_dialog_request_cb               (GossipProtocol     *protocol,
+							  GossipContact      *contact,
+							  gpointer            user_data);
+static void subscription_dialog_event_activated_cb       (GossipEventManager *event_manager,
+							  GossipEvent        *event,
+							  GossipProtocol     *protocol);
+static void subscription_dialog_vcard_cb                 (GossipResult        result,
+							  GossipVCard        *vcard,
+							  SubscriptionData   *data);
+static void subscription_dialog_request_dialog_cb        (GtkWidget          *dialog,
+							  gint                response,
+							  SubscriptionData   *data);
+
+
+void
+gossip_subscription_dialog_init (GossipSession *session)
+{
+	g_signal_connect (session, 
+			  "protocol-connected",
+			  G_CALLBACK (subscription_dialog_protocol_connected_cb),
+			  NULL);
+
+	g_signal_connect (session, 
+			  "protocol-disconnected",
+			  G_CALLBACK (subscription_dialog_protocol_disconnected_cb),
+			  NULL);
+}
+
+void
+gossip_subscription_dialog_finalize (GossipSession *session)
+{
+ 	g_signal_handlers_disconnect_by_func (session, 
+					      subscription_dialog_protocol_connected_cb, 
+					      NULL);
+ 	g_signal_handlers_disconnect_by_func (session, 
+					      subscription_dialog_protocol_disconnected_cb, 
+					      NULL);
+}
+
+static void
+subscription_dialog_protocol_connected_cb (GossipSession  *session,
+					   GossipAccount  *account,
+					   GossipProtocol *protocol,
+					   gpointer        user_data)
+{
+	g_signal_connect (protocol,
+                          "subscription-request",
+                          G_CALLBACK (subscription_dialog_request_cb),
+                          session);
+}
+
+static void
+subscription_dialog_protocol_disconnected_cb (GossipSession  *session,
+					      GossipAccount  *account,
+					      GossipProtocol *protocol,
+					      gpointer        user_data)
+{
+ 	g_signal_handlers_disconnect_by_func (protocol, 
+					      subscription_dialog_request_cb, 
+					      session);
+}
+
+static void
+subscription_dialog_request_cb (GossipProtocol *protocol,
+				GossipContact  *contact,
+				gpointer        user_data)
+{
+	GossipEvent      *event;
+	gchar            *str;
+
+	event = gossip_event_new (GOSSIP_EVENT_SUBSCRIPTION_REQUEST);
+
+	str = g_strdup_printf (_("New subscription request from %s"), 
+			       gossip_contact_get_name (contact));
+
+	g_object_set (event, 
+		      "message", str, 
+		      "data", contact,
+		      NULL);
+	g_free (str);
+
+	gossip_event_manager_add (gossip_app_get_event_manager (),
+				  event, 
+				  (GossipEventActivatedFunction)subscription_dialog_event_activated_cb,
+				  G_OBJECT (protocol));
+}
+
+static void
+subscription_dialog_event_activated_cb (GossipEventManager *event_manager,
+					GossipEvent        *event,
+					GossipProtocol     *protocol)
+{
+	GossipContact    *contact;
+	SubscriptionData *data;
+
+	contact = GOSSIP_CONTACT (gossip_event_get_data (event));
+
+	data = g_new0 (SubscriptionData, 1);
+
+	data->protocol = g_object_ref (protocol);
+	data->contact = g_object_ref (contact);
+
+	gossip_session_get_vcard (gossip_app_get_session (),
+				  NULL,
+				  data->contact,
+				  (GossipVCardCallback) subscription_dialog_vcard_cb,
+				  data, 
+				  NULL);
+}
+
+static void
+subscription_dialog_vcard_cb (GossipResult      result,
+			      GossipVCard       *vcard,
+			      SubscriptionData  *data)
+{
+	GtkWidget   *dialog;
+	GtkWidget   *who_label;
+	GtkWidget   *question_label;
+	GtkWidget   *id_label;
+ 	GtkWidget   *website_label;
+ 	GtkWidget   *personal_table;
+	const gchar *name = NULL;
+	const gchar *url = NULL;
+	gchar       *who;
+	gchar       *question;
+	gchar       *str;
+	gint         num_matches = 0;
+
+	if (GOSSIP_IS_VCARD (vcard)) {
+		data->vcard = g_object_ref (vcard);
+
+		name = gossip_vcard_get_name (vcard);
+		url = gossip_vcard_get_url (vcard);
+	}
+
+	gossip_glade_get_file_simple (GLADEDIR "/main.glade",
+				      "subscription_request_dialog",
+				      NULL,
+				      "subscription_request_dialog", &dialog,
+				      "who_label", &who_label,
+				      "question_label", &question_label,
+				      "id_label", &id_label,
+				      "website_label", &website_label,
+				      "personal_table", &personal_table,
+				      NULL);
+
+	if (name) {
+		who = g_strdup_printf (_("%s wants to be added to your contact list."), 
+				       name);
+		question = g_strdup_printf (_("Do you want to add %s to your contact list?"),
+					    name);
+	} else {
+		who = g_strdup (_("Someone wants to be added to your contact list."));
+		question = g_strdup (_("Do you want to add this person to your contact list?"));
+	}
+
+	str = g_strdup_printf ("<span weight='bold' size='larger'>%s</span>", who);
+	gtk_label_set_markup (GTK_LABEL (who_label), str);
+	gtk_label_set_use_markup (GTK_LABEL (who_label), TRUE);
+	g_free (str);
+	g_free (who);
+
+	gtk_label_set_text (GTK_LABEL (question_label), question);
+	g_free (question);
+
+	gtk_label_set_text (GTK_LABEL (id_label), gossip_contact_get_id (data->contact));
+
+	if (url && strlen (url) > 0) {
+		GArray *start, *end;
+
+		start = g_array_new (FALSE, FALSE, sizeof (gint));
+		end = g_array_new (FALSE, FALSE, sizeof (gint));
+		
+		num_matches = gossip_utils_url_regex_match (url, start, end);
+	}
+
+	if (num_matches > 0) {
+		GtkWidget *href;
+		GtkWidget *alignment;
+
+		href = gnome_href_new (url, url);
+
+		alignment = gtk_alignment_new (0, 1, 0, 0.5);
+		gtk_container_add (GTK_CONTAINER (alignment), href);
+
+		gtk_table_attach (GTK_TABLE (personal_table),
+				  alignment, 
+				  1, 2,
+				  1, 2,
+				  GTK_FILL, GTK_FILL,
+				  0, 0);
+		
+		gtk_widget_show_all (personal_table);
+	} else {
+		gtk_widget_hide (website_label);
+	}
+
+	g_signal_connect (dialog,
+			  "response",
+			  G_CALLBACK (subscription_dialog_request_dialog_cb),
+			  data);
+
+	gtk_widget_show (dialog);
+}
+
+static void
+subscription_dialog_request_dialog_cb (GtkWidget        *dialog,
+				       gint              response,
+				       SubscriptionData *data)
+{
+	gboolean add_user;
+
+	g_return_if_fail (GTK_IS_DIALOG (dialog));
+
+	g_return_if_fail (GOSSIP_IS_PROTOCOL (data->protocol));
+	g_return_if_fail (GOSSIP_IS_CONTACT (data->contact));
+
+	add_user = (gossip_contact_get_type (data->contact) == GOSSIP_CONTACT_TYPE_TEMPORARY);
+
+	gtk_widget_destroy (dialog);
+	
+	if (response == GTK_RESPONSE_YES ||
+	    response == GTK_RESPONSE_NO) {
+		gboolean subscribe;
+
+		subscribe = (response == GTK_RESPONSE_YES);
+		gossip_protocol_set_subscription (data->protocol, 
+						  data->contact, 
+						  subscribe);
+
+		if (subscribe && add_user) {
+			const gchar *id, *name, *message;
+			
+			id = gossip_contact_get_id (data->contact);
+			if (data->vcard) {
+				name = gossip_vcard_get_name (data->vcard);
+			} else {
+				name = id;
+			}
+			
+			message = _("I would like to add you to my contact list.");
+					
+			/* FIXME: how is session related to an IM account? */
+			/* micke, hmm .. this feels a bit wrong, should be
+			 * signalled from the protocol when we do 
+			 * set_subscribed
+			 */
+			gossip_protocol_add_contact (data->protocol,
+						     id, name, NULL,
+						     message);
+		}
+	}
+	
+	g_object_unref (data->protocol);
+	g_object_unref (data->contact);
+
+	if (data->vcard) {
+		g_object_unref (data->vcard);
+	}
+	
+	g_free (data);
+}
Index: src/gossip-subscription-dialog.h
===================================================================
RCS file: src/gossip-subscription-dialog.h
diff -N src/gossip-subscription-dialog.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/gossip-subscription-dialog.h	16 Nov 2005 21:45:44 -0000
@@ -0,0 +1,29 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005 Imendio AB
+ *
+ * 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.
+ */
+
+#ifndef __GOSSIP_SUBSCRIPTION_DIALOG_H__
+#define __GOSSIP_SUBSCRIPTION_DIALOG_H__
+
+#include <libgossip/gossip-session.h>
+
+void gossip_subscription_dialog_init     (GossipSession *session);
+void gossip_subscription_dialog_finalize (GossipSession *session);
+
+#endif /* __GOSSIP_SUBSCRIPTION_DIALOG_H__ */
Index: ui/Makefile.am
===================================================================
RCS file: /cvs/gnome/gossip/ui/Makefile.am,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile.am
--- ui/Makefile.am	19 May 2003 18:27:21 -0000	1.1.1.1
+++ ui/Makefile.am	16 Nov 2005 21:45:44 -0000
@@ -2,9 +2,10 @@
 
 gladedir = $(datadir)/gossip
 glade_DATA = 				\
-	main.glade                      \
 	chat.glade                      \
+	connect.glade			\
 	group-chat.glade		\
-	connect.glade
+	file-transfer.glade		\
+	main.glade
 
 EXTRA_DIST = $(glade_DATA)
Index: ui/file-transfer.glade
===================================================================
RCS file: ui/file-transfer.glade
diff -N ui/file-transfer.glade
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ui/file-transfer.glade	16 Nov 2005 21:45:44 -0000
@@ -0,0 +1,589 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="file_transfers">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Gossip - File Transfers</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+
+  <child>
+    <placeholder/>
+  </child>
+</widget>
+
+<widget class="GtkDialog" id="file_transfer_dialog">
+  <property name="title" translatable="yes">Gossip - File Transfer Request</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">False</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+  <property name="has_separator">False</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">12</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="hbuttonbox1">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="button4">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-9</property>
+
+	      <child>
+		<widget class="GtkAlignment" id="alignment1">
+		  <property name="visible">True</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xscale">0</property>
+		  <property name="yscale">0</property>
+		  <property name="top_padding">0</property>
+		  <property name="bottom_padding">0</property>
+		  <property name="left_padding">0</property>
+		  <property name="right_padding">0</property>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox1">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">2</property>
+
+		      <child>
+			<widget class="GtkImage" id="image1">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-no</property>
+			  <property name="icon_size">4</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label1">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">_Deny</property>
+			  <property name="use_underline">True</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="button5">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-8</property>
+
+	      <child>
+		<widget class="GtkAlignment" id="alignment2">
+		  <property name="visible">True</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xscale">0</property>
+		  <property name="yscale">0</property>
+		  <property name="top_padding">0</property>
+		  <property name="bottom_padding">0</property>
+		  <property name="left_padding">0</property>
+		  <property name="right_padding">0</property>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox2">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">2</property>
+
+		      <child>
+			<widget class="GtkImage" id="image2">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-yes</property>
+			  <property name="icon_size">4</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label2">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">_Accept</property>
+			  <property name="use_underline">True</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0.5</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+		    </widget>
+		  </child>
+		</widget>
+	      </child>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkVBox" id="vbox2">
+	  <property name="border_width">6</property>
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox3">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">12</property>
+
+	      <child>
+		<widget class="GtkImage" id="image3">
+		  <property name="visible">True</property>
+		  <property name="stock">gtk-dialog-question</property>
+		  <property name="icon_size">6</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkVBox" id="vbox3">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">18</property>
+
+		  <child>
+		    <widget class="GtkLabel" id="who_label">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes"></property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">True</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkVBox" id="vbox4">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">0</property>
+
+		      <child>
+			<widget class="GtkTable" id="personal_table">
+			  <property name="visible">True</property>
+			  <property name="n_rows">2</property>
+			  <property name="n_columns">2</property>
+			  <property name="homogeneous">False</property>
+			  <property name="row_spacing">2</property>
+			  <property name="column_spacing">6</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="id_label">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="label" translatable="yes"></property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">True</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">1</property>
+			      <property name="right_attach">2</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="label5">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Contact ID:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">0</property>
+			      <property name="bottom_attach">1</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="website_label">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">Web site:</property>
+			      <property name="use_underline">False</property>
+			      <property name="use_markup">False</property>
+			      <property name="justify">GTK_JUSTIFY_LEFT</property>
+			      <property name="wrap">False</property>
+			      <property name="selectable">False</property>
+			      <property name="xalign">0</property>
+			      <property name="yalign">0.5</property>
+			      <property name="xpad">0</property>
+			      <property name="ypad">0</property>
+			      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			      <property name="width_chars">-1</property>
+			      <property name="single_line_mode">False</property>
+			      <property name="angle">0</property>
+			    </widget>
+			    <packing>
+			      <property name="left_attach">0</property>
+			      <property name="right_attach">1</property>
+			      <property name="top_attach">1</property>
+			      <property name="bottom_attach">2</property>
+			      <property name="x_options">fill</property>
+			      <property name="y_options"></property>
+			    </packing>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">True</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">True</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="label7">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">This person wishes to send you this file:</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">True</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkTable" id="table2">
+		      <property name="visible">True</property>
+		      <property name="n_rows">2</property>
+		      <property name="n_columns">2</property>
+		      <property name="homogeneous">False</property>
+		      <property name="row_spacing">2</property>
+		      <property name="column_spacing">6</property>
+
+		      <child>
+			<widget class="GtkLabel" id="file_name_label">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="label" translatable="yes"></property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">True</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">0</property>
+			  <property name="bottom_attach">1</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label10">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">File name:</property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">0</property>
+			  <property name="right_attach">1</property>
+			  <property name="top_attach">0</property>
+			  <property name="bottom_attach">1</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label11">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">File size:</property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">False</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">0</property>
+			  <property name="right_attach">1</property>
+			  <property name="top_attach">1</property>
+			  <property name="bottom_attach">2</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="file_size_label">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="label" translatable="yes"></property>
+			  <property name="use_underline">False</property>
+			  <property name="use_markup">False</property>
+			  <property name="justify">GTK_JUSTIFY_LEFT</property>
+			  <property name="wrap">False</property>
+			  <property name="selectable">True</property>
+			  <property name="xalign">0</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+			  <property name="width_chars">-1</property>
+			  <property name="single_line_mode">False</property>
+			  <property name="angle">0</property>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">1</property>
+			  <property name="bottom_attach">2</property>
+			  <property name="x_options">fill</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">True</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+
+		  <child>
+		    <widget class="GtkLabel" id="label_question">
+		      <property name="visible">True</property>
+		      <property name="label" translatable="yes">Do you want to accept this file?</property>
+		      <property name="use_underline">False</property>
+		      <property name="use_markup">True</property>
+		      <property name="justify">GTK_JUSTIFY_LEFT</property>
+		      <property name="wrap">True</property>
+		      <property name="selectable">False</property>
+		      <property name="xalign">0</property>
+		      <property name="yalign">0.5</property>
+		      <property name="xpad">0</property>
+		      <property name="ypad">0</property>
+		      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		      <property name="width_chars">-1</property>
+		      <property name="single_line_mode">False</property>
+		      <property name="angle">0</property>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">False</property>
+		    </packing>
+		  </child>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">True</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
Index: ui/file-transfer.gladep
===================================================================
RCS file: ui/file-transfer.gladep
diff -N ui/file-transfer.gladep
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ui/file-transfer.gladep	16 Nov 2005 21:45:44 -0000
@@ -0,0 +1,8 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
+
+<glade-project>
+  <name>File-transfer</name>
+  <program_name>file-transfer</program_name>
+  <gnome_support>FALSE</gnome_support>
+</glade-project>
Index: ui/main.glade
===================================================================
RCS file: /cvs/gnome/gossip/ui/main.glade,v
retrieving revision 1.105
diff -u -r1.105 main.glade
--- ui/main.glade	12 Nov 2005 11:49:36 -0000	1.105
+++ ui/main.glade	16 Nov 2005 21:45:51 -0000
@@ -53,7 +53,7 @@
 			  <property name="use_underline">True</property>
 
 			  <child internal-child="image">
-			    <widget class="GtkImage" id="image111">
+			    <widget class="GtkImage" id="image125">
 			      <property name="visible">True</property>
 			      <property name="stock">gtk-execute</property>
 			      <property name="icon_size">1</property>
@@ -73,7 +73,7 @@
 			  <property name="use_underline">True</property>
 
 			  <child internal-child="image">
-			    <widget class="GtkImage" id="image112">
+			    <widget class="GtkImage" id="image126">
 			      <property name="visible">True</property>
 			      <property name="stock">gtk-execute</property>
 			      <property name="icon_size">1</property>
@@ -108,7 +108,7 @@
 			  <accelerator key="N" modifiers="GDK_CONTROL_MASK" signal="activate"/>
 
 			  <child internal-child="image">
-			    <widget class="GtkImage" id="image113">
+			    <widget class="GtkImage" id="image127">
 			      <property name="visible">True</property>
 			      <property name="pixbuf">gossip-message.png</property>
 			      <property name="xalign">0.5</property>
@@ -133,7 +133,7 @@
 			  <property name="use_underline">True</property>
 
 			  <child internal-child="image">
-			    <widget class="GtkImage" id="image114">
+			    <widget class="GtkImage" id="image128">
 			      <property name="visible">True</property>
 			      <property name="stock">gtk-add</property>
 			      <property name="icon_size">1</property>
@@ -157,19 +157,6 @@
 		      </child>
 
 		      <child>
-			<widget class="GtkSeparatorMenuItem" id="separator1">
-			</widget>
-		      </child>
-
-		      <child>
-			<widget class="GtkMenuItem" id="actions_configure_transports">
-			  <property name="sensitive">False</property>
-			  <property name="label" translatable="yes">Configure Transports</property>
-			  <property name="use_underline">True</property>
-			</widget>
-		      </child>
-
-		      <child>
 			<widget class="GtkSeparatorMenuItem" id="avskiljare2">
 			  <property name="visible">True</property>
 			</widget>
@@ -211,7 +198,7 @@
 		      </child>
 
 		      <child>
-			<widget class="GtkSeparatorMenuItem" id="avskiljare4">
+			<widget class="GtkSeparatorMenuItem" id="separator2">
 			  <property name="visible">True</property>
 			</widget>
 		      </child>
@@ -223,7 +210,7 @@
 			  <property name="use_underline">True</property>
 
 			  <child internal-child="image">
-			    <widget class="GtkImage" id="image115">
+			    <widget class="GtkImage" id="image129">
 			      <property name="visible">True</property>
 			      <property name="stock">gtk-preferences</property>
 			      <property name="icon_size">1</property>
@@ -2498,7 +2485,7 @@
 			  <property name="column_spacing">6</property>
 
 			  <child>
-			    <widget class="GtkLabel" id="jid_label">
+			    <widget class="GtkLabel" id="id_label">
 			      <property name="visible">True</property>
 			      <property name="can_focus">True</property>
 			      <property name="label" translatable="yes"></property>
@@ -2528,7 +2515,7 @@
 			  <child>
 			    <widget class="GtkLabel" id="label22">
 			      <property name="visible">True</property>
-			      <property name="label" translatable="yes">Jabber ID:</property>
+			      <property name="label" translatable="yes">ID:</property>
 			      <property name="use_underline">False</property>
 			      <property name="use_markup">False</property>
 			      <property name="justify">GTK_JUSTIFY_LEFT</property>
