? ft.patch
? protocols/jabber/ft.patch
? protocols/jabber/gossip-jabber-file-transfer.c
? protocols/jabber/gossip-jabber-file-transfer.h
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	8 Nov 2005 19:24:25 -0000
@@ -14,6 +14,10 @@
 	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-vcard.c			\
 	gossip-jabber-vcard.h			\
 	gossip-jabber-services.c		\
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	8 Nov 2005 19:24:26 -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	8 Nov 2005 19:24:26 -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	8 Nov 2005 19:24:26 -0000
@@ -0,0 +1,366 @@
+/* -*- 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 <loudmouth/loudmouth.h>
+
+#include "gossip-jabber-ft.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"
+
+
+/* static GHashTable *ids = NULL; */
+
+
+void 
+gossip_jabber_ft_init (void)
+{
+/* 	ids = g_hash_table_new_full (g_str_hash, */
+/* 				     g_str_equal, */
+/* 				     g_free, */
+				     
+}
+
+void
+gossip_jabber_ft_send (const gchar *to,
+		       const gchar *file_name,
+		       const gchar *file_size,
+		       const gchar *mime_type)
+{
+	LmMessage     *m;
+	LmMessageNode *node, *si_node, *field_node;
+	
+	const gchar   *mime_type_used = NULL;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (file_name != NULL);
+	g_return_if_fail (file_size != NULL);
+
+	if (mime_type && mime_type[0] != '\0') {
+		mime_type = "text/plain";
+	}
+
+	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, "si", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_FILE_TRANSFER_XMLNS,
+					"id", "ft1",
+					"mime-type", mime_type_used,
+					"profile", XMPP_FILE_TRANSFER_PROFILE,
+					NULL);
+
+	si_node = node;
+
+	node = lm_message_node_add_child (si_node, "file", NULL);
+	lm_message_node_set_attributes (node, 
+					"xmlns", XMPP_FILE_XMLNS,
+					"name", file_name,
+					"size", file_size,
+					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, 
+					"xmlns", "jabber:x:data",
+					"type", "form",
+					NULL);
+
+	node = lm_message_node_add_child (node, "field", NULL);
+	lm_message_node_set_attributes (node, 
+					"var", "stream-method",
+					"type", "list-single",
+					NULL);
+
+	field_node = node;
+
+	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 */
+/* 	lm_connection_send (priv->connection, m, NULL); */
+	lm_message_unref (m);
+}
+		
+void
+gossip_jabber_ft_send_response (const gchar *to,
+				const gchar *id)
+{
+	LmMessage     *m;
+	LmMessageNode *node;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (id != NULL);
+
+	m = lm_message_new_with_sub_type (to,
+					  LM_MESSAGE_TYPE_IQ,
+					  LM_MESSAGE_SUB_TYPE_RESULT);
+	node = m->node;
+	lm_message_node_set_attributes (node, 
+					"id", id,
+					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 (priv->connection, m, NULL); */
+	lm_message_unref (m);
+}
+
+
+/*
+ * stream stuff
+ */
+
+void
+gossip_jabber_ft_iib_start (const gchar *to)
+{
+	LmMessage     *m;
+	LmMessageNode *node;
+
+	const gchar   *sid = "test";
+	const gchar   *block_size = "4096";
+
+	g_return_if_fail (to != NULL);
+
+	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 (priv->connection, m, NULL); */
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_start_response (const gchar *to,
+				     const gchar *id)
+{
+	LmMessage     *m;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (id != NULL);
+
+	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 (priv->connection, m, NULL); */
+	lm_message_unref (m);
+}
+
+
+void
+gossip_jabber_ft_iib_error (const gchar *to,
+			    const gchar *id,
+			    const gchar *error_code,
+			    const gchar *error_type)
+{
+	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);
+
+	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 (priv->connection, m, NULL); */
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_send (const gchar *to,
+			   const gchar *sid,
+			   const gchar *data,
+			   const gchar *seq)
+{
+	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);
+
+	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 (priv->connection, m, NULL); */
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_finish (const gchar *to,
+			     const gchar *sid)
+{
+	LmMessage     *m;
+	LmMessageNode *node;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (sid != NULL);
+
+	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 (priv->connection, m, NULL); */
+	lm_message_unref (m);
+}
+
+void
+gossip_jabber_ft_iib_finish_response (const gchar *to,
+				      const gchar *id)
+{
+	LmMessage     *m;
+
+	g_return_if_fail (to != NULL);
+	g_return_if_fail (id != NULL);
+
+	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 (priv->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	8 Nov 2005 19:24:26 -0000
@@ -0,0 +1,55 @@
+/* -*- 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>
+
+void gossip_jabber_ft_init                (void);
+void gossip_jabber_ft_send                (const gchar *to,
+					   const gchar *file_name,
+					   const gchar *file_size,
+					   const gchar *mime_type);
+void gossip_jabber_ft_send_response       (const gchar *to,
+					   const gchar *id);
+
+/*
+ * stream API
+ */
+void gossip_jabber_ft_iib_start           (const gchar *to);
+void gossip_jabber_ft_iib_start_response  (const gchar *to,
+					   const gchar *id);
+void gossip_jabber_ft_iib_error           (const gchar *to,
+					   const gchar *id,
+					   const gchar *error_code,
+					   const gchar *error_type);
+void gossip_jabber_ft_iib_send            (const gchar *to,
+					   const gchar *sid,
+					   const gchar *data,
+					   const gchar *seq);
+void gossip_jabber_ft_iib_finish          (const gchar *to,
+					   const gchar *sid);
+void gossip_jabber_ft_iib_finish_response (const gchar *to,
+					   const gchar *id);
+
+
+
+#endif /* __GOSSIP_JABBER_FT_H__ */
