]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-ft-handler.c
W.I.P. for heavy lifting on EmpathyTpFile.
[empathy.git] / libempathy / empathy-ft-handler.c
index dfaeceabfa6d8311d1b4fcca4d11222610eab0d9..c1365fb863f35c2781d9e560fb315e34641fa6b5 100644 (file)
@@ -74,6 +74,12 @@ typedef struct {
   gssize total_read;
 } HashingData;
 
+typedef struct {
+  EmpathyFTHandlerReadyCallback callback;
+  gpointer user_data;
+  EmpathyFTHandler *handler;
+} CallbacksData;
+
 /* private data */
 typedef struct {
   gboolean dispose_run;
@@ -81,6 +87,15 @@ typedef struct {
   GFile *gfile;
   EmpathyTpFile *tpfile;
   GCancellable *cancellable;
+
+  /* transfer properties */
+  gchar *content_type;
+  gchar *filename;
+  gchar *description;
+  guint64 total_bytes;
+  guint64 transferred_bytes;
+  gchar *content_hash;
+  EmpFileHashType content_hash_type;
 } EmpathyFTHandlerPriv;
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -638,10 +653,48 @@ ft_handler_read_async_cb (GObject *source,
   schedule_hash_chunk (hash_data);
 }
 
+static void
+ft_handler_complete_request (EmpathyFTHandler *handler)
+{ 
+  EmpathyFTHandlerPriv *priv = GET_PRIV (handler);
+  GError *myerr = NULL;
+
+  g_cancellable_set_error_if_cancelled (priv->cancellable, &myerr);
+
+  if (myerr == NULL)
+    {
+      if (error != NULL)
+        {
+          myerr = g_error_copy (error);
+        }
+      else
+        {
+          /* check if FT is allowed before firing up the I/O machinery */
+          if (!ft_handler_check_if_allowed (req_data->handler))
+            {
+              g_set_error_literal (&myerr, EMPATHY_FT_ERROR_QUARK,
+                  EMPATHY_FT_ERROR_NOT_SUPPORTED,
+                  _("File transfer not supported by remote contact"));
+            }
+        }
+    }
+
+  if (myerr != NULL)
+    {
+      g_signal_emit (req_data->handler, signals[TRANSFER_ERROR], 0, myerr);
+
+      request_data_free (req_data);
+      g_clear_error (&myerr);
+
+      return;
+    }
+
+}
+
 static void
 ft_handler_gfile_ready_cb (GObject *source,
                            GAsyncResult *res,
-                           RequestData *req_data)
+                           CallbacksData *cb_data)
 {
   GFileInfo *info;
   GError *error = NULL;
@@ -652,9 +705,7 @@ ft_handler_gfile_ready_cb (GObject *source,
   info = g_file_query_info_finish (req_data->gfile, res, &error);
   if (error != NULL)
     {
-      g_signal_emit (req_data->handler, signals[TRANSFER_ERROR], 0, error);
-
-      request_data_free (req_data);
+      /* TODO: error handling */
       g_clear_error (&error);
 
       return;
@@ -675,78 +726,131 @@ ft_handler_contact_ready_cb (EmpathyContact *contact,
                              gpointer user_data,
                              GObject *weak_object)  
 {
-  RequestData *req_data = user_data;
-  EmpathyFTHandlerPriv *priv = GET_PRIV (req_data->handler);
-  GError *myerr = NULL;
+  CallbacksData *cb_data = user_data;
+  EmpathyFTHandlerPriv *priv = GET_PRIV (weak_object);
 
   g_assert (priv->contact != NULL);
   g_assert (priv->gfile != NULL);
 
   DEBUG ("FT: contact is ready.");
 
-  g_cancellable_set_error_if_cancelled (priv->cancellable, &myerr);
+  /* start collecting info about the file */
+  g_file_query_info_async (priv->gfile,
+      G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+      G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+      G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+      G_FILE_ATTRIBUTE_TIME_MODIFIED,
+      G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
+      NULL, (GAsyncReadyCallback) ft_handler_gfile_ready_cb,
+      cb_data);
+}
 
-  if (myerr == NULL)
-    {
-      if (error != NULL)
-        {
-          myerr = g_error_copy (error);
-        }
-      else
-        {
-          /* check if FT is allowed before firing up the I/O machinery */
-          if (!ft_handler_check_if_allowed (req_data->handler))
-            {
-              g_set_error_literal (&myerr, EMPATHY_FT_ERROR_QUARK,
-                  EMPATHY_FT_ERROR_NOT_SUPPORTED,
-                  _("File transfer not supported by remote contact"));
-            }
-        }
-    }
+static void
+callbacks_data_free (gpointer user_data)
+{
+  CallbacksData *data = user_data;
 
-  if (myerr != NULL)
-    {
-      g_signal_emit (req_data->handler, signals[TRANSFER_ERROR], 0, myerr);
+  g_object_unref (data->handler);
 
-      request_data_free (req_data);
-      g_clear_error (&myerr);
+  g_slice_free (CallbacksData, data);
+}
+
+static void
+channel_get_all_properties_cb (TpProxy *proxy,
+                               GHashTable *properties,
+                               const GError *error,
+                               gpointer user_data,
+                               GObject *weak_object)
+{
+  CallbacksData *cb_data = user_data;
+  EmpathyFTHandler *handler = EMPATHY_FT_HANDLER (weak_object);
+  EmpathyFTHandlerPriv *priv = GET_PRIV (handler);
 
+  if (error != NULL)
+    {
+      cb_data->callback (handler, error, cb_data->user_data);
       return;
     }
 
-  /* start collecting info about the file */
-  g_file_query_info_async (req_data->gfile,
-      G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
-      G_FILE_ATTRIBUTE_STANDARD_SIZE ","
-      G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
-      G_FILE_ATTRIBUTE_TIME_MODIFIED,
-      G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT,
-      priv->cancellable, (GAsyncReadyCallback) ft_handler_gfile_ready_cb,
-      req_data);
+  priv->total_bytes = g_value_get_uint64 (
+      g_hash_table_lookup (properties, "Size"));
+
+  priv->transferred_bytes = g_value_get_uint64 (
+      g_hash_table_lookup (properties, "TransferredBytes"));
+
+  priv->filename = g_value_dup_string (
+      g_hash_table_lookup (properties, "Filename"));
+
+  priv->content_hash = g_value_dup_string (
+      g_hash_table_lookup (properties, "ContentHash"));
+
+  priv->content_hash_type = g_value_get_uint (
+      g_hash_table_lookup (properties, "ContentHashType"));
+
+  priv->content_type = g_value_dup_string (
+      g_hash_table_lookup (properties, "ContentType"));
+
+  priv->description = g_value_dup_string (
+      g_hash_table_lookup (properties, "Description"));
+
+  g_hash_table_destroy (properties);
+
+  cb_data->callback (handler, NULL, cb_data->user_data);
 }
 
 /* public methods */
 
-EmpathyFTHandler*
+void
 empathy_ft_handler_new_outgoing (EmpathyContact *contact,
-                                 GFile *source)
+                                 GFile *source,
+                                 EmpathyFTHandlerReadyCallback callback,
+                                 gpointer user_data)
 {
+  EmpathyFTHandler *handler;
+  CallbacksData *data;
+
   g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL);
   g_return_val_if_fail (G_IS_FILE (source), NULL);
 
-  return g_object_new (EMPATHY_TYPE_FT_HANDLER,
+  handler = g_object_new (EMPATHY_TYPE_FT_HANDLER,
       "contact", contact, "gfile", source, NULL);
+
+  data = g_slice_new0 (CallbacksData);
+  data->callback = callback;
+  data->user_data = user_data;
+  data->handler = g_object_ref (handler);
+
+  empathy_contact_call_when_ready (priv->contact,
+      EMPATHY_CONTACT_READY_HANDLE,
+      ft_handler_contact_ready_cb, data, NULL, G_OBJECT (handler));
 }
 
-EmpathyFTHandler *
+void
 empathy_ft_handler_new_incoming (EmpathyTpFile *tp_file,
-                                 GFile *destination)
+                                 GFile *destination,
+                                 EmpathyFTHandlerReadyCallback callback,
+                                 gpointer user_data)
 {
+  EmpathyFTHandler *handler;
+  TpChannel *channel;
+  CallbacksData *data;
+
   g_return_val_if_fail (EMPATHY_IS_TP_FILE (tp_file), NULL);
   g_return_val_if_fail (G_IS_FILE (destination), NULL);
 
-  return g_object_new (EMPATHY_TYPE_FT_HANDLER,
+  handler = g_object_new (EMPATHY_TYPE_FT_HANDLER,
       "tp-file", tp_file, "gfile", destination, NULL);
+
+  g_object_get (tp_file, "channel", &channel, NULL);
+
+  data = g_slice_new0 (CallbacksData);
+  data->callback = callback;
+  data->user_data = user_data;
+  data->handler = g_object_ref (handler);
+
+  tp_cli_dbus_properties_call_get_all (channel,
+      -1, EMP_IFACE_CHANNEL_TYPE_FILE_TRANSFER,
+      channel_get_all_properties_cb, data, callbacks_data_free, G_OBJECT (handler));
 }
 
 void