Add a function to handle incoming data in the filetransfert module.
authorNicolas Cornu <nicolas.cornu@ensi-bourges.fr>
Sun, 18 Jul 2010 18:55:22 +0200
changeset 53 64a47491c068
parent 52 d803c882a182
child 54 1c1153f9f945
Add a function to handle incoming data in the filetransfert module. Also, check the filename and md5 hash in the jingle_ft_check function.
jingle-filetransfer/filetransfer.c
jingle-filetransfer/filetransfer.h
--- a/jingle-filetransfer/filetransfer.c	Tue Jul 13 18:30:23 2010 +0200
+++ b/jingle-filetransfer/filetransfer.c	Sun Jul 18 18:55:22 2010 +0200
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include <glib.h>
+#include <string.h>
 
 #include <mcabber/modules.h>
 #include <mcabber/utils.h>
@@ -35,6 +36,7 @@
 
 
 gconstpointer jingle_ft_check(JingleContent *cn, GError **err);
+static gboolean is_md5_hash(const gchar *hash);
 static void jingle_ft_init(void);
 static void jingle_ft_uninit(void);
 
@@ -83,17 +85,17 @@
 
   ft = g_new0(JingleFT, 1);
   datestr  = lm_message_node_get_attribute(node, "date");
-  ft->hash = lm_message_node_get_attribute(node, "hash");
-  ft->name = lm_message_node_get_attribute(node, "name");
+  ft->hash = (gchar *) lm_message_node_get_attribute(node, "hash");
+  ft->name = (gchar *) lm_message_node_get_attribute(node, "name");
   sizestr  = lm_message_node_get_attribute(node, "size");
-  
+
   if (!ft->name || !sizestr) {
     g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_MISSING,
                 "an attribute of the file element is missing");
     g_free(ft);
     return NULL;
   }
-  
+
   ft->date = from_iso8601(datestr, 1);
   ft->size = g_ascii_strtoll(sizestr, NULL, 10);
 
@@ -105,9 +107,68 @@
     return NULL;
   }
 
+  ft->name = g_path_get_basename(ft->name);
+  if (!g_strcmp0(ft->name, ".")) {
+    g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_BADVALUE,
+                "the offered file has an invalid filename");
+    g_free(ft->name);
+    g_free(ft);
+    return NULL;
+  }
+
+  // check if the md5 hash is valid ([a-fA-F0-9){32})
+  if (ft->hash != NULL && (strlen(ft->hash) != 32 || !is_md5_hash(ft->hash))) {
+    g_set_error(err, JINGLE_CHECK_ERROR, JINGLE_CHECK_ERROR_BADVALUE,
+                "the offered file has an invalid filename");
+    g_free(ft->name);
+    g_free(ft);
+    return NULL;
+  }
+  ft->hash = g_strndup(ft->hash, 32);
+
   return (gconstpointer) ft;
 }
 
+static gboolean is_md5_hash(const gchar *hash) {
+  int i = 0;
+  for (i = 0; i < 32 && hash[i]; i++)
+    if (!g_ascii_isxdigit(hash[i])) break;
+
+  if (i == 31)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+gboolean handle_data(gconstpointer *jingleft, const gchar *data, guint len)
+{
+  JingleFT *ft = (JingleFT *) jingleft;
+  GError *err = NULL;
+  GIOStatus status;
+  gsize bytes_written = 0;
+
+  // TODO: check if the file already exist or if it was created
+  // during the call to jingle_ft_check and handle_data
+  if (ft->outfile == NULL) {
+    ft->outfile = g_io_channel_new_file(ft->name, "w", &err);
+    if (ft->outfile == NULL || err != NULL) {
+      // propagate the GError ?
+      return FALSE;
+	}
+  }
+  status = g_io_channel_write_chars(ft->outfile, data, (gssize) len,
+                                    &bytes_written, &err);
+
+  if (status != G_IO_STATUS_NORMAL || err != NULL) {
+    return FALSE;
+  }
+  if (bytes_written != len) {
+    // not supposed to happen if status is normal, unless outfile is non-blocking
+    return FALSE;
+  }
+  return TRUE;
+}
+
 static void jingle_ft_init(void)
 {
   jingle_register_app(NS_JINGLE_APP_FT, &funcs, JINGLE_TRANS_TCP);
--- a/jingle-filetransfer/filetransfer.h	Tue Jul 13 18:30:23 2010 +0200
+++ b/jingle-filetransfer/filetransfer.h	Sun Jul 18 18:55:22 2010 +0200
@@ -10,13 +10,16 @@
   time_t date;
 
   /* MD5 hash of the file, optional */
-  const gchar *hash;
+  gchar *hash;
 
   /* the name of the file that the sender wishes to send */
-  const gchar *name;
+  gchar *name;
 
   /* the size, in bytes, of the data to be sent */
   gint64 size;
+
+  /* descriptor to the output file */
+  GIOChannel *outfile;
 } JingleFT;
 
 #endif