/* * Syncdaemon API * * Authors: Rodrigo Moya * * Copyright 2010-2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see . * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your * version. If you delete this exception statement from all source * files in the program, then also delete it here. * */ #include "config.h" #include "syncdaemon-shares-interface.h" #include "utils.h" G_DEFINE_TYPE(SyncdaemonSharesInterface, syncdaemon_shares_interface, SYNCDAEMON_TYPE_INTERFACE) struct _SyncdaemonSharesInterfacePrivate { GObject *proxy; GHashTable *shared; GHashTable *shares; }; typedef struct _AddEmblemData { SyncdaemonSharesInterface *interface; gchar *path; } AddEmblemData; static void syncdaemon_shares_interface_finalize (GObject *object) { SyncdaemonSharesInterface *interface = SYNCDAEMON_SHARES_INTERFACE (object); if (interface->priv != NULL) { g_free (interface->priv); } G_OBJECT_CLASS (syncdaemon_shares_interface_parent_class)->finalize (object); } static void syncdaemon_shares_interface_class_init (SyncdaemonSharesInterfaceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = syncdaemon_shares_interface_finalize; } static void share_created_cb (DBusGProxy *proxy, GHashTable *hash, gpointer user_data) { SyncdaemonDaemon *daemon = NULL; SyncdaemonShareInfo *share_info; SyncdaemonSharesInterface *interface = SYNCDAEMON_SHARES_INTERFACE (user_data); share_info = syncdaemon_share_info_new_from_hash_table (hash); switch (syncdaemon_share_info_get_share_type (share_info)) { case SYNCDAEMON_SHARE_INFO_TYPE_SHARED: if (interface->priv->shared == NULL) { GSList *shared; shared = syncdaemon_shares_interface_get_shared (interface); g_slist_free (shared); } g_hash_table_insert (interface->priv->shared, g_strdup (syncdaemon_share_info_get_path (share_info)), share_info); break; case SYNCDAEMON_SHARE_INFO_TYPE_SHARE: if (interface->priv->shares == NULL) { GSList *shares; shares = syncdaemon_shares_interface_get_shares (interface); g_slist_free (shares); } g_hash_table_insert (interface->priv->shares, g_strdup (syncdaemon_share_info_get_path (share_info)), share_info); break; default: return; } g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "share_created", TRUE, share_info); } static void share_create_error_cb (DBusGProxy *proxy, GHashTable *hash, const gchar *error, gpointer user_data) { SyncdaemonDaemon *daemon = NULL; SyncdaemonSharesInterface *interface = SYNCDAEMON_SHARES_INTERFACE (user_data); g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) { SyncdaemonShareInfo *share_info; share_info = syncdaemon_share_info_new_from_hash_table (hash); g_signal_emit_by_name (daemon, "share_created", FALSE, share_info); g_object_unref (G_OBJECT (share_info)); } } static void share_deleted_cb (DBusGProxy *proxy, GHashTable *hash, gpointer user_data) { SyncdaemonDaemon *daemon = NULL; SyncdaemonShareInfo *share_info; SyncdaemonSharesInterface *interface = SYNCDAEMON_SHARES_INTERFACE (user_data); share_info = syncdaemon_share_info_new_from_hash_table (hash); switch (syncdaemon_share_info_get_share_type (share_info)) { case SYNCDAEMON_SHARE_INFO_TYPE_SHARED: if (interface->priv->shared != NULL) g_hash_table_remove (interface->priv->shared, syncdaemon_share_info_get_path (share_info)); break; case SYNCDAEMON_SHARE_INFO_TYPE_SHARE: if (interface->priv->shares != NULL) g_hash_table_remove (interface->priv->shares, syncdaemon_share_info_get_path (share_info)); break; default: return; } g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "share_deleted", TRUE, share_info); g_object_unref (G_OBJECT (share_info)); } static void share_delete_error_cb (DBusGProxy *proxy, GHashTable *hash, const gchar *error, gpointer user_data) { SyncdaemonDaemon *daemon = NULL; SyncdaemonSharesInterface *interface = SYNCDAEMON_SHARES_INTERFACE (user_data); g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) { SyncdaemonShareInfo *share_info; share_info = syncdaemon_share_info_new_from_hash_table (hash); g_signal_emit_by_name (daemon, "share_deleted", FALSE, share_info); g_object_unref (G_OBJECT (share_info)); } } static void syncdaemon_shares_interface_init (SyncdaemonSharesInterface *interface) { interface->priv = g_new0 (SyncdaemonSharesInterfacePrivate, 1); /* Setup DBus proxy */ interface->priv->proxy = syncdaemon_interface_setup_proxy (SYNCDAEMON_INTERFACE (interface), "com.ubuntuone.SyncDaemon", "/shares", "com.ubuntuone.SyncDaemon.Shares"); if (interface->priv->proxy != NULL) { /* Connect to DBus signals */ dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareCreated", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareCreated", G_CALLBACK (share_created_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareCreateError", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareCreateError", G_CALLBACK (share_create_error_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareDeleted", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareDeleted", G_CALLBACK (share_deleted_cb), interface, NULL); dbus_g_proxy_add_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareDeleteError", dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING), G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal (DBUS_G_PROXY (interface->priv->proxy), "ShareDeleteError", G_CALLBACK (share_delete_error_cb), interface, NULL); } } /** * syncdaemon_shares_interface_new: */ SyncdaemonSharesInterface * syncdaemon_shares_interface_new (SyncdaemonDaemon *daemon) { g_return_val_if_fail (SYNCDAEMON_IS_DAEMON (daemon), NULL); return g_object_new (SYNCDAEMON_TYPE_SHARES_INTERFACE, "daemon", daemon, NULL); } /** * syncdaemon_shares_interface_accept: */ void syncdaemon_shares_interface_accept (SyncdaemonSharesInterface *interface, const gchar *share_id) { g_return_if_fail (SYNCDAEMON_IS_SHARES_INTERFACE (interface)); g_return_if_fail (share_id != NULL); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "accept_share", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_STRING, share_id, G_TYPE_INVALID); } void add_emblem_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { SyncdaemonShareInfo *share_info; SyncdaemonDaemon *daemon; GHashTable *hash; AddEmblemData *emblem_data = user_data; hash = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (hash, "path", emblem_data->path); share_info = syncdaemon_share_info_new_from_hash_table (hash); g_hash_table_unref (hash); g_hash_table_insert (emblem_data->interface->priv->shared, g_strdup (syncdaemon_share_info_get_path (share_info)), share_info); g_object_get (G_OBJECT (emblem_data->interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "share_created", TRUE, share_info); no_output_dbus_call_ended_cb (proxy, call_id, user_data); g_object_unref (emblem_data->interface); g_free (emblem_data->path); g_free (emblem_data); } /** * syncdaemon_shares_interface_create: */ void syncdaemon_shares_interface_create (SyncdaemonSharesInterface *interface, const gchar *path, GSList *usernames, const gchar *name, gboolean allow_modifications) { AddEmblemData *emblem_data; g_return_if_fail (SYNCDAEMON_IS_SHARES_INTERFACE (interface)); g_return_if_fail (path != NULL); g_return_if_fail (usernames != NULL); g_return_if_fail (name != NULL); emblem_data = g_new0 (AddEmblemData, 1); emblem_data->interface = g_object_ref (interface); emblem_data->path = g_strdup (path); if (g_slist_length (usernames) == 1) { dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "create_share", add_emblem_cb, emblem_data, NULL, G_TYPE_STRING, path, G_TYPE_STRING, (const gchar *) usernames->data, G_TYPE_STRING, name, G_TYPE_STRING, allow_modifications ? "Modify" : "View", G_TYPE_INVALID); } else { GSList *l; gint i; gchar **users_array = g_new0 (gchar *, g_slist_length (usernames)); for (l = usernames, i = 0; l != NULL; l = l->next, i++) users_array[i] = g_strdup (l->data); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "create_shares", add_emblem_cb, emblem_data, NULL, G_TYPE_STRING, path, G_TYPE_STRV, users_array, G_TYPE_STRING, name, G_TYPE_STRING, allow_modifications ? "Modify" : "View", G_TYPE_INVALID); g_strfreev (users_array); } } /** * syncdaemon_shares_interface_delete: */ void syncdaemon_shares_interface_delete (SyncdaemonSharesInterface *interface, const gchar *path) { GSList *shares, *l; const gchar *share_id = NULL; g_return_if_fail (SYNCDAEMON_IS_SHARES_INTERFACE (interface)); g_return_if_fail (path != NULL); shares = syncdaemon_shares_interface_get_shared (interface); for (l = shares; l != NULL; l = l->next) { SyncdaemonShareInfo *sinfo = SYNCDAEMON_SHARE_INFO (l->data); if (g_str_equal (path, syncdaemon_share_info_get_path (sinfo))) share_id = syncdaemon_share_info_get_node_id (sinfo); } if (share_id != NULL) { dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "delete_share", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_STRING, share_id, G_TYPE_INVALID); } g_slist_free (shares); } /** * syncdaemon_shares_interface_get_shared: */ GSList * syncdaemon_shares_interface_get_shared (SyncdaemonSharesInterface *interface) { GHashTableIter iter; gchar *path; SyncdaemonShareInfo *share_info; GSList *shared_list, *returned_list = NULL;; GError *error = NULL; g_return_val_if_fail (SYNCDAEMON_IS_SHARES_INTERFACE (interface), NULL); if (interface->priv->shared == NULL) { interface->priv->shared = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); if (dbus_g_proxy_call (DBUS_G_PROXY (interface->priv->proxy), "get_shared", &error, G_TYPE_INVALID, dbus_g_type_get_collection ("GSList", dbus_g_type_get_map ( "GHashTable", G_TYPE_STRING, G_TYPE_STRING)), &shared_list, G_TYPE_INVALID)) { while (shared_list != NULL) { GHashTable *hash = (GHashTable *) shared_list->data; share_info = syncdaemon_share_info_new_from_hash_table (hash); shared_list = g_slist_remove (shared_list, hash); g_hash_table_unref (hash); g_hash_table_insert (interface->priv->shared, g_strdup (syncdaemon_share_info_get_path (share_info)), share_info); } } else { SyncdaemonDaemon *daemon = NULL; g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "error", error->message, NULL); g_error_free (error); return NULL; } } /* Create the list to be returned */ g_hash_table_iter_init (&iter, interface->priv->shared); while (g_hash_table_iter_next (&iter, (gpointer *) &path, (gpointer *) &share_info)) returned_list = g_slist_append (returned_list, share_info); return returned_list; } /** * syncdaemon_shares_interface_get_shares: */ GSList * syncdaemon_shares_interface_get_shares (SyncdaemonSharesInterface *interface) { GHashTableIter iter; gchar *path; SyncdaemonShareInfo *share_info; GSList *shares_list, *returned_list = NULL;; GError *error = NULL; g_return_val_if_fail (SYNCDAEMON_IS_SHARES_INTERFACE (interface), NULL); if (interface->priv->shares == NULL) { interface->priv->shares = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); if (dbus_g_proxy_call (DBUS_G_PROXY (interface->priv->proxy), "get_shares", &error, G_TYPE_INVALID, dbus_g_type_get_collection ("GSList", dbus_g_type_get_map ( "GHashTable", G_TYPE_STRING, G_TYPE_STRING)), &shares_list, G_TYPE_INVALID)) { while (shares_list != NULL) { GHashTable *hash = (GHashTable *) shares_list->data; share_info = syncdaemon_share_info_new_from_hash_table (hash); shares_list = g_slist_remove (shares_list, hash); g_hash_table_unref (hash); g_hash_table_insert (interface->priv->shares, g_strdup (syncdaemon_share_info_get_path (share_info)), share_info); } } else { SyncdaemonDaemon *daemon = NULL; g_object_get (G_OBJECT (interface), "daemon", &daemon, NULL); if (daemon != NULL) g_signal_emit_by_name (daemon, "error", error->message, NULL); g_error_free (error); return NULL; } } /* Create the list to be returned */ g_hash_table_iter_init (&iter, interface->priv->shares); while (g_hash_table_iter_next (&iter, (gpointer) &path, (gpointer) &share_info)) returned_list = g_slist_append (returned_list, share_info); return returned_list; } /** * syncdaemon_shares_interface_refresh: */ void syncdaemon_shares_interface_refresh (SyncdaemonSharesInterface *interface) { g_return_if_fail (SYNCDAEMON_IS_SHARES_INTERFACE (interface)); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "refresh_shares", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_INVALID); } /** * syncdaemon_shares_interface_reject: */ void syncdaemon_shares_interface_reject (SyncdaemonSharesInterface *interface, const gchar *share_id) { g_return_if_fail (SYNCDAEMON_IS_SHARES_INTERFACE (interface)); g_return_if_fail (share_id != NULL); dbus_g_proxy_begin_call (DBUS_G_PROXY (interface->priv->proxy), "reject_share", no_output_dbus_call_ended_cb, interface, NULL, G_TYPE_STRING, share_id, G_TYPE_INVALID); }