summaryrefslogtreecommitdiff
path: root/gnome-2-24/common
diff options
context:
space:
mode:
Diffstat (limited to 'gnome-2-24/common')
-rw-r--r--gnome-2-24/common/Makefile.am23
-rw-r--r--gnome-2-24/common/gdbusutils.c1391
-rw-r--r--gnome-2-24/common/gdbusutils.h100
-rw-r--r--gnome-2-24/common/gmountoperationdbus.c324
-rw-r--r--gnome-2-24/common/gmountoperationdbus.h40
-rw-r--r--gnome-2-24/common/gmountsource.c716
-rw-r--r--gnome-2-24/common/gmountsource.h115
-rw-r--r--gnome-2-24/common/gmountspec.c534
-rw-r--r--gnome-2-24/common/gmountspec.h103
-rw-r--r--gnome-2-24/common/gmounttracker.c621
-rw-r--r--gnome-2-24/common/gmounttracker.h86
-rw-r--r--gnome-2-24/common/gsysutils.c181
-rw-r--r--gnome-2-24/common/gsysutils.h39
-rw-r--r--gnome-2-24/common/gvfsdaemonprotocol.c614
-rw-r--r--gnome-2-24/common/gvfsdaemonprotocol.h186
15 files changed, 5073 insertions, 0 deletions
diff --git a/gnome-2-24/common/Makefile.am b/gnome-2-24/common/Makefile.am
new file mode 100644
index 00000000..2fbb908b
--- /dev/null
+++ b/gnome-2-24/common/Makefile.am
@@ -0,0 +1,23 @@
+NULL =
+
+lib_LTLIBRARIES=libgvfscommon.la
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \
+ -I$(top_srcdir)/daemon \
+ $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \
+ -DDBUS_API_SUBJECT_TO_CHANGE
+
+libgvfscommon_la_SOURCES = \
+ gsysutils.c gsysutils.h \
+ gdbusutils.c gdbusutils.h \
+ gmountspec.c gmountspec.h \
+ gmountoperationdbus.c gmountoperationdbus.h \
+ gmountsource.c gmountsource.h \
+ gmounttracker.c gmounttracker.h \
+ gvfsdaemonprotocol.c gvfsdaemonprotocol.h \
+ $(NULL)
+
+libgvfscommon_la_LIBADD = \
+ $(DBUS_LIBS) \
+ $(GLIB_LIBS)
diff --git a/gnome-2-24/common/gdbusutils.c b/gnome-2-24/common/gdbusutils.c
new file mode 100644
index 00000000..c4282452
--- /dev/null
+++ b/gnome-2-24/common/gdbusutils.c
@@ -0,0 +1,1391 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+#include <gdbusutils.h>
+#include <gio/gio.h>
+
+void
+_g_dbus_oom (void)
+{
+ g_error ("DBus failed with out of memory error");
+}
+
+/* We use _ for escaping, so its not valid */
+#define VALID_INITIAL_NAME_CHARACTER(c) \
+ ( ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z') )
+#define VALID_NAME_CHARACTER(c) \
+ ( ((c) >= '0' && (c) <= '9') || \
+ ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z'))
+
+
+static void
+append_escaped_name (GString *s,
+ const char *unescaped)
+{
+ char c;
+ gboolean first;
+ static const gchar hex[16] = "0123456789ABCDEF";
+
+ while ((c = *unescaped++) != 0)
+ {
+ if (first)
+ {
+ if (VALID_INITIAL_NAME_CHARACTER (c))
+ {
+ g_string_append_c (s, c);
+ continue;
+ }
+ }
+ else
+ {
+ if (VALID_NAME_CHARACTER (c))
+ {
+ g_string_append_c (s, c);
+ continue;
+ }
+ }
+
+ first = FALSE;
+ g_string_append_c (s, '_');
+ g_string_append_c (s, hex[((guchar)c) >> 4]);
+ g_string_append_c (s, hex[((guchar)c) & 0xf]);
+ }
+}
+
+DBusMessage *
+_dbus_message_new_gerror (DBusMessage *message,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...)
+{
+ DBusMessage *reply;
+ va_list args;
+ GError error;
+
+ error.domain = domain;
+ error.code = code;
+ va_start (args, format);
+ error.message = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ reply = _dbus_message_new_from_gerror (message, &error);
+
+ g_free (error.message);
+
+ return reply;
+}
+
+DBusMessage *
+_dbus_message_new_from_gerror (DBusMessage *message,
+ GError *error)
+{
+ DBusMessage *reply;
+ GString *str;
+
+ str = g_string_new ("org.glib.GError.");
+ append_escaped_name (str, g_quark_to_string (error->domain));
+ g_string_append_printf (str, ".c%d", error->code);
+ reply = dbus_message_new_error (message, str->str, error->message);
+ g_string_free (str, TRUE);
+ return reply;
+}
+
+gboolean
+_g_error_from_message (DBusMessage *message,
+ GError **error)
+{
+ DBusError derror;
+
+ dbus_error_init (&derror);
+ if (dbus_set_error_from_message (&derror, message))
+ {
+ _g_error_from_dbus (&derror, error);
+ dbus_error_free (&derror);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+static void
+append_unescaped_dbus_name (GString *s,
+ const char *escaped,
+ const char *end)
+{
+ guchar c;
+
+ while (escaped < end)
+ {
+ c = *escaped++;
+ if (c == '_' &&
+ escaped < end)
+ {
+ c = g_ascii_xdigit_value (*escaped++) << 4;
+
+ if (escaped < end)
+ c |= g_ascii_xdigit_value (*escaped++);
+ }
+ g_string_append_c (s, c);
+ }
+}
+
+char *
+_g_dbus_unescape_bus_name (const char *escaped, const char *end)
+{
+ GString *s = g_string_new ("");
+
+ if (end == NULL)
+ end = escaped + strlen (escaped);
+
+ append_unescaped_dbus_name (s, escaped, end);
+ return g_string_free (s, FALSE);
+}
+
+/* We use _ for escaping */
+#define VALID_INITIAL_BUS_NAME_CHARACTER(c) \
+ ( ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z') || \
+ /*((c) == '_') || */((c) == '-'))
+#define VALID_BUS_NAME_CHARACTER(c) \
+ ( ((c) >= '0' && (c) <= '9') || \
+ ((c) >= 'A' && (c) <= 'Z') || \
+ ((c) >= 'a' && (c) <= 'z') || \
+ /*((c) == '_')||*/ ((c) == '-'))
+
+void
+_g_dbus_append_escaped_bus_name (GString *s,
+ gboolean at_start,
+ const char *unescaped)
+{
+ char c;
+ gboolean first;
+ static const gchar hex[16] = "0123456789ABCDEF";
+
+ while ((c = *unescaped++) != 0)
+ {
+ if (first && at_start)
+ {
+ if (VALID_INITIAL_BUS_NAME_CHARACTER (c))
+ {
+ g_string_append_c (s, c);
+ continue;
+ }
+ }
+ else
+ {
+ if (VALID_BUS_NAME_CHARACTER (c))
+ {
+ g_string_append_c (s, c);
+ continue;
+ }
+ }
+
+ first = FALSE;
+ g_string_append_c (s, '_');
+ g_string_append_c (s, hex[((guchar)c) >> 4]);
+ g_string_append_c (s, hex[((guchar)c) & 0xf]);
+ }
+}
+
+void
+_g_dbus_message_iter_append_cstring (DBusMessageIter *iter, const char *str)
+{
+ DBusMessageIter array;
+
+ if (str == NULL)
+ str = "";
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING,
+ &array))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_fixed_array (&array,
+ DBUS_TYPE_BYTE,
+ &str, strlen (str)))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (iter, &array))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_message_iter_append_args_valist (DBusMessageIter *iter,
+ int first_arg_type,
+ va_list var_args)
+{
+ int type;
+
+ g_return_if_fail (iter != NULL);
+
+ type = first_arg_type;
+
+ while (type != DBUS_TYPE_INVALID)
+ {
+ if (type == G_DBUS_TYPE_CSTRING)
+ {
+ const char **value_p;
+ const char *value;
+
+ value_p = va_arg (var_args, const char**);
+ value = *value_p;
+
+ _g_dbus_message_iter_append_cstring (iter, value);
+ }
+ else if (dbus_type_is_basic (type))
+ {
+ const void *value;
+ value = va_arg (var_args, const void*);
+
+ if (!dbus_message_iter_append_basic (iter,
+ type,
+ value))
+ _g_dbus_oom ();
+ }
+ else if (type == DBUS_TYPE_ARRAY)
+ {
+ int element_type;
+ DBusMessageIter array;
+ char buf[2];
+
+ element_type = va_arg (var_args, int);
+
+ buf[0] = element_type;
+ buf[1] = '\0';
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ buf,
+ &array))
+ _g_dbus_oom ();
+
+ if (dbus_type_is_fixed (element_type))
+ {
+ const void **value;
+ int n_elements;
+
+ value = va_arg (var_args, const void**);
+ n_elements = va_arg (var_args, int);
+
+ if (!dbus_message_iter_append_fixed_array (&array,
+ element_type,
+ value,
+ n_elements))
+ _g_dbus_oom ();
+ }
+ else if (element_type == DBUS_TYPE_STRING ||
+ element_type == DBUS_TYPE_SIGNATURE ||
+ element_type == DBUS_TYPE_OBJECT_PATH)
+ {
+ const char ***value_p;
+ const char **value;
+ int n_elements;
+ int i;
+
+ value_p = va_arg (var_args, const char***);
+ n_elements = va_arg (var_args, int);
+
+ value = *value_p;
+
+ i = 0;
+ while (i < n_elements)
+ {
+ if (!dbus_message_iter_append_basic (&array,
+ element_type,
+ &value[i]))
+ _g_dbus_oom ();
+ ++i;
+ }
+ }
+ else
+ {
+ g_error ("arrays of %d can't be appended with _g_dbus_message_append_args_valist for now\n",
+ element_type);
+ }
+
+ if (!dbus_message_iter_close_container (iter, &array))
+ _g_dbus_oom ();
+ }
+
+ type = va_arg (var_args, int);
+ }
+}
+
+
+void
+_g_dbus_message_append_args_valist (DBusMessage *message,
+ int first_arg_type,
+ va_list var_args)
+{
+ int type;
+ DBusMessageIter iter;
+
+ g_return_if_fail (message != NULL);
+
+ type = first_arg_type;
+
+ dbus_message_iter_init_append (message, &iter);
+
+ _g_dbus_message_iter_append_args_valist (&iter,
+ first_arg_type,
+ var_args);
+}
+
+dbus_bool_t
+_g_dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args)
+{
+ int spec_type, msg_type, i, dbus_spec_type;
+ dbus_bool_t retval;
+
+
+ retval = FALSE;
+
+ spec_type = first_arg_type;
+ i = 0;
+
+ while (spec_type != DBUS_TYPE_INVALID)
+ {
+ msg_type = dbus_message_iter_get_arg_type (iter);
+
+ if (spec_type == G_DBUS_TYPE_CSTRING)
+ dbus_spec_type = DBUS_TYPE_ARRAY;
+ else
+ dbus_spec_type = spec_type;
+
+ if (msg_type != dbus_spec_type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be of type \"%c\", but "
+ "is actually of type \"%c\"\n", i,
+ spec_type,
+ msg_type);
+
+ goto out;
+ }
+
+ if (spec_type == G_DBUS_TYPE_CSTRING)
+ {
+ int element_type;
+ char **ptr;
+ const char *str;
+ int n_elements;
+ DBusMessageIter array;
+
+ element_type = dbus_message_iter_get_element_type (iter);
+ if (DBUS_TYPE_BYTE != element_type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be an array of \"char\", but "
+ "is actually an array of \"%d\"\n",
+ i,
+ element_type);
+ goto out;
+ }
+
+ ptr = va_arg (var_args, char**);
+ g_assert (ptr != NULL);
+
+ dbus_message_iter_recurse (iter, &array);
+ dbus_message_iter_get_fixed_array (&array,
+ &str, &n_elements);
+ *ptr = g_strndup (str, n_elements);
+ }
+ else if (dbus_type_is_basic (spec_type))
+ {
+ void *ptr;
+
+ ptr = va_arg (var_args, void*);
+
+ g_assert (ptr != NULL);
+
+ dbus_message_iter_get_basic (iter, ptr);
+ }
+ else if (spec_type == DBUS_TYPE_ARRAY)
+ {
+ int element_type;
+ int spec_element_type;
+ const void **ptr;
+ int *n_elements_p;
+ DBusMessageIter array;
+
+ spec_element_type = va_arg (var_args, int);
+ element_type = dbus_message_iter_get_element_type (iter);
+
+ if (spec_element_type != element_type)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Argument %d is specified to be an array of \"%d\", but "
+ "is actually an array of \"%d\"\n",
+ i,
+ spec_element_type,
+ element_type);
+
+ goto out;
+ }
+
+ if (dbus_type_is_fixed (spec_element_type))
+ {
+ ptr = va_arg (var_args, const void**);
+ n_elements_p = va_arg (var_args, int*);
+
+ g_assert (ptr != NULL);
+ g_assert (n_elements_p != NULL);
+
+ dbus_message_iter_recurse (iter, &array);
+
+ dbus_message_iter_get_fixed_array (&array,
+ ptr, n_elements_p);
+ }
+ else if (spec_element_type == DBUS_TYPE_STRING ||
+ spec_element_type == DBUS_TYPE_SIGNATURE ||
+ spec_element_type == DBUS_TYPE_OBJECT_PATH)
+ {
+ char ***str_array_p;
+ int n_elements;
+ char **str_array;
+
+ str_array_p = va_arg (var_args, char***);
+ n_elements_p = va_arg (var_args, int*);
+
+ g_assert (str_array_p != NULL);
+ g_assert (n_elements_p != NULL);
+
+ /* Count elements in the array */
+ dbus_message_iter_recurse (iter, &array);
+
+ n_elements = 0;
+ while (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_INVALID)
+ {
+ ++n_elements;
+ dbus_message_iter_next (&array);
+ }
+
+ str_array = g_new0 (char*, n_elements + 1);
+ if (str_array == NULL)
+ {
+ _g_dbus_oom ();
+ goto out;
+ }
+
+ /* Now go through and dup each string */
+ dbus_message_iter_recurse (iter, &array);
+
+ i = 0;
+ while (i < n_elements)
+ {
+ const char *s;
+ dbus_message_iter_get_basic (&array, &s);
+
+ str_array[i] = g_strdup (s);
+ if (str_array[i] == NULL)
+ {
+ g_strfreev (str_array);
+ _g_dbus_oom ();
+ goto out;
+ }
+
+ ++i;
+
+ if (!dbus_message_iter_next (&array))
+ g_assert (i == n_elements);
+ }
+
+ g_assert (dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_INVALID);
+ g_assert (i == n_elements);
+ g_assert (str_array[i] == NULL);
+
+ *str_array_p = str_array;
+ *n_elements_p = n_elements;
+ }
+ }
+
+ spec_type = va_arg (var_args, int);
+ if (!dbus_message_iter_next (iter) && spec_type != DBUS_TYPE_INVALID)
+ {
+ dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
+ "Message has only %d arguments, but more were expected", i);
+ goto out;
+ }
+
+ i++;
+ }
+
+ retval = TRUE;
+
+ out:
+ return retval;
+}
+
+dbus_bool_t
+_g_dbus_message_iter_get_args (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ ...)
+{
+ va_list var_args;
+ dbus_bool_t res;
+
+ va_start (var_args, first_arg_type);
+ res = _g_dbus_message_iter_get_args_valist (iter, error,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+ return res;
+}
+
+/* Same as the dbus one, except doesn't give OOM and handles
+ G_DBUS_TYPE_CSTRING
+*/
+void
+_g_dbus_message_append_args (DBusMessage *message,
+ int first_arg_type,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (message != NULL);
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_append_args_valist (message,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+}
+
+void
+_g_dbus_message_iter_append_args (DBusMessageIter *iter,
+ int first_arg_type,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (iter != NULL);
+
+ va_start (var_args, first_arg_type);
+ _g_dbus_message_iter_append_args_valist (iter,
+ first_arg_type,
+ var_args);
+ va_end (var_args);
+}
+
+void
+_g_error_from_dbus (DBusError *derror,
+ GError **error)
+{
+ const char *name, *end;
+ GString *str;
+ GQuark domain;
+ int code;
+
+ if (g_str_has_prefix (derror->name, "org.glib.GError."))
+ {
+ domain = 0;
+ code = 0;
+
+ name = derror->name + strlen ("org.glib.GError.");
+ end = strchr (name, '.');
+ if (end)
+ {
+ str = g_string_new (NULL);
+ append_unescaped_dbus_name (str, name, end);
+ domain = g_quark_from_string (str->str);
+ g_string_free (str, TRUE);
+
+ end++; /* skip . */
+ if (*end++ == 'c')
+ code = atoi (end);
+ }
+
+ g_set_error_literal (error, domain, code, derror->message);
+ }
+ /* TODO: Special case other types, like DBUS_ERROR_NO_MEMORY etc? */
+ else
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "DBus error %s: %s", derror->name, derror->message);
+}
+
+GList *
+_g_dbus_bus_list_names_with_prefix (DBusConnection *connection,
+ const char *prefix,
+ DBusError *error)
+{
+ DBusMessage *message, *reply;
+ DBusMessageIter iter, array;
+ GList *names;
+
+ g_return_val_if_fail (connection != NULL, NULL);
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ "ListNames");
+ if (message == NULL)
+ return NULL;
+
+ reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ return NULL;
+
+ names = NULL;
+
+ if (!dbus_message_iter_init (reply, &iter) ||
+ (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) ||
+ (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING))
+ goto out;
+
+ for (dbus_message_iter_recurse (&iter, &array);
+ dbus_message_iter_get_arg_type (&array) == DBUS_TYPE_STRING;
+ dbus_message_iter_next (&array))
+ {
+ char *name;
+ dbus_message_iter_get_basic (&array, &name);
+ if (g_str_has_prefix (name, prefix))
+ names = g_list_prepend (names, g_strdup (name));
+ }
+
+ names = g_list_reverse (names);
+
+ out:
+ dbus_message_unref (reply);
+ return names;
+}
+
+/*************************************************************************
+ * Helper fd source *
+ ************************************************************************/
+
+typedef struct
+{
+ GSource source;
+ GPollFD pollfd;
+ GCancellable *cancellable;
+ gulong cancelled_tag;
+} FDSource;
+
+static gboolean
+fd_source_prepare (GSource *source,
+ gint *timeout)
+{
+ FDSource *fd_source = (FDSource *)source;
+ *timeout = -1;
+
+ return g_cancellable_is_cancelled (fd_source->cancellable);
+}
+
+static gboolean
+fd_source_check (GSource *source)
+{
+ FDSource *fd_source = (FDSource *)source;
+
+ return
+ g_cancellable_is_cancelled (fd_source->cancellable) ||
+ fd_source->pollfd.revents != 0;
+}
+
+static gboolean
+fd_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+
+{
+ GFDSourceFunc func = (GFDSourceFunc)callback;
+ FDSource *fd_source = (FDSource *)source;
+
+ g_assert (func != NULL);
+
+ return (*func) (user_data, fd_source->pollfd.revents, fd_source->pollfd.fd);
+}
+
+static void
+fd_source_finalize (GSource *source)
+{
+ FDSource *fd_source = (FDSource *)source;
+
+ if (fd_source->cancelled_tag)
+ g_signal_handler_disconnect (fd_source->cancellable,
+ fd_source->cancelled_tag);
+
+ if (fd_source->cancellable)
+ g_object_unref (fd_source->cancellable);
+}
+
+static GSourceFuncs fd_source_funcs = {
+ fd_source_prepare,
+ fd_source_check,
+ fd_source_dispatch,
+ fd_source_finalize
+};
+
+/* Might be called on another thread */
+static void
+fd_source_cancelled_cb (GCancellable *cancellable,
+ gpointer data)
+{
+ /* Wake up the mainloop in case we're waiting on async calls with FDSource */
+ g_main_context_wakeup (NULL);
+}
+
+/* Two __ to avoid conflict with gio version */
+GSource *
+__g_fd_source_new (int fd,
+ gushort events,
+ GCancellable *cancellable)
+{
+ GSource *source;
+ FDSource *fd_source;
+
+ source = g_source_new (&fd_source_funcs, sizeof (FDSource));
+ fd_source = (FDSource *)source;
+
+ if (cancellable)
+ fd_source->cancellable = g_object_ref (cancellable);
+
+ fd_source->pollfd.fd = fd;
+ fd_source->pollfd.events = events;
+ g_source_add_poll (source, &fd_source->pollfd);
+
+ if (cancellable)
+ fd_source->cancelled_tag =
+ g_signal_connect_data (cancellable, "cancelled",
+ (GCallback)fd_source_cancelled_cb,
+ NULL, NULL,
+ 0);
+
+ return source;
+}
+
+
+/*************************************************************************
+ * *
+ * dbus mainloop integration for async ops *
+ * *
+ *************************************************************************/
+
+static gint32 main_integration_data_slot = -1;
+static GOnce once_init_main_integration = G_ONCE_INIT;
+
+/**
+ * A GSource subclass for dispatching DBusConnection messages.
+ * We need this on top of the IO handlers, because sometimes
+ * there are messages to dispatch queued up but no IO pending.
+ *
+ * The source is owned by the connection (and the main context
+ * while that is alive)
+ */
+typedef struct
+{
+ GSource source;
+
+ DBusConnection *connection;
+ GSList *ios;
+ GSList *timeouts;
+} DBusSource;
+
+typedef struct
+{
+ DBusSource *dbus_source;
+ GSource *source;
+ DBusWatch *watch;
+} IOHandler;
+
+typedef struct
+{
+ DBusSource *dbus_source;
+ GSource *source;
+ DBusTimeout *timeout;
+} TimeoutHandler;
+
+static gpointer
+main_integration_init (gpointer arg)
+{
+ if (!dbus_connection_allocate_data_slot (&main_integration_data_slot))
+ g_error ("Unable to allocate data slot");
+
+ return NULL;
+}
+
+static gboolean
+dbus_source_prepare (GSource *source,
+ gint *timeout)
+{
+ DBusConnection *connection = ((DBusSource *)source)->connection;
+
+ *timeout = -1;
+
+ return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+static gboolean
+dbus_source_check (GSource *source)
+{
+ return FALSE;
+}
+
+static gboolean
+dbus_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ DBusConnection *connection = ((DBusSource *)source)->connection;
+
+ dbus_connection_ref (connection);
+
+ /* Only dispatch once - we don't want to starve other GSource */
+ dbus_connection_dispatch (connection);
+
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+static gboolean
+io_handler_dispatch (gpointer data,
+ GIOCondition condition,
+ int fd)
+{
+ IOHandler *handler = data;
+ guint dbus_condition = 0;
+ DBusConnection *connection;
+
+ connection = handler->dbus_source->connection;
+
+ if (connection)
+ dbus_connection_ref (connection);
+
+ if (condition & G_IO_IN)
+ dbus_condition |= DBUS_WATCH_READABLE;
+ if (condition & G_IO_OUT)
+ dbus_condition |= DBUS_WATCH_WRITABLE;
+ if (condition & G_IO_ERR)
+ dbus_condition |= DBUS_WATCH_ERROR;
+ if (condition & G_IO_HUP)
+ dbus_condition |= DBUS_WATCH_HANGUP;
+
+ /* Note that we don't touch the handler after this, because
+ * dbus may have disabled the watch and thus killed the
+ * handler.
+ */
+ dbus_watch_handle (handler->watch, dbus_condition);
+ handler = NULL;
+
+ if (connection)
+ dbus_connection_unref (connection);
+
+ return TRUE;
+}
+
+static void
+io_handler_free (IOHandler *handler)
+{
+ DBusSource *dbus_source;
+
+ dbus_source = handler->dbus_source;
+ dbus_source->ios = g_slist_remove (dbus_source->ios, handler);
+
+ g_source_destroy (handler->source);
+ g_source_unref (handler->source);
+ g_free (handler);
+}
+
+static void
+dbus_source_add_watch (DBusSource *dbus_source,
+ DBusWatch *watch)
+{
+ guint flags;
+ GIOCondition condition;
+ IOHandler *handler;
+ int fd;
+
+ if (!dbus_watch_get_enabled (watch))
+ return;
+
+ g_assert (dbus_watch_get_data (watch) == NULL);
+
+ flags = dbus_watch_get_flags (watch);
+
+ condition = G_IO_ERR | G_IO_HUP;
+ if (flags & DBUS_WATCH_READABLE)
+ condition |= G_IO_IN;
+ if (flags & DBUS_WATCH_WRITABLE)
+ condition |= G_IO_OUT;
+
+ handler = g_new0 (IOHandler, 1);
+ handler->dbus_source = dbus_source;
+ handler->watch = watch;
+
+#if (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION == 1 && DBUS_MICRO_VERSION >= 1) || (DBUS_MAJOR_VERSION == 1 && DBUS_MINOR_VERSION > 1) || (DBUS_MAJOR_VERSION > 1)
+ fd = dbus_watch_get_unix_fd (watch);
+#else
+ fd = dbus_watch_get_fd (watch);
+#endif
+
+ handler->source = __g_fd_source_new (fd, condition, NULL);
+ g_source_set_callback (handler->source,
+ (GSourceFunc) io_handler_dispatch, handler,
+ NULL);
+ g_source_attach (handler->source, NULL);
+
+ dbus_source->ios = g_slist_prepend (dbus_source->ios, handler);
+ dbus_watch_set_data (watch, handler,
+ (DBusFreeFunction)io_handler_free);
+}
+
+static void
+dbus_source_remove_watch (DBusSource *dbus_source,
+ DBusWatch *watch)
+{
+ dbus_watch_set_data (watch, NULL, NULL);
+}
+
+static void
+timeout_handler_free (TimeoutHandler *handler)
+{
+ DBusSource *dbus_source;
+
+ dbus_source = handler->dbus_source;
+ dbus_source->timeouts = g_slist_remove (dbus_source->timeouts, handler);
+
+ g_source_destroy (handler->source);
+ g_source_unref (handler->source);
+ g_free (handler);
+}
+
+static gboolean
+timeout_handler_dispatch (gpointer data)
+{
+ TimeoutHandler *handler = data;
+
+ dbus_timeout_handle (handler->timeout);
+
+ return TRUE;
+}
+
+static void
+dbus_source_add_timeout (DBusSource *dbus_source,
+ DBusTimeout *timeout)
+{
+ TimeoutHandler *handler;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return;
+
+ g_assert (dbus_timeout_get_data (timeout) == NULL);
+
+ handler = g_new0 (TimeoutHandler, 1);
+ handler->dbus_source = dbus_source;
+ handler->timeout = timeout;
+
+ handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
+ g_source_set_callback (handler->source,
+ timeout_handler_dispatch, handler,
+ NULL);
+ g_source_attach (handler->source, NULL);
+
+ /* handler->source is owned by the context here */
+ dbus_source->timeouts = g_slist_prepend (dbus_source->timeouts, handler);
+
+ dbus_timeout_set_data (timeout, handler,
+ (DBusFreeFunction)timeout_handler_free);
+}
+
+static void
+dbus_source_remove_timeout (DBusSource *source,
+ DBusTimeout *timeout)
+{
+ dbus_timeout_set_data (timeout, NULL, NULL);
+}
+
+static dbus_bool_t
+add_watch (DBusWatch *watch,
+ gpointer data)
+{
+ DBusSource *dbus_source = data;
+
+ dbus_source_add_watch (dbus_source, watch);
+
+ return TRUE;
+}
+
+static void
+remove_watch (DBusWatch *watch,
+ gpointer data)
+{
+ DBusSource *dbus_source = data;
+
+ dbus_source_remove_watch (dbus_source, watch);
+}
+
+static void
+watch_toggled (DBusWatch *watch,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove */
+ if (dbus_watch_get_enabled (watch))
+ add_watch (watch, data);
+ else
+ remove_watch (watch, data);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ DBusSource *source = data;
+
+ if (!dbus_timeout_get_enabled (timeout))
+ return TRUE;
+
+ dbus_source_add_timeout (source, timeout);
+
+ return TRUE;
+}
+
+static void
+remove_timeout (DBusTimeout *timeout,
+ void *data)
+{
+ DBusSource *source = data;
+
+ dbus_source_remove_timeout (source, timeout);
+}
+
+static void
+timeout_toggled (DBusTimeout *timeout,
+ void *data)
+{
+ /* Because we just exit on OOM, enable/disable is
+ * no different from add/remove
+ */
+ if (dbus_timeout_get_enabled (timeout))
+ add_timeout (timeout, data);
+ else
+ remove_timeout (timeout, data);
+}
+
+static void
+wakeup_main (void *data)
+{
+ g_main_context_wakeup (NULL);
+}
+
+static const GSourceFuncs dbus_source_funcs = {
+ dbus_source_prepare,
+ dbus_source_check,
+ dbus_source_dispatch
+};
+
+/* Called when the connection dies or when we're unintegrating from mainloop */
+static void
+dbus_source_free (DBusSource *dbus_source)
+{
+ while (dbus_source->ios)
+ {
+ IOHandler *handler = dbus_source->ios->data;
+
+ dbus_watch_set_data (handler->watch, NULL, NULL);
+ }
+
+ while (dbus_source->timeouts)
+ {
+ TimeoutHandler *handler = dbus_source->timeouts->data;
+
+ dbus_timeout_set_data (handler->timeout, NULL, NULL);
+ }
+
+ /* Remove from mainloop */
+ g_source_destroy ((GSource *)dbus_source);
+
+ g_source_unref ((GSource *)dbus_source);
+}
+
+void
+_g_dbus_connection_integrate_with_main (DBusConnection *connection)
+{
+ DBusSource *dbus_source;
+
+ g_once (&once_init_main_integration, main_integration_init, NULL);
+
+ g_assert (connection != NULL);
+
+ _g_dbus_connection_remove_from_main (connection);
+
+ dbus_source = (DBusSource *)
+ g_source_new ((GSourceFuncs*)&dbus_source_funcs,
+ sizeof (DBusSource));
+
+ dbus_source->connection = connection;
+
+ if (!dbus_connection_set_watch_functions (connection,
+ add_watch,
+ remove_watch,
+ watch_toggled,
+ dbus_source, NULL))
+ _g_dbus_oom ();
+
+ if (!dbus_connection_set_timeout_functions (connection,
+ add_timeout,
+ remove_timeout,
+ timeout_toggled,
+ dbus_source, NULL))
+ _g_dbus_oom ();
+
+ dbus_connection_set_wakeup_main_function (connection,
+ wakeup_main,
+ dbus_source, NULL);
+
+ /* Owned by both connection and mainloop (until destroy) */
+ g_source_attach ((GSource *)dbus_source, NULL);
+
+ if (!dbus_connection_set_data (connection,
+ main_integration_data_slot,
+ dbus_source, (DBusFreeFunction)dbus_source_free))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_connection_remove_from_main (DBusConnection *connection)
+{
+ g_once (&once_init_main_integration, main_integration_init, NULL);
+
+ if (!dbus_connection_set_data (connection,
+ main_integration_data_slot,
+ NULL, NULL))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_message_iter_copy (DBusMessageIter *dest,
+ DBusMessageIter *source)
+{
+ int type, element_type;
+
+ while (dbus_message_iter_get_arg_type (source) != DBUS_TYPE_INVALID)
+ {
+ type = dbus_message_iter_get_arg_type (source);
+
+ if (dbus_type_is_basic (type))
+ {
+ dbus_uint64_t value;
+ dbus_message_iter_get_basic (source, &value);
+ dbus_message_iter_append_basic (dest, type, &value);
+ }
+ else if (type == DBUS_TYPE_ARRAY)
+ {
+ DBusMessageIter source_array, dest_array;
+ void *value;
+ int n_elements;
+ char buf[2];
+
+ element_type = dbus_message_iter_get_element_type (source);
+ if (dbus_type_is_fixed (element_type))
+ {
+ buf[0] = element_type;
+ buf[1] = '\0';
+
+ dbus_message_iter_recurse (source, &source_array);
+ dbus_message_iter_get_fixed_array (&source_array, &value, &n_elements);
+
+ if (!dbus_message_iter_open_container (dest, DBUS_TYPE_ARRAY,
+ buf, &dest_array))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_fixed_array (&dest_array,
+ element_type,
+ &value, n_elements))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (dest, &dest_array))
+ _g_dbus_oom ();
+ }
+ else
+ g_error ("Unsupported array type %c in _g_dbus_message_iter_copy", element_type);
+ }
+ else
+ g_error ("Unsupported type %c in _g_dbus_message_iter_copy", type);
+
+ dbus_message_iter_next (source);
+ }
+
+}
+
+typedef struct {
+ GAsyncDBusCallback callback;
+ gpointer user_data;
+ GError *io_error;
+
+
+ /* protected by async_call lock: */
+ gboolean ran; /* the pending_call reply handler ran */
+ gboolean idle; /* we queued an idle */
+
+ /* only used for idle */
+ DBusPendingCall *pending;
+} AsyncDBusCallData;
+
+/* Lock to protect the data for working around racecondition
+ between send_with_reply and pending_set_notify */
+G_LOCK_DEFINE_STATIC(async_call);
+
+static void
+handle_async_reply (DBusPendingCall *pending,
+ AsyncDBusCallData *data)
+{
+ DBusMessage *reply;
+ GError *error;
+
+ reply = dbus_pending_call_steal_reply (pending);
+
+ error = NULL;
+ if (_g_error_from_message (reply, &error))
+ {
+ if (data->callback)
+ data->callback (NULL, error, data->user_data);
+ g_error_free (error);
+ }
+ else
+ {
+ if (data->callback)
+ data->callback (reply, NULL, data->user_data);
+ }
+
+ dbus_message_unref (reply);
+}
+
+static void
+async_call_reply (DBusPendingCall *pending,
+ void *_data)
+{
+ AsyncDBusCallData *data = _data;
+
+ G_LOCK (async_call);
+ if (data->idle)
+ return;
+ data->ran = TRUE;
+ G_UNLOCK (async_call);
+
+ handle_async_reply (pending, data);
+}
+
+static gboolean
+idle_async_callback (void *_data)
+{
+ AsyncDBusCallData *data = _data;
+ handle_async_reply (data->pending, data);
+ dbus_pending_call_unref (data->pending);
+ return FALSE;
+}
+
+static gboolean
+async_call_error_at_idle (gpointer _data)
+{
+ AsyncDBusCallData *data = _data;
+
+ if (data->callback)
+ data->callback (NULL, data->io_error, data->user_data);
+
+ g_error_free (data->io_error);
+ g_free (data);
+
+ return FALSE;
+}
+
+void
+_g_dbus_connection_call_async (DBusConnection *connection,
+ DBusMessage *message,
+ int timeout_msecs,
+ GAsyncDBusCallback callback,
+ gpointer user_data)
+{
+ AsyncDBusCallData *data;
+ DBusPendingCall *pending_call;
+ DBusError derror;
+
+ data = g_new0 (AsyncDBusCallData, 1);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ if (connection == NULL)
+ {
+ dbus_error_init (&derror);
+ connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
+ if (connection == NULL)
+ {
+ g_set_error_literal (&data->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Can't open dbus connection");
+ g_idle_add (async_call_error_at_idle, data);
+ dbus_error_free (&derror);
+ return;
+ }
+ }
+
+ if (!dbus_connection_send_with_reply (connection, message, &pending_call, timeout_msecs))
+ _g_dbus_oom ();
+
+ if (pending_call == NULL)
+ {
+ g_set_error (&data->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error while getting peer-to-peer dbus connection: %s",
+ "Connection is closed");
+ g_idle_add (async_call_error_at_idle, data);
+ return;
+ }
+
+ if (!dbus_pending_call_set_notify (pending_call,
+ async_call_reply,
+ data, g_free))
+ _g_dbus_oom ();
+
+
+ /* All this is required to work around a race condition between
+ * send_with_reply and pending_call_set_notify :/
+ */
+ G_LOCK (async_call);
+
+ if (dbus_pending_call_get_completed (pending_call) &&
+ !data->ran)
+ {
+ data->idle = TRUE;
+ data->pending = dbus_pending_call_ref (pending_call);
+ g_idle_add (idle_async_callback, data);
+ }
+
+ G_UNLOCK (async_call);
+
+
+ dbus_pending_call_unref (pending_call);
+}
diff --git a/gnome-2-24/common/gdbusutils.h b/gnome-2-24/common/gdbusutils.h
new file mode 100644
index 00000000..00ef566d
--- /dev/null
+++ b/gnome-2-24/common/gdbusutils.h
@@ -0,0 +1,100 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_DBUS_UTILS_H__
+#define __G_DBUS_UTILS_H__
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+typedef gboolean (*GFDSourceFunc) (gpointer data,
+ GIOCondition condition,
+ int fd);
+typedef void (*GAsyncDBusCallback) (DBusMessage *reply,
+ GError *error,
+ gpointer user_data);
+
+/* Only used internally, never on wire */
+#define G_DBUS_TYPE_CSTRING 1024
+
+GList * _g_dbus_bus_list_names_with_prefix (DBusConnection *connection,
+ const char *prefix,
+ DBusError *error);
+void _g_dbus_message_iter_append_cstring (DBusMessageIter *iter,
+ const char *str);
+void _g_dbus_message_iter_append_args_valist (DBusMessageIter *iter,
+ int first_arg_type,
+ va_list var_args);
+void _g_dbus_message_iter_append_args (DBusMessageIter *iter,
+ int first_arg_type,
+ ...);
+void _g_dbus_message_append_args_valist (DBusMessage *message,
+ int first_arg_type,
+ va_list var_args);
+void _g_dbus_message_append_args (DBusMessage *message,
+ int first_arg_type,
+ ...);
+dbus_bool_t _g_dbus_message_iter_get_args_valist (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ va_list var_args);
+dbus_bool_t _g_dbus_message_iter_get_args (DBusMessageIter *iter,
+ DBusError *error,
+ int first_arg_type,
+ ...);
+void _g_error_from_dbus (DBusError *derror,
+ GError **error);
+gboolean _g_error_from_message (DBusMessage *message,
+ GError **error);
+DBusMessage *_dbus_message_new_from_gerror (DBusMessage *message,
+ GError *error);
+DBusMessage *_dbus_message_new_gerror (DBusMessage *message,
+ GQuark domain,
+ gint code,
+ const gchar *format,
+ ...);
+char * _g_dbus_unescape_bus_name (const char *escaped,
+ const char *end);
+void _g_dbus_append_escaped_bus_name (GString *string,
+ gboolean at_start,
+ const char *unescaped);
+void _g_dbus_connection_integrate_with_main (DBusConnection *connection);
+void _g_dbus_connection_remove_from_main (DBusConnection *connection);
+GSource * __g_fd_source_new (int fd,
+ gushort events,
+ GCancellable *cancellable);
+void _g_dbus_message_iter_copy (DBusMessageIter *dest,
+ DBusMessageIter *source);
+void _g_dbus_oom (void) G_GNUC_NORETURN;
+void _g_dbus_connection_call_async (DBusConnection *connection,
+ DBusMessage *message,
+ int timeout_msecs,
+ GAsyncDBusCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+
+#endif /* __G_DBUS_UTILS_H__ */
diff --git a/gnome-2-24/common/gmountoperationdbus.c b/gnome-2-24/common/gmountoperationdbus.c
new file mode 100644
index 00000000..1027b3a9
--- /dev/null
+++ b/gnome-2-24/common/gmountoperationdbus.c
@@ -0,0 +1,324 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <dbus/dbus.h>
+
+#define I_(string) g_intern_static_string (string)
+
+#include <gio/gio.h>
+#include "gmountoperationdbus.h"
+#include "gvfsdaemonprotocol.h"
+#include "gdbusutils.h"
+#include <glib/gi18n-lib.h>
+
+typedef struct
+{
+ GMountOperation *op;
+ char *obj_path;
+ char *dbus_id;
+ DBusConnection *connection;
+} GMountOperationDBus;
+
+static DBusHandlerResult mount_op_message_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+static void mount_op_unregister_function (DBusConnection *connection,
+ void *user_data);
+static void mount_op_ask_password (GMountOperationDBus *op_dbus,
+ DBusMessage *message);
+static void mount_op_ask_question (GMountOperationDBus *op_dbus,
+ DBusMessage *message);
+
+static void
+g_mount_operation_dbus_free (GMountOperationDBus *op_dbus)
+{
+ if (op_dbus->connection)
+ {
+ dbus_connection_unregister_object_path (op_dbus->connection,
+ op_dbus->obj_path);
+ dbus_connection_unref (op_dbus->connection);
+ }
+ g_free (op_dbus->dbus_id);
+ g_free (op_dbus->obj_path);
+ g_free (op_dbus);
+}
+
+GMountSource *
+g_mount_operation_dbus_wrap (GMountOperation *op,
+ DBusConnection *connection)
+{
+ GMountOperationDBus *op_dbus;
+ static int mount_id = 0;
+ DBusObjectPathVTable mount_vtable = {
+ mount_op_unregister_function,
+ mount_op_message_function
+ };
+
+ if (op == NULL)
+ return g_mount_source_new_dummy ();
+
+ op_dbus = g_new0 (GMountOperationDBus, 1);
+
+ op_dbus->op = op;
+ op_dbus->connection = dbus_connection_ref (connection);
+ op_dbus->obj_path = g_strdup_printf ("/org/gtk/gvfs/mountop/%d", mount_id++);
+ if (op_dbus->connection)
+ {
+ op_dbus->dbus_id = g_strdup (dbus_bus_get_unique_name (op_dbus->connection));
+ if (!dbus_connection_register_object_path (op_dbus->connection,
+ op_dbus->obj_path,
+ &mount_vtable,
+ op_dbus))
+ _g_dbus_oom ();
+ }
+
+ g_object_set_data_full (G_OBJECT (op), "dbus-op",
+ op_dbus, (GDestroyNotify)g_mount_operation_dbus_free);
+
+ return g_mount_source_new (op_dbus->dbus_id, op_dbus->obj_path);
+}
+
+/**
+ * Called when a #DBusObjectPathVTable is unregistered (or its connection is freed).
+ * Found in #DBusObjectPathVTable.
+ */
+static void
+mount_op_unregister_function (DBusConnection *connection,
+ void *user_data)
+{
+}
+
+/**
+ * Called when a message is sent to a registered object path. Found in
+ * #DBusObjectPathVTable which is registered with dbus_connection_register_object_path()
+ * or dbus_connection_register_fallback().
+ */
+static DBusHandlerResult
+mount_op_message_function (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GMountOperationDBus *op_dbus = user_data;
+
+ if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD))
+ mount_op_ask_password (op_dbus, message);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION))
+ mount_op_ask_question (op_dbus, message);
+ else
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+mount_op_send_reply (GMountOperationDBus *op_dbus,
+ DBusMessage *reply)
+{
+ if (!dbus_connection_send (op_dbus->connection, reply, NULL))
+ _g_dbus_oom ();
+
+ g_signal_handlers_disconnect_matched (op_dbus->op,
+ G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA,
+ g_signal_lookup ("reply", G_TYPE_MOUNT_OPERATION),
+ 0,
+ NULL,
+ NULL,
+ reply);
+ dbus_message_unref (reply);
+}
+
+static void
+ask_password_reply (GMountOperation *op,
+ GMountOperationResult result,
+ gpointer data)
+{
+ DBusMessage *reply = data;
+ const char *username, *password, *domain;
+ dbus_bool_t anonymous;
+ guint32 password_save;
+ dbus_bool_t handled, abort_dbus;
+ GMountOperationDBus *op_dbus;
+
+ op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op");
+
+ handled = (result != G_MOUNT_OPERATION_UNHANDLED);
+ abort_dbus = (result == G_MOUNT_OPERATION_ABORTED);
+
+ password = g_mount_operation_get_password (op);
+ if (password == NULL)
+ password = "";
+ username = g_mount_operation_get_username (op);
+ if (username == NULL)
+ username = "";
+ domain = g_mount_operation_get_domain (op);
+ if (domain == NULL)
+ domain = "";
+ anonymous = g_mount_operation_get_anonymous (op);
+ password_save = g_mount_operation_get_password_save (op);
+
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &abort_dbus,
+ DBUS_TYPE_STRING, &password,
+ DBUS_TYPE_STRING, &username,
+ DBUS_TYPE_STRING, &domain,
+ DBUS_TYPE_BOOLEAN, &anonymous,
+ DBUS_TYPE_UINT32, &password_save,
+ 0);
+
+ mount_op_send_reply (op_dbus, reply);
+}
+
+static void
+mount_op_ask_password (GMountOperationDBus *op_dbus,
+ DBusMessage *message)
+{
+ const char *message_string, *default_user, *default_domain;
+ guint32 flags;
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ DBusError error;
+
+ reply = NULL;
+
+ dbus_message_iter_init (message, &iter);
+
+ dbus_error_init (&error);
+ if (!_g_dbus_message_iter_get_args (&iter,
+ &error,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_STRING, &default_user,
+ DBUS_TYPE_STRING, &default_domain,
+ DBUS_TYPE_UINT32, &flags,
+ 0))
+ {
+ reply = dbus_message_new_error (message, error.name, error.message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+ if (!dbus_connection_send (op_dbus->connection, reply, NULL))
+ _g_dbus_oom ();
+ dbus_message_unref (reply);
+ dbus_error_free (&error);
+ return;
+ }
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ g_signal_connect (op_dbus->op, "reply", (GCallback)ask_password_reply, reply);
+
+ g_signal_emit_by_name (op_dbus->op, "ask_password",
+ message_string,
+ default_user,
+ default_domain,
+ flags);
+}
+
+static void
+ask_question_reply (GMountOperation *op,
+ GMountOperationResult result,
+ gpointer data)
+{
+ DBusMessage *reply = data;
+ guint32 choice;
+ dbus_bool_t handled, abort_dbus;
+ GMountOperationDBus *op_dbus;
+
+ op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op");
+
+ handled = (result != G_MOUNT_OPERATION_UNHANDLED);
+ abort_dbus = (result == G_MOUNT_OPERATION_ABORTED);
+
+ choice = g_mount_operation_get_choice (op);
+
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &abort_dbus,
+ DBUS_TYPE_UINT32, &choice,
+ 0);
+
+ mount_op_send_reply (op_dbus, reply);
+}
+
+static void
+mount_op_ask_question (GMountOperationDBus *op_dbus,
+ DBusMessage *message)
+{
+ const char *message_string;
+ char **choices;
+ int num_choices;
+ dbus_bool_t handled = FALSE;
+ DBusMessage *reply;
+ DBusError error;
+ gboolean res;
+ DBusMessageIter iter;
+
+ reply = NULL;
+
+ dbus_message_iter_init (message, &iter);
+ dbus_error_init (&error);
+ if (!_g_dbus_message_iter_get_args (&iter,
+ &error,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ &choices, &num_choices,
+ 0))
+ {
+ reply = dbus_message_new_error (message, error.name, error.message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+ if (!dbus_connection_send (op_dbus->connection, reply, NULL))
+ _g_dbus_oom ();
+ dbus_message_unref (reply);
+ dbus_error_free (&error);
+ return;
+ }
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ _g_dbus_oom ();
+
+ g_signal_connect (op_dbus->op, "reply", (GCallback)ask_question_reply, reply);
+
+ g_signal_emit_by_name (op_dbus->op, "ask_question",
+ message_string,
+ choices,
+ &res);
+ if (!res)
+ {
+ _g_dbus_message_append_args (reply,
+ DBUS_TYPE_BOOLEAN, &handled,
+ 0);
+ mount_op_send_reply (op_dbus, reply);
+ }
+
+ dbus_free_string_array (choices);
+}
diff --git a/gnome-2-24/common/gmountoperationdbus.h b/gnome-2-24/common/gmountoperationdbus.h
new file mode 100644
index 00000000..26ee4013
--- /dev/null
+++ b/gnome-2-24/common/gmountoperationdbus.h
@@ -0,0 +1,40 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_OPERATION_DBUS_H__
+#define __G_MOUNT_OPERATION_DBUS_H__
+
+#include <sys/stat.h>
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <gmountspec.h>
+#include <gmountsource.h>
+
+G_BEGIN_DECLS
+
+GMountSource *g_mount_operation_dbus_wrap (GMountOperation *op,
+ DBusConnection *connection);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_OPERATION_DBUS_H__ */
diff --git a/gnome-2-24/common/gmountsource.c b/gnome-2-24/common/gmountsource.c
new file mode 100644
index 00000000..e801d647
--- /dev/null
+++ b/gnome-2-24/common/gmountsource.c
@@ -0,0 +1,716 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <gmountsource.h>
+#include <gdbusutils.h>
+#include <gio/gio.h>
+#include <gvfsdaemonprotocol.h>
+
+struct _GMountSource
+{
+ GObject parent_instance;
+
+ char *dbus_id;
+ char *obj_path;
+};
+
+G_DEFINE_TYPE (GMountSource, g_mount_source, G_TYPE_OBJECT)
+
+static void
+g_mount_source_finalize (GObject *object)
+{
+ GMountSource *source;
+
+ source = G_MOUNT_SOURCE (object);
+
+ g_free (source->dbus_id);
+ g_free (source->obj_path);
+
+ if (G_OBJECT_CLASS (g_mount_source_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_mount_source_parent_class)->finalize) (object);
+}
+
+static void
+g_mount_source_class_init (GMountSourceClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_mount_source_finalize;
+}
+
+static void
+g_mount_source_init (GMountSource *mount_source)
+{
+}
+
+GMountSource *
+g_mount_source_new (const char *dbus_id,
+ const char *obj_path)
+{
+ GMountSource *source;
+
+ source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL);
+
+ source->dbus_id = g_strdup (dbus_id);
+ source->obj_path = g_strdup (obj_path);
+
+ return source;
+}
+
+GMountSource *
+g_mount_source_new_dummy (void)
+{
+ GMountSource *source;
+
+ source = g_object_new (G_TYPE_MOUNT_SOURCE, NULL);
+
+ source->dbus_id = g_strdup ("");
+ source->obj_path = g_strdup ("/");
+
+ return source;
+}
+
+
+void
+g_mount_source_to_dbus (GMountSource *source,
+ DBusMessage *message)
+{
+ g_assert (source->dbus_id != NULL);
+ g_assert (source->obj_path != NULL);
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &source->dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &source->obj_path,
+ 0))
+ _g_dbus_oom ();
+
+}
+
+const char *
+g_mount_source_get_dbus_id (GMountSource *mount_source)
+{
+ return mount_source->dbus_id;
+}
+
+const char *
+g_mount_source_get_obj_path (GMountSource *mount_source)
+{
+ return mount_source->obj_path;
+}
+
+typedef struct AskPasswordData AskPasswordData;
+
+struct AskPasswordData {
+
+ /* results: */
+ gboolean aborted;
+ char *password;
+ char *username;
+ char *domain;
+ GPasswordSave password_save;
+ gboolean anonymous;
+};
+
+typedef struct AskSyncData AskSyncData;
+
+struct AskSyncData {
+
+ /* For sync calls */
+ GMutex *mutex;
+ GCond *cond;
+
+ /* results: */
+ GAsyncResult *result;
+};
+
+static void
+ask_password_data_free (gpointer _data)
+{
+ AskPasswordData *data = (AskPasswordData *) _data;
+ g_free (data->password);
+ g_free (data->username);
+ g_free (data->domain);
+ g_free (data);
+}
+
+/* the callback from dbus -> main thread */
+static void
+ask_password_reply (DBusMessage *reply,
+ GError *error,
+ gpointer _data)
+{
+ GSimpleAsyncResult *result;
+ AskPasswordData *data;
+ dbus_bool_t handled, aborted, anonymous;
+ guint32 password_save;
+ const char *password, *username, *domain;
+ DBusMessageIter iter;
+
+ result = G_SIMPLE_ASYNC_RESULT (_data);
+ handled = TRUE;
+
+ data = g_new0 (AskPasswordData, 1);
+ g_simple_async_result_set_op_res_gpointer (result, data, ask_password_data_free);
+
+ if (reply == NULL)
+ {
+ data->aborted = TRUE;
+ }
+ else
+ {
+ dbus_message_iter_init (reply, &iter);
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &aborted,
+ DBUS_TYPE_STRING, &password,
+ DBUS_TYPE_STRING, &username,
+ DBUS_TYPE_STRING, &domain,
+ DBUS_TYPE_BOOLEAN, &anonymous,
+ DBUS_TYPE_UINT32, &password_save,
+ 0))
+ data->aborted = TRUE;
+ else
+ {
+ data->aborted = aborted;
+
+ if (!anonymous)
+ {
+ data->password = g_strdup (password);
+ data->username = *username == 0 ? NULL : g_strdup (username);
+ data->domain = *domain == 0 ? NULL : g_strdup (domain);
+ }
+ data->password_save = (GPasswordSave)password_save;
+ data->anonymous = anonymous;
+
+ /* TODO: handle more args */
+ }
+ }
+
+ if (handled == FALSE)
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
+ }
+
+ g_simple_async_result_complete (result);
+}
+
+void
+g_mount_source_ask_password_async (GMountSource *source,
+ const char *message_string,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ DBusMessage *message;
+ guint32 flags_as_int;
+
+
+ /* If no dbus id specified, reply that we weren't handled */
+ if (source->dbus_id[0] == 0)
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (source),
+ callback,
+ user_data,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Internal Error");
+ return;
+ }
+
+ if (message_string == NULL)
+ message_string = "";
+ if (default_user == NULL)
+ default_user = "";
+ if (default_domain == NULL)
+ default_domain = "";
+
+ flags_as_int = flags;
+
+ message = dbus_message_new_method_call (source->dbus_id,
+ source->obj_path,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD);
+
+ _g_dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_STRING, &default_user,
+ DBUS_TYPE_STRING, &default_domain,
+ DBUS_TYPE_UINT32, &flags_as_int,
+ 0);
+
+ result = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+ g_mount_source_ask_password_async);
+ /* 30 minute timeout */
+ _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
+ ask_password_reply, result);
+ dbus_message_unref (message);
+
+}
+
+/**
+ * g_mount_source_ask_password_finish:
+ * @source: the source to query
+ * @result: the async result
+ * @aborted: set to %TRUE if the password dialog was aborted by the user
+ * @password_out: the to the password set by the user or to %NULL if none
+ * @user_out: set to the username set by the user or to %NULL if none
+ * @domain_out: set to the domain set by the user or to %NULL if none
+ * @anonymous_out: set to %TRUE if the user selected anonymous login. This
+ * should only happen if G_ASK_PASSWORD_ANONYMOUS_SUPPORTED
+ * was supplied whe querying the password.
+ * @password_save_out: set to the save flags to use when saving the password
+ * in the keyring.
+ *
+ * Requests the reply parameters from a g_mount_source_ask_password_async()
+ * request. All out parameters can be set to %NULL to ignore them.
+ * <note><para>Please be aware that out parameters other than the password
+ * are set to %NULL if the user don't specify them so make sure to
+ * check them.</para></note>
+ *
+ * Returns: %FALSE if the async reply contained an error.
+ **/
+gboolean
+g_mount_source_ask_password_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out)
+{
+ AskPasswordData *data, def = { TRUE, };
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, NULL))
+ data = &def;
+ else
+ data = (AskPasswordData *) g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (aborted)
+ *aborted = data->aborted;
+
+ if (password_out)
+ {
+ *password_out = data->password;
+ data->password = NULL;
+ }
+
+ if (user_out)
+ {
+ *user_out = data->username;
+ data->username = NULL;
+ }
+
+ if (domain_out)
+ {
+ *domain_out = data->domain;
+ data->domain = NULL;
+ }
+
+ if (anonymous_out)
+ *anonymous_out = data->anonymous;
+
+ if (password_save_out)
+ *password_save_out = data->password_save;
+
+ return data != &def;
+}
+
+
+static void
+ask_reply_sync (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ AskSyncData *data;
+
+ data = (AskSyncData *) user_data;
+
+ data->result = g_object_ref (res);
+
+ /* Wake up sync call thread */
+ g_mutex_lock (data->mutex);
+ g_cond_signal (data->cond);
+ g_mutex_unlock (data->mutex);
+}
+
+gboolean
+g_mount_source_ask_password (GMountSource *source,
+ const char *message_string,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags,
+ gboolean *aborted_out,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out)
+{
+ gboolean handled;
+ AskSyncData data = {NULL};
+
+ data.mutex = g_mutex_new ();
+ data.cond = g_cond_new ();
+
+ g_mutex_lock (data.mutex);
+
+
+ g_mount_source_ask_password_async (source,
+ message_string,
+ default_user,
+ default_domain,
+ flags,
+ ask_reply_sync,
+ &data);
+
+ g_cond_wait(data.cond, data.mutex);
+ g_mutex_unlock (data.mutex);
+
+ g_cond_free (data.cond);
+ g_mutex_free (data.mutex);
+
+
+ handled = g_mount_source_ask_password_finish (source,
+ data.result,
+ aborted_out,
+ password_out,
+ user_out,
+ domain_out,
+ anonymous_out,
+ password_save_out);
+ g_object_unref (data.result);
+
+ return handled;
+}
+
+static void
+op_ask_password_reply (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GMountOperationResult result;
+ GMountOperation *op;
+ GMountSource *source;
+ gboolean handled, aborted;
+ char *username;
+ char *password;
+ char *domain;
+ GPasswordSave password_save;
+
+ source = G_MOUNT_SOURCE (source_object);
+ op = G_MOUNT_OPERATION (user_data);
+ username = NULL;
+ password = NULL;
+ domain = NULL;
+
+ handled = g_mount_source_ask_password_finish (source,
+ res,
+ &aborted,
+ &username,
+ &password,
+ &domain,
+ NULL,
+ &password_save);
+
+ if (!handled)
+ result = G_MOUNT_OPERATION_UNHANDLED;
+ else if (aborted)
+ result = G_MOUNT_OPERATION_ABORTED;
+ else
+ {
+ result = G_MOUNT_OPERATION_HANDLED;
+
+ if (password)
+ g_mount_operation_set_password (op, password);
+ if (username)
+ g_mount_operation_set_username (op, username);
+ if (domain)
+ g_mount_operation_set_domain (op, domain);
+ g_mount_operation_set_password_save (op, password_save);
+ }
+
+ g_mount_operation_reply (op, result);
+ g_object_unref (op);
+}
+
+static gboolean
+op_ask_password (GMountOperation *op,
+ const char *message,
+ const char *default_user,
+ const char *default_domain,
+ GAskPasswordFlags flags,
+ GMountSource *mount_source)
+{
+ g_mount_source_ask_password_async (mount_source,
+ message,
+ default_user,
+ default_domain,
+ flags,
+ op_ask_password_reply,
+ g_object_ref (op));
+ return TRUE;
+}
+
+typedef struct AskQuestionData AskQuestionData;
+
+struct AskQuestionData {
+
+ /* results: */
+ gboolean aborted;
+ guint32 choice;
+};
+
+/* the callback from dbus -> main thread */
+static void
+ask_question_reply (DBusMessage *reply,
+ GError *error,
+ gpointer _data)
+{
+ GSimpleAsyncResult *result;
+ AskQuestionData *data;
+ dbus_bool_t handled, aborted;
+ guint32 choice;
+ DBusMessageIter iter;
+
+ result = G_SIMPLE_ASYNC_RESULT (_data);
+ handled = TRUE;
+
+ data = g_new0 (AskQuestionData, 1);
+ g_simple_async_result_set_op_res_gpointer (result, data, g_free);
+
+ if (reply == NULL)
+ {
+ data->aborted = TRUE;
+ }
+ else
+ {
+ dbus_message_iter_init (reply, &iter);
+ if (!_g_dbus_message_iter_get_args (&iter, NULL,
+ DBUS_TYPE_BOOLEAN, &handled,
+ DBUS_TYPE_BOOLEAN, &aborted,
+ DBUS_TYPE_UINT32, &choice,
+ 0))
+ data->aborted = TRUE;
+ else
+ {
+ data->aborted = aborted;
+ data->choice = choice;
+ }
+ }
+
+ if (handled == FALSE)
+ {
+ g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
+ }
+
+ g_simple_async_result_complete (result);
+}
+
+gboolean
+g_mount_source_ask_question (GMountSource *source,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ gboolean *aborted_out,
+ gint *choice_out)
+{
+ gint choice;
+ gboolean handled, aborted;
+ AskSyncData data = {NULL};
+
+ data.mutex = g_mutex_new ();
+ data.cond = g_cond_new ();
+
+ g_mutex_lock (data.mutex);
+
+ g_mount_source_ask_question_async (source,
+ message,
+ choices,
+ n_choices,
+ ask_reply_sync,
+ &data);
+
+ g_cond_wait(data.cond, data.mutex);
+ g_mutex_unlock (data.mutex);
+
+ g_cond_free (data.cond);
+ g_mutex_free (data.mutex);
+
+ handled = g_mount_source_ask_question_finish (source,
+ data.result,
+ &aborted,
+ &choice);
+
+ g_object_unref (data.result);
+
+ if (aborted_out)
+ *aborted_out = aborted;
+
+ if (choice_out)
+ *choice_out = choice;
+
+ return handled;
+}
+
+void
+g_mount_source_ask_question_async (GMountSource *source,
+ const char *message_string,
+ const char **choices,
+ gint n_choices,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ DBusMessage *message;
+
+ /* If no dbus id specified, reply that we weren't handled */
+ if (source->dbus_id[0] == 0)
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (source),
+ callback,
+ user_data,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Internal Error");
+ return;
+ }
+
+ if (message_string == NULL)
+ message_string = "";
+
+ message = dbus_message_new_method_call (source->dbus_id,
+ source->obj_path,
+ G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
+ G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION);
+
+ _g_dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &message_string,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ choices, n_choices,
+ 0);
+
+ result = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
+ g_mount_source_ask_question_async);
+ /* 30 minute timeout */
+ _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
+ ask_question_reply, result);
+ dbus_message_unref (message);
+
+}
+
+gboolean
+g_mount_source_ask_question_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ gint *choice_out)
+{
+ AskQuestionData *data, def= { FALSE, };
+ GSimpleAsyncResult *simple;
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, NULL))
+ data = &def;
+ else
+ data = (AskQuestionData *) g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (aborted)
+ *aborted = data->aborted;
+
+ if (choice_out)
+ *choice_out = data->choice;
+
+ return data != &def;
+}
+
+static void
+op_ask_question_reply (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GMountOperationResult result;
+ GMountOperation *op;
+ GMountSource *source;
+ gboolean handled, aborted;
+ gint choice;
+
+ source = G_MOUNT_SOURCE (source_object);
+ op = G_MOUNT_OPERATION (user_data);
+
+ handled = g_mount_source_ask_question_finish (source,
+ res,
+ &aborted,
+ &choice);
+
+ if (!handled)
+ result = G_MOUNT_OPERATION_UNHANDLED;
+ else if (aborted)
+ result = G_MOUNT_OPERATION_ABORTED;
+ else
+ {
+ result = G_MOUNT_OPERATION_HANDLED;
+ g_mount_operation_set_choice (op, choice);
+ }
+
+ g_mount_operation_reply (op, result);
+ g_object_unref (op);
+}
+
+static gboolean
+op_ask_question (GMountOperation *op,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ GMountSource *mount_source)
+{
+ g_mount_source_ask_question_async (mount_source,
+ message,
+ choices,
+ n_choices,
+ op_ask_question_reply,
+ g_object_ref (op));
+ return TRUE;
+}
+
+GMountOperation *
+g_mount_source_get_operation (GMountSource *mount_source)
+{
+ GMountOperation *op;
+
+ op = g_mount_operation_new ();
+ g_object_set_data_full (G_OBJECT (op), "source",
+ g_object_ref (mount_source),
+ g_object_unref);
+
+
+ g_signal_connect (op, "ask_password", (GCallback)op_ask_password, mount_source);
+ g_signal_connect (op, "ask_question", (GCallback)op_ask_question, mount_source);
+
+ return op;
+}
diff --git a/gnome-2-24/common/gmountsource.h b/gnome-2-24/common/gmountsource.h
new file mode 100644
index 00000000..e4298357
--- /dev/null
+++ b/gnome-2-24/common/gmountsource.h
@@ -0,0 +1,115 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_SOURCE_H__
+#define __G_MOUNT_SOURCE_H__
+
+#include <glib-object.h>
+#include <gmountspec.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_MOUNT_SOURCE (g_mount_source_get_type ())
+#define G_MOUNT_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOUNT_SOURCE, GMountSource))
+#define G_MOUNT_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOUNT_SOURCE, GMountSourceClass))
+#define G_IS_MOUNT_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOUNT_SOURCE))
+#define G_IS_MOUNT_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOUNT_SOURCE))
+#define G_MOUNT_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MOUNT_SOURCE, GMountSourceClass))
+
+typedef struct _GMountSource GMountSource;
+typedef struct _GMountSourceClass GMountSourceClass;
+
+struct _GMountSourceClass
+{
+ GObjectClass parent_class;
+};
+
+typedef void (*RequestMountSpecCallback) (GMountSource *source,
+ GMountSpec *mount_spec,
+ GError *error,
+ gpointer data);
+
+GType g_mount_source_get_type (void) G_GNUC_CONST;
+
+GMountSource *g_mount_source_new (const char *dbus_id,
+ const char *obj_path);
+GMountSource *g_mount_source_new_dummy (void);
+void g_mount_source_to_dbus (GMountSource *source,
+ DBusMessage *message);
+gboolean g_mount_source_ask_password (GMountSource *mount_source,
+ const char *message,
+ const char *initial_user,
+ const char *initial_domain,
+ GAskPasswordFlags flags,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out);
+
+void g_mount_source_ask_password_async (GMountSource *mount_source,
+ const char *message,
+ const char *initial_user,
+ const char *initial_domain,
+ GAskPasswordFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean g_mount_source_ask_password_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ char **password_out,
+ char **user_out,
+ char **domain_out,
+ gboolean *anonymous_out,
+ GPasswordSave *password_save_out);
+
+gboolean g_mount_source_ask_question (GMountSource *mount_source,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ gboolean *aborted,
+ gint *choice_out);
+
+void g_mount_source_ask_question_async (GMountSource *mount_source,
+ const char *message,
+ const char **choices,
+ gint n_choices,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean g_mount_source_ask_question_finish (GMountSource *source,
+ GAsyncResult *result,
+ gboolean *aborted,
+ gint *choice_out);
+
+
+const char * g_mount_source_get_dbus_id (GMountSource *mount_source);
+const char * g_mount_source_get_obj_path (GMountSource *mount_source);
+
+GMountOperation *g_mount_source_get_operation (GMountSource *mount_source);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_SOURCE_H__ */
diff --git a/gnome-2-24/common/gmountspec.c b/gnome-2-24/common/gmountspec.c
new file mode 100644
index 00000000..7d8fa57e
--- /dev/null
+++ b/gnome-2-24/common/gmountspec.c
@@ -0,0 +1,534 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "gdbusutils.h"
+#include "gmountspec.h"
+
+static GHashTable *unique_hash = NULL;
+G_LOCK_DEFINE_STATIC(unique_hash);
+
+static int
+item_compare (const void *_a, const void *_b)
+{
+ const GMountSpecItem *a = _a;
+ const GMountSpecItem *b = _b;
+
+ return strcmp (a->key, b->key);
+}
+
+GMountSpec *
+g_mount_spec_new (const char *type)
+{
+ GMountSpec *spec;
+
+ spec = g_new0 (GMountSpec, 1);
+ spec->ref_count = 1;
+ spec->items = g_array_new (FALSE, TRUE, sizeof (GMountSpecItem));
+ spec->mount_prefix = g_strdup ("/");
+
+ if (type != NULL)
+ g_mount_spec_set (spec, "type", type);
+
+ return spec;
+}
+
+/* Takes ownership of passed in data */
+GMountSpec *
+g_mount_spec_new_from_data (GArray *items,
+ char *mount_prefix)
+{
+ GMountSpec *spec;
+
+ spec = g_new0 (GMountSpec, 1);
+ spec->ref_count = 1;
+ spec->items = items;
+ if (mount_prefix == NULL)
+ spec->mount_prefix = g_strdup ("/");
+ else
+ spec->mount_prefix = mount_prefix;
+
+ g_array_sort (spec->items, item_compare);
+
+ return spec;
+}
+
+GMountSpec *
+g_mount_spec_get_unique_for (GMountSpec *spec)
+{
+ GMountSpec *unique_spec;
+
+ if (spec->is_unique)
+ return g_mount_spec_ref (spec);
+
+ G_LOCK (unique_hash);
+
+ if (unique_hash == NULL)
+ unique_hash = g_hash_table_new (g_mount_spec_hash, (GEqualFunc)g_mount_spec_equal);
+
+ unique_spec = g_hash_table_lookup (unique_hash, spec);
+
+ if (unique_spec == NULL)
+ {
+ spec->is_unique = TRUE;
+ g_hash_table_insert (unique_hash, spec, spec);
+ unique_spec = spec;
+ }
+
+ g_mount_spec_ref (unique_spec);
+
+ G_UNLOCK (unique_hash);
+
+ return unique_spec;
+}
+
+void
+g_mount_spec_set_mount_prefix (GMountSpec *spec,
+ const char *mount_prefix)
+{
+ g_free (spec->mount_prefix);
+ spec->mount_prefix = g_strdup (mount_prefix);
+}
+
+
+static void
+add_item (GMountSpec *spec,
+ const char *key,
+ char *value)
+{
+ GMountSpecItem item;
+
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ item.key = g_strdup (key);
+ item.value = value;
+
+ g_array_append_val (spec->items, item);
+}
+
+
+void
+g_mount_spec_set_with_len (GMountSpec *spec,
+ const char *key,
+ const char *value,
+ int value_len)
+{
+ int i;
+ char *value_copy;
+
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ if (value_len == -1)
+ value_copy = g_strdup (value);
+ else
+ value_copy = g_strndup (value, value_len);
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+ if (strcmp (item->key, key) == 0)
+ {
+ g_free (item->value);
+ item->value = value_copy;
+ return;
+ }
+ }
+
+ add_item (spec, key, value_copy);
+ g_array_sort (spec->items, item_compare);
+}
+
+void
+g_mount_spec_set (GMountSpec *spec,
+ const char *key,
+ const char *value)
+{
+ g_mount_spec_set_with_len (spec, key, value, -1);
+}
+
+
+GMountSpec *
+g_mount_spec_copy (GMountSpec *spec)
+{
+ GMountSpec *copy;
+ int i;
+
+ copy = g_mount_spec_new (NULL);
+ g_mount_spec_set_mount_prefix (copy, spec->mount_prefix);
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+ g_mount_spec_set (copy, item->key, item->value);
+ }
+
+ return copy;
+}
+
+GMountSpec *
+g_mount_spec_ref (GMountSpec *spec)
+{
+ g_atomic_int_inc (&spec->ref_count);
+ return spec;
+}
+
+
+void
+g_mount_spec_unref (GMountSpec *spec)
+{
+ int i;
+
+ if (g_atomic_int_dec_and_test (&spec->ref_count))
+ {
+ G_LOCK (unique_hash);
+ if (unique_hash != NULL &&
+ spec->is_unique)
+ g_hash_table_remove (unique_hash, spec);
+ G_UNLOCK (unique_hash);
+
+ g_free (spec->mount_prefix);
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+ g_free (item->key);
+ g_free (item->value);
+ }
+ g_array_free (spec->items, TRUE);
+
+ g_free (spec);
+ }
+}
+
+GMountSpec *
+g_mount_spec_from_dbus (DBusMessageIter *iter)
+{
+ GMountSpec *spec;
+ DBusMessageIter array_iter, struct_iter, spec_iter;
+ const char *key;
+ char *value;
+ char *mount_prefix;
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ return NULL;
+
+ dbus_message_iter_recurse (iter, &spec_iter);
+
+ mount_prefix = NULL;
+ if (!_g_dbus_message_iter_get_args (&spec_iter, NULL,
+ G_DBUS_TYPE_CSTRING, &mount_prefix,
+ 0))
+ return NULL;
+
+ spec = g_mount_spec_new (NULL);
+ g_free (spec->mount_prefix);
+ spec->mount_prefix = mount_prefix;
+
+ if (dbus_message_iter_get_arg_type (&spec_iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type (&spec_iter) != DBUS_TYPE_STRUCT)
+ {
+ g_mount_spec_unref (spec);
+ return NULL;
+ }
+
+ dbus_message_iter_recurse (&spec_iter, &array_iter);
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ dbus_message_iter_recurse (&array_iter, &struct_iter);
+ if (_g_dbus_message_iter_get_args (&struct_iter, NULL,
+ DBUS_TYPE_STRING, &key,
+ G_DBUS_TYPE_CSTRING, &value,
+ 0))
+ add_item (spec, key, value);
+ dbus_message_iter_next (&array_iter);
+ }
+
+ dbus_message_iter_next (iter);
+
+ /* Sort on key */
+ g_array_sort (spec->items, item_compare);
+
+ return spec;
+}
+
+void
+g_mount_spec_to_dbus_with_path (DBusMessageIter *iter,
+ GMountSpec *spec,
+ const char *path)
+{
+ DBusMessageIter spec_iter, array_iter, item_iter;
+ int i;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &spec_iter))
+ _g_dbus_oom ();
+
+ _g_dbus_message_iter_append_cstring (&spec_iter, path ? path : "");
+
+ if (!dbus_message_iter_open_container (&spec_iter,
+ DBUS_TYPE_ARRAY,
+ G_MOUNT_SPEC_ITEM_TYPE_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+
+ if (!dbus_message_iter_open_container (&array_iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &item_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&item_iter, DBUS_TYPE_STRING,
+ &item->key))
+ _g_dbus_oom ();
+ _g_dbus_message_iter_append_cstring (&item_iter, item->value);
+
+ if (!dbus_message_iter_close_container (&array_iter, &item_iter))
+ _g_dbus_oom ();
+
+ }
+
+ if (!dbus_message_iter_close_container (&spec_iter, &array_iter))
+ _g_dbus_oom ();
+
+
+
+ if (!dbus_message_iter_close_container (iter, &spec_iter))
+ _g_dbus_oom ();
+
+}
+
+void
+g_mount_spec_to_dbus (DBusMessageIter *iter,
+ GMountSpec *spec)
+{
+ g_mount_spec_to_dbus_with_path (iter, spec, spec->mount_prefix);
+}
+
+static gboolean
+items_equal (GArray *a,
+ GArray *b)
+{
+ int i;
+
+ if (a->len != b->len)
+ return FALSE;
+
+ for (i = 0; i < a->len; i++)
+ {
+ GMountSpecItem *item_a = &g_array_index (a, GMountSpecItem, i);
+ GMountSpecItem *item_b = &g_array_index (b, GMountSpecItem, i);
+
+ if (strcmp (item_a->key, item_b->key) != 0)
+ return FALSE;
+ if (strcmp (item_a->value, item_b->value) != 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+path_has_prefix (const char *path,
+ const char *prefix)
+{
+ int prefix_len;
+
+ if (prefix == NULL)
+ return TRUE;
+
+ prefix_len = strlen (prefix);
+
+ if (strncmp (path, prefix, prefix_len) == 0 &&
+ (prefix_len == 0 || /* empty prefix always matches */
+ prefix[prefix_len - 1] == '/' || /* last char in prefix was a /, so it must be in path too */
+ path[prefix_len] == 0 ||
+ path[prefix_len] == '/'))
+ return TRUE;
+
+ return FALSE;
+}
+
+guint
+g_mount_spec_hash (gconstpointer _mount)
+{
+ GMountSpec *mount = (GMountSpec *) _mount;
+ guint hash;
+ int i;
+
+ hash = 0;
+ if (mount->mount_prefix)
+ hash ^= g_str_hash (mount->mount_prefix);
+
+ for (i = 0; i < mount->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (mount->items, GMountSpecItem, i);
+ hash ^= g_str_hash (item->value);
+ }
+
+ return hash;
+}
+
+gboolean
+g_mount_spec_equal (GMountSpec *mount1,
+ GMountSpec *mount2)
+{
+ return items_equal (mount1->items, mount2->items) &&
+ ((mount1->mount_prefix == mount2->mount_prefix) ||
+ (mount1->mount_prefix != NULL && mount2->mount_prefix != NULL &&
+ strcmp (mount1->mount_prefix, mount2->mount_prefix) == 0));
+}
+
+gboolean
+g_mount_spec_match_with_path (GMountSpec *mount,
+ GMountSpec *spec,
+ const char *path)
+{
+ if (items_equal (mount->items, spec->items) &&
+ path_has_prefix (path, mount->mount_prefix))
+ return TRUE;
+ return FALSE;
+}
+
+gboolean
+g_mount_spec_match (GMountSpec *mount,
+ GMountSpec *path)
+{
+ return g_mount_spec_match_with_path (mount, path, path->mount_prefix);
+}
+
+const char *
+g_mount_spec_get (GMountSpec *spec,
+ const char *key)
+{
+ int i;
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+
+ if (strcmp (item->key, key) == 0)
+ return item->value;
+ }
+
+ return NULL;
+}
+
+const char *
+g_mount_spec_get_type (GMountSpec *spec)
+{
+ return g_mount_spec_get (spec, "type");
+}
+
+char *
+g_mount_spec_to_string (GMountSpec *spec)
+{
+ GString *str;
+ int i;
+
+ if (spec == NULL)
+ return g_strdup ("(null)");
+
+ str = g_string_new ("");
+
+ for (i = 0; i < spec->items->len; i++)
+ {
+ GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
+
+ g_string_append_printf (str, "%s='%s',", item->key, item->value);
+ }
+ g_string_append_printf (str, "mount_prefix='%s'", spec->mount_prefix);
+
+ return g_string_free (str, FALSE);
+}
+
+char *
+g_mount_spec_canonicalize_path (const char *path)
+{
+ char *canon, *start, *p, *q;
+
+ if (*path != '/')
+ canon = g_strconcat ("/", path, NULL);
+ else
+ canon = g_strdup (path);
+
+ /* Skip initial slash */
+ start = canon + 1;
+
+ p = start;
+ while (*p != 0)
+ {
+ if (p[0] == '.' && (p[1] == 0 || p[1] == '/'))
+ {
+ memmove (p, p+1, strlen (p+1)+1);
+ }
+ else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || p[2] == '/'))
+ {
+ q = p + 2;
+ /* Skip previous separator */
+ p = p - 2;
+ if (p < start)
+ p = start;
+ while (p > start && *p != '/')
+ p--;
+ if (*p == '/')
+ p++;
+ memmove (p, q, strlen (q)+1);
+ }
+ else
+ {
+ /* Skip until next separator */
+ while (*p != 0 && *p != '/')
+ p++;
+
+ /* Keep one separator */
+ if (*p != 0)
+ p++;
+ }
+
+ /* Remove additional separators */
+ q = p;
+ while (*q && *q == '/')
+ q++;
+
+ if (p != q)
+ memmove (p, q, strlen (q)+1);
+ }
+
+ /* Remove trailing slashes */
+ if (p > start && *(p-1) == '/')
+ *(p-1) = 0;
+
+ return canon;
+}
diff --git a/gnome-2-24/common/gmountspec.h b/gnome-2-24/common/gmountspec.h
new file mode 100644
index 00000000..55ac5c63
--- /dev/null
+++ b/gnome-2-24/common/gmountspec.h
@@ -0,0 +1,103 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_SPEC_H__
+#define __G_MOUNT_SPEC_H__
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \
+ DBUS_TYPE_STRING_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
+
+#define G_MOUNT_SPEC_ITEM_TYPE_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+#define G_MOUNT_SPEC_INNER_TYPE_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING G_MOUNT_SPEC_ITEM_TYPE_AS_STRING
+
+#define G_MOUNT_SPEC_TYPE_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ G_MOUNT_SPEC_INNER_TYPE_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+typedef struct {
+ char *key;
+ char *value;
+} GMountSpecItem;
+
+typedef struct {
+ volatile int ref_count;
+ GArray *items;
+ char *mount_prefix;
+ gboolean is_unique;
+} GMountSpec;
+
+GMountSpec *g_mount_spec_new (const char *type);
+GMountSpec *g_mount_spec_new_from_data (GArray *items,
+ char *mount_prefix);
+GMountSpec *g_mount_spec_ref (GMountSpec *spec);
+void g_mount_spec_unref (GMountSpec *spec);
+GMountSpec *g_mount_spec_get_unique_for (GMountSpec *spec);
+GMountSpec *g_mount_spec_copy (GMountSpec *spec);
+GMountSpec *g_mount_spec_from_dbus (DBusMessageIter *iter);
+void g_mount_spec_to_dbus (DBusMessageIter *iter,
+ GMountSpec *spec);
+void g_mount_spec_to_dbus_with_path (DBusMessageIter *iter,
+ GMountSpec *spec,
+ const char *path);
+void g_mount_spec_set_mount_prefix (GMountSpec *spec,
+ const char *mount_prefix);
+void g_mount_spec_set (GMountSpec *spec,
+ const char *key,
+ const char *value);
+void g_mount_spec_set_with_len (GMountSpec *spec,
+ const char *key,
+ const char *value,
+ int value_len);
+guint g_mount_spec_hash (gconstpointer mount);
+gboolean g_mount_spec_equal (GMountSpec *mount1,
+ GMountSpec *mount2);
+gboolean g_mount_spec_match (GMountSpec *mount,
+ GMountSpec *path);
+gboolean g_mount_spec_match_with_path (GMountSpec *mount,
+ GMountSpec *spec,
+ const char *path);
+const char *g_mount_spec_get (GMountSpec *spec,
+ const char *key);
+const char *g_mount_spec_get_type (GMountSpec *spec);
+
+/* For debugging */
+char * g_mount_spec_to_string (GMountSpec *spec);
+
+char * g_mount_spec_canonicalize_path (const char *path);
+
+G_END_DECLS
+
+
+#endif /* __G_MOUNT_SPEC_H__ */
diff --git a/gnome-2-24/common/gmounttracker.c b/gnome-2-24/common/gmounttracker.c
new file mode 100644
index 00000000..eba29ef5
--- /dev/null
+++ b/gnome-2-24/common/gmounttracker.c
@@ -0,0 +1,621 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gmounttracker.h>
+#include <gdbusutils.h>
+#include <gvfsdaemonprotocol.h>
+
+enum {
+ MOUNTED,
+ UNMOUNTED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_CONNECTION
+};
+
+/* TODO: Real P_() */
+#define P_(_x) (_x)
+#define I_(string) g_intern_static_string (string)
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+struct _GMountTracker
+{
+ GObject parent_instance;
+
+ GMutex *lock;
+ GList *mounts;
+ DBusConnection *connection;
+};
+
+G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT)
+
+static DBusHandlerResult g_mount_tracker_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data);
+static GObject* g_mount_tracker_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params);
+static void g_mount_tracker_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void g_mount_tracker_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+gboolean
+g_mount_info_equal (GMountInfo *info1,
+ GMountInfo *info2)
+{
+ return
+ strcmp (info1->dbus_id, info2->dbus_id) == 0 &&
+ strcmp (info1->object_path, info2->object_path) == 0;
+}
+
+GMountInfo *
+g_mount_info_dup (GMountInfo *info)
+{
+ GMountInfo *copy;
+
+ copy = g_new (GMountInfo, 1);
+ copy->ref_count = 1;
+ copy->display_name = g_strdup (info->display_name);
+ copy->stable_name = g_strdup (info->stable_name);
+ copy->x_content_types = g_strdup (info->x_content_types);
+ copy->icon = g_strdup (info->icon);
+ copy->dbus_id = g_strdup (info->dbus_id);
+ copy->object_path = g_strdup (info->object_path);
+ copy->mount_spec = g_mount_spec_copy (info->mount_spec);
+ copy->user_visible = info->user_visible;
+ copy->prefered_filename_encoding = g_strdup (info->prefered_filename_encoding);
+ copy->fuse_mountpoint = g_strdup (info->fuse_mountpoint);
+
+ return copy;
+}
+
+GMountInfo *
+g_mount_info_ref (GMountInfo *info)
+{
+ g_atomic_int_inc (&info->ref_count);
+ return info;
+}
+
+void
+g_mount_info_unref (GMountInfo *info)
+{
+ if (g_atomic_int_dec_and_test (&info->ref_count))
+ {
+ g_free (info->display_name);
+ g_free (info->stable_name);
+ g_free (info->x_content_types);
+ g_free (info->icon);
+ g_free (info->dbus_id);
+ g_free (info->object_path);
+ g_mount_spec_unref (info->mount_spec);
+ g_free (info->prefered_filename_encoding);
+ g_free (info->fuse_mountpoint);
+ g_free (info);
+ }
+}
+
+const char *
+g_mount_info_resolve_path (GMountInfo *info,
+ const char *path)
+{
+ const char *new_path;
+ int len;
+
+ if (info->mount_spec->mount_prefix != NULL &&
+ info->mount_spec->mount_prefix[0] != 0)
+ {
+ len = strlen (info->mount_spec->mount_prefix);
+ if (info->mount_spec->mount_prefix[len-1] == '/')
+ len--;
+ new_path = path + len;
+ }
+ else
+ new_path = path;
+
+ if (new_path == NULL ||
+ new_path[0] == 0)
+ new_path = "/";
+
+ return new_path;
+}
+
+GMountInfo *
+g_mount_info_from_dbus (DBusMessageIter *iter)
+{
+ DBusMessageIter struct_iter;
+ GMountInfo *info;
+ GMountSpec *mount_spec;
+ dbus_bool_t user_visible;
+ char *display_name;
+ char *stable_name;
+ char *x_content_types;
+ char *icon;
+ char *prefered_filename_encoding;
+ char *dbus_id;
+ char *obj_path;
+ char *fuse_mountpoint;
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ return NULL;
+
+ dbus_message_iter_recurse (iter, &struct_iter);
+
+ if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
+ DBUS_TYPE_STRING, &dbus_id,
+ DBUS_TYPE_OBJECT_PATH, &obj_path,
+ DBUS_TYPE_STRING, &display_name,
+ DBUS_TYPE_STRING, &stable_name,
+ DBUS_TYPE_STRING, &x_content_types,
+ DBUS_TYPE_STRING, &icon,
+ DBUS_TYPE_STRING, &prefered_filename_encoding,
+ DBUS_TYPE_BOOLEAN, &user_visible,
+ G_DBUS_TYPE_CSTRING, &fuse_mountpoint,
+ 0))
+ return NULL;
+
+ mount_spec = g_mount_spec_from_dbus (&struct_iter);
+ if (mount_spec == NULL) {
+ g_free (fuse_mountpoint);
+ return NULL;
+ }
+
+ info = g_new0 (GMountInfo, 1);
+ info->ref_count = 1;
+ info->display_name = g_strdup (display_name);
+ info->stable_name = g_strdup (stable_name);
+ info->x_content_types = g_strdup (x_content_types);
+ info->icon = g_strdup (icon);
+ info->dbus_id = g_strdup (dbus_id);
+ info->object_path = g_strdup (obj_path);
+ info->mount_spec = mount_spec;
+ info->user_visible = user_visible;
+ info->prefered_filename_encoding = g_strdup (prefered_filename_encoding);
+ info->fuse_mountpoint = fuse_mountpoint;
+
+ return info;
+}
+
+
+static void
+g_mount_tracker_finalize (GObject *object)
+{
+ GMountTracker *tracker;
+
+ tracker = G_MOUNT_TRACKER (object);
+
+ if (tracker->lock)
+ g_mutex_free (tracker->lock);
+
+ g_list_foreach (tracker->mounts,
+ (GFunc)g_mount_info_unref, NULL);
+ g_list_free (tracker->mounts);
+
+ dbus_connection_remove_filter (tracker->connection, g_mount_tracker_filter_func, tracker);
+
+
+ dbus_bus_remove_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
+ NULL);
+ dbus_bus_remove_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
+ NULL);
+
+ dbus_connection_unref (tracker->connection);
+
+ if (G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) (object);
+}
+
+static void
+g_mount_tracker_class_init (GMountTrackerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_mount_tracker_finalize;
+ gobject_class->constructor = g_mount_tracker_constructor;
+ gobject_class->set_property = g_mount_tracker_set_property;
+ gobject_class->get_property = g_mount_tracker_get_property;
+
+ signals[MOUNTED] = g_signal_new (I_("mounted"),
+ G_TYPE_MOUNT_TRACKER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GMountTrackerClass, mounted),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ signals[UNMOUNTED] = g_signal_new (I_("unmounted"),
+ G_TYPE_MOUNT_TRACKER,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GMountTrackerClass, unmounted),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+ g_object_class_install_property (gobject_class,
+ PROP_CONNECTION,
+ g_param_spec_pointer ("connection",
+ P_("DBus connection"),
+ P_("The dbus connection to use for ipc."),
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+
+}
+
+static void
+g_mount_tracker_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GMountTracker *tracker = G_MOUNT_TRACKER (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ if (tracker->connection)
+ dbus_connection_unref (tracker->connection);
+ tracker->connection = NULL;
+ if (g_value_get_pointer (value))
+ tracker->connection = dbus_connection_ref (g_value_get_pointer (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_mount_tracker_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GMountTracker *tracker = G_MOUNT_TRACKER (object);
+
+ switch (prop_id)
+ {
+ case PROP_CONNECTION:
+ g_value_set_pointer (value, tracker->connection);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GList *
+g_mount_tracker_find (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ GList *l;
+
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ if (g_mount_info_equal (info, (GMountInfo *)l->data))
+ return l;
+ }
+
+ return NULL;
+}
+
+static void
+g_mount_tracker_add_mount (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ /* Don't add multiple times */
+ if (g_mount_tracker_find (tracker, info))
+ {
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+ return;
+ }
+
+ tracker->mounts = g_list_prepend (tracker->mounts, g_mount_info_ref (info));
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ g_signal_emit (tracker, signals[MOUNTED], 0, info);
+}
+
+static void
+g_mount_tracker_remove_mount (GMountTracker *tracker,
+ GMountInfo *info)
+{
+ GList *l;
+ GMountInfo *old_info;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ l = g_mount_tracker_find (tracker, info);
+
+ /* Don't remove multiple times */
+ if (l == NULL)
+ {
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+ return;
+ }
+
+ old_info = l->data;
+
+ tracker->mounts = g_list_delete_link (tracker->mounts, l);
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ g_signal_emit (tracker, signals[UNMOUNTED], 0, old_info);
+ g_mount_info_unref (old_info);
+}
+
+static void
+list_mounts_reply (GMountTracker *tracker,
+ DBusMessage *reply)
+{
+ DBusMessageIter iter, array_iter;
+ GMountInfo *info;
+ gboolean b;
+
+ b = dbus_message_iter_init (reply, &iter);
+ if (b && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY)
+ {
+ dbus_message_iter_recurse (&iter, &array_iter);
+
+ do
+ {
+ info = g_mount_info_from_dbus (&array_iter);
+ if (info)
+ {
+ g_mount_tracker_add_mount (tracker, info);
+ g_mount_info_unref (info);
+ }
+ }
+ while (dbus_message_iter_next (&array_iter));
+ }
+ else
+ {
+ /* list_mounts_reply problem - gvfsd not running? */
+ }
+}
+
+static DBusHandlerResult
+g_mount_tracker_filter_func (DBusConnection *conn,
+ DBusMessage *message,
+ gpointer data)
+{
+ GMountTracker *tracker = data;
+ GMountInfo *info;
+ DBusMessageIter iter;
+
+ if (dbus_message_is_signal (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED))
+ {
+ dbus_message_iter_init (message, &iter);
+ info = g_mount_info_from_dbus (&iter);
+
+ if (info)
+ {
+ g_mount_tracker_add_mount (tracker, info);
+ g_mount_info_unref (info);
+ }
+ }
+ else if (dbus_message_is_signal (message,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED))
+ {
+ dbus_message_iter_init (message, &iter);
+ info = g_mount_info_from_dbus (&iter);
+
+ if (info)
+ {
+ g_mount_tracker_remove_mount (tracker, info);
+ g_mount_info_unref (info);
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/* Called after construction when the construct properties (like connection) are set */
+static void
+init_connection (GMountTracker *tracker)
+{
+ DBusMessage *message, *reply;
+
+ if (tracker->connection == NULL)
+ tracker->connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+
+ message =
+ dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
+ G_VFS_DBUS_MOUNTTRACKER_PATH,
+ G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
+ G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS);
+ if (message == NULL)
+ _g_dbus_oom ();
+
+ dbus_message_set_auto_start (message, TRUE);
+
+ reply = dbus_connection_send_with_reply_and_block (tracker->connection, message,
+ G_VFS_DBUS_TIMEOUT_MSECS,
+ NULL);
+ dbus_message_unref (message);
+
+ if (reply != NULL)
+ {
+ list_mounts_reply (tracker, reply);
+ dbus_message_unref (reply);
+ }
+
+ dbus_connection_add_filter (tracker->connection, g_mount_tracker_filter_func, tracker, NULL);
+
+ dbus_bus_add_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
+ NULL);
+ dbus_bus_add_match (tracker->connection,
+ "sender='"G_VFS_DBUS_DAEMON_NAME"',"
+ "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
+ "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
+ NULL);
+}
+
+static void
+g_mount_tracker_init (GMountTracker *tracker)
+{
+ if (g_thread_supported ())
+ tracker->lock = g_mutex_new ();
+}
+
+
+static GObject*
+g_mount_tracker_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_params)
+{
+ GObject *object;
+ GMountTracker *tracker;
+
+ object = (* G_OBJECT_CLASS (g_mount_tracker_parent_class)->constructor) (type,
+ n_construct_properties,
+ construct_params);
+
+ tracker = G_MOUNT_TRACKER (object);
+
+ init_connection (tracker);
+
+ return object;
+}
+
+GMountTracker *
+g_mount_tracker_new (DBusConnection *connection)
+{
+ GMountTracker *tracker;
+
+ tracker = g_object_new (G_TYPE_MOUNT_TRACKER, "connection", connection, NULL);
+
+ return tracker;
+}
+
+GList *
+g_mount_tracker_list_mounts (GMountTracker *tracker)
+{
+ GList *res, *l;
+ GMountInfo *copy;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ res = NULL;
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ copy = g_mount_info_ref (l->data);
+ res = g_list_prepend (res, copy);
+ }
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ return g_list_reverse (res);
+}
+
+GMountInfo *
+g_mount_tracker_find_by_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec)
+{
+ GList *l;
+ GMountInfo *info, *found;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ found = NULL;
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ info = l->data;
+
+ if (g_mount_spec_equal (info->mount_spec, mount_spec))
+ {
+ found = g_mount_info_ref (info);
+ break;
+ }
+ }
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ return found;
+}
+
+
+gboolean
+g_mount_tracker_has_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec)
+{
+ GList *l;
+ GMountInfo *info;
+ gboolean found;
+
+ if (tracker->lock)
+ g_mutex_lock (tracker->lock);
+
+ found = FALSE;
+ for (l = tracker->mounts; l != NULL; l = l->next)
+ {
+ info = l->data;
+
+ if (g_mount_spec_equal (info->mount_spec, mount_spec))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (tracker->lock)
+ g_mutex_unlock (tracker->lock);
+
+ return found;
+}
+
diff --git a/gnome-2-24/common/gmounttracker.h b/gnome-2-24/common/gmounttracker.h
new file mode 100644
index 00000000..67c91ff1
--- /dev/null
+++ b/gnome-2-24/common/gmounttracker.h
@@ -0,0 +1,86 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_MOUNT_TRACKER_H__
+#define __G_MOUNT_TRACKER_H__
+
+#include <glib-object.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_MOUNT_TRACKER (g_mount_tracker_get_type ())
+#define G_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOUNT_TRACKER, GMountTracker))
+#define G_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOUNT_TRACKER, GMountTrackerClass))
+#define G_IS_MOUNT_TRACKER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOUNT_TRACKER))
+#define G_IS_MOUNT_TRACKER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOUNT_TRACKER))
+#define G_MOUNT_TRACKER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_MOUNT_TRACKER, GMountTrackerClass))
+
+typedef struct _GMountTracker GMountTracker;
+typedef struct _GMountTrackerClass GMountTrackerClass;
+
+typedef struct {
+ volatile int ref_count;
+ char *display_name;
+ char *stable_name;
+ char *x_content_types;
+ char *icon;
+ char *dbus_id;
+ char *object_path;
+ gboolean user_visible;
+ char *prefered_filename_encoding; /* NULL -> UTF8 */
+ char *fuse_mountpoint;
+ GMountSpec *mount_spec;
+} GMountInfo;
+
+struct _GMountTrackerClass
+{
+ GObjectClass parent_class;
+
+ void (*mounted) (GMountTracker *tracker,
+ GMountInfo *info);
+ void (*unmounted) (GMountTracker *tracker,
+ GMountInfo *info);
+};
+
+GType g_mount_tracker_get_type (void) G_GNUC_CONST;
+
+gboolean g_mount_info_equal (GMountInfo *info1,
+ GMountInfo *info2);
+GMountInfo *g_mount_info_ref (GMountInfo *info);
+GMountInfo *g_mount_info_dup (GMountInfo *info);
+void g_mount_info_unref (GMountInfo *info);
+const char *g_mount_info_resolve_path (GMountInfo *info,
+ const char *path);
+
+GMountInfo * g_mount_info_from_dbus (DBusMessageIter *iter);
+
+GMountTracker *g_mount_tracker_new (DBusConnection *connection);
+GList * g_mount_tracker_list_mounts (GMountTracker *tracker);
+GMountInfo * g_mount_tracker_find_by_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec);
+gboolean g_mount_tracker_has_mount_spec (GMountTracker *tracker,
+ GMountSpec *mount_spec);
+
+G_END_DECLS
+
+#endif /* __G_MOUNT_TRACKER_H__ */
diff --git a/gnome-2-24/common/gsysutils.c b/gnome-2-24/common/gsysutils.c
new file mode 100644
index 00000000..9dd8afa4
--- /dev/null
+++ b/gnome-2-24/common/gsysutils.c
@@ -0,0 +1,181 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#if defined(HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#include <gio/gio.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "gsysutils.h"
+
+int
+_g_socket_send_fd (int connection_fd,
+ int fd)
+{
+ struct msghdr msg;
+ struct iovec vec[1];
+ char buf[1] = {'x'};
+ char ccmsg[CMSG_SPACE (sizeof (fd))];
+ struct cmsghdr *cmsg;
+ int ret;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ vec[0].iov_base = buf;
+ vec[0].iov_len = 1;
+ msg.msg_iov = vec;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof (ccmsg);
+ cmsg = CMSG_FIRSTHDR (&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN (sizeof(fd));
+ *(int*)CMSG_DATA (cmsg) = fd;
+ msg.msg_controllen = cmsg->cmsg_len;
+ msg.msg_flags = 0;
+
+ ret = sendmsg (connection_fd, &msg, 0);
+ return ret;
+}
+
+/* receive a file descriptor over file descriptor fd */
+int
+_g_socket_receive_fd (int socket_fd)
+{
+ struct msghdr msg;
+ struct iovec iov[1];
+ char buf[1];
+ int rv;
+ char ccmsg[CMSG_SPACE (sizeof(int))];
+ struct cmsghdr *cmsg;
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 1;
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = ccmsg;
+ msg.msg_controllen = sizeof (ccmsg);
+
+ rv = recvmsg (socket_fd, &msg, 0);
+ if (rv == -1)
+ {
+ perror ("recvmsg");
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR (&msg);
+ if (cmsg == NULL)
+ return -1;
+
+ if (!cmsg->cmsg_type == SCM_RIGHTS) {
+ g_warning("got control message of unknown type %d",
+ cmsg->cmsg_type);
+ return -1;
+ }
+
+ return *(int*)CMSG_DATA(cmsg);
+}
+
+int
+_g_socket_connect (const char *address,
+ GError **error)
+{
+ int fd;
+ const char *path;
+ size_t path_len;
+ struct sockaddr_un addr;
+ gboolean abstract;
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (fd == -1)
+ {
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error creating socket: %s"),
+ g_strerror (errsv));
+ return -1;
+ }
+
+ if (g_str_has_prefix (address, "unix:abstract="))
+ {
+ path = address + strlen ("unix:abstract=");
+ abstract = TRUE;
+ }
+ else
+ {
+ path = address + strlen ("unix:path=");
+ abstract = FALSE;
+ }
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ path_len = strlen (path);
+
+ if (abstract)
+ {
+ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
+ path_len++; /* Account for the extra nul byte added to the start of sun_path */
+
+ strncpy (&addr.sun_path[1], path, path_len);
+ }
+ else
+ {
+ strncpy (addr.sun_path, path, path_len);
+ }
+
+ if (connect (fd, (struct sockaddr*) &addr, G_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
+ {
+ int errsv = errno;
+
+ g_set_error (error, G_IO_ERROR,
+ g_io_error_from_errno (errsv),
+ _("Error connecting to socket: %s"),
+ g_strerror (errsv));
+ close (fd);
+ return -1;
+ }
+
+ return fd;
+}
diff --git a/gnome-2-24/common/gsysutils.h b/gnome-2-24/common/gsysutils.h
new file mode 100644
index 00000000..f68a2642
--- /dev/null
+++ b/gnome-2-24/common/gsysutils.h
@@ -0,0 +1,39 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __G_SYS_UTILS_H__
+#define __G_SYS_UTILS_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+int _g_socket_send_fd (int socket_fd,
+ int fd);
+int _g_socket_receive_fd (int socket_fd);
+int _g_socket_connect (const char *address,
+ GError **error);
+
+G_END_DECLS
+
+
+#endif /* __G_SYS_UTILS_H__ */
diff --git a/gnome-2-24/common/gvfsdaemonprotocol.c b/gnome-2-24/common/gvfsdaemonprotocol.c
new file mode 100644
index 00000000..36331ed8
--- /dev/null
+++ b/gnome-2-24/common/gvfsdaemonprotocol.c
@@ -0,0 +1,614 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#include <config.h>
+
+#include <glib-object.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n-lib.h>
+#include <gvfsdaemonprotocol.h>
+#include <gdbusutils.h>
+#include <gio/gio.h>
+
+static const char *
+get_object_signature (GObject *obj)
+{
+ if (G_IS_THEMED_ICON (obj))
+ {
+ return
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING;
+ }
+ else if (G_IS_FILE_ICON (obj))
+ {
+ GFile *file;
+ char *path;
+
+ file = g_file_icon_get_file (G_FILE_ICON (obj));
+
+ path = g_file_get_path (file);
+ if (path)
+ {
+ g_free (path);
+ return
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING;
+ }
+ }
+ return
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING;
+}
+
+static void
+append_string_array (DBusMessageIter *iter, char **strs)
+{
+ DBusMessageIter array;
+ int i;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &array))
+ _g_dbus_oom ();
+
+
+ for (i = 0; strs[i] != NULL; i++)
+ {
+ if (!dbus_message_iter_append_basic (&array, DBUS_TYPE_STRING, &strs[i]))
+ _g_dbus_oom ();
+ }
+
+ if (!dbus_message_iter_close_container (iter, &array))
+ _g_dbus_oom ();
+}
+
+static void
+append_object (DBusMessageIter *iter, GObject *obj)
+{
+ DBusMessageIter obj_struct_iter;
+ guint32 v_uint32;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &obj_struct_iter))
+ _g_dbus_oom ();
+
+ if (G_IS_THEMED_ICON (obj))
+ {
+ const char * const *icons;
+
+ icons = g_themed_icon_get_names (G_THEMED_ICON (obj));
+
+ v_uint32 = 1;
+ if (!dbus_message_iter_append_basic (&obj_struct_iter,
+ DBUS_TYPE_UINT32, &v_uint32))
+ _g_dbus_oom ();
+
+ append_string_array (&obj_struct_iter, (char **)icons);
+ }
+ else if (G_IS_FILE_ICON (obj))
+ {
+ GFile *file;
+ char *path;
+
+ file = g_file_icon_get_file (G_FILE_ICON (obj));
+
+ path = g_file_get_path (file);
+ if (path)
+ {
+ v_uint32 = 2;
+ if (!dbus_message_iter_append_basic (&obj_struct_iter,
+ DBUS_TYPE_UINT32, &v_uint32))
+ _g_dbus_oom ();
+
+ path = g_file_get_path (file);
+ _g_dbus_message_iter_append_cstring (&obj_struct_iter, path);
+ g_free (path);
+ }
+ else
+ {
+ /* Seems unlikely that daemon backend will generate GFileIcons with
+ files on the vfs, so its probably not a problem not to support this.
+ (Its tricky to support, since we don't link the daemon to the client/
+ library directly.) */
+ g_warning ("Unknown file type for icon in attribute, ignoring");
+
+ v_uint32 = 0;
+ if (!dbus_message_iter_append_basic (&obj_struct_iter,
+ DBUS_TYPE_UINT32, &v_uint32))
+ _g_dbus_oom ();
+ }
+ }
+ else
+ {
+ /* NULL or unknown type: */
+ if (obj != NULL)
+ g_warning ("Unknown attribute object type, ignoring");
+
+ v_uint32 = 0;
+ if (!dbus_message_iter_append_basic (&obj_struct_iter,
+ DBUS_TYPE_UINT32, &v_uint32))
+ _g_dbus_oom ();
+ }
+
+ if (!dbus_message_iter_close_container (iter, &obj_struct_iter))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_attribute_value_destroy (GFileAttributeType type,
+ GDbusAttributeValue *value)
+{
+ switch (type) {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ g_free (value->ptr);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ if (value->ptr)
+ g_object_unref (value->ptr);
+ break;
+ default:
+ break;
+ }
+}
+
+gpointer
+_g_dbus_attribute_as_pointer (GFileAttributeType type,
+ GDbusAttributeValue *value)
+{
+ switch (type) {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ return value->ptr;
+ default:
+ return (gpointer) value;
+ }
+}
+
+const char *
+_g_dbus_type_from_file_attribute_type (GFileAttributeType type)
+{
+ char *dbus_type;
+
+ switch (type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ dbus_type = DBUS_TYPE_STRING_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
+ dbus_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ dbus_type = DBUS_TYPE_UINT32_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ dbus_type = DBUS_TYPE_INT32_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ dbus_type = DBUS_TYPE_UINT64_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ dbus_type = DBUS_TYPE_INT64_AS_STRING;
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ dbus_type = DBUS_TYPE_STRUCT_AS_STRING;
+ break;
+ default:
+ dbus_type = NULL;
+ g_warning ("Invalid attribute type %u, ignoring\n", type);
+ break;
+ }
+
+ return dbus_type;
+}
+
+void
+_g_dbus_append_file_attribute (DBusMessageIter *iter,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p)
+{
+ DBusMessageIter variant_iter, inner_struct_iter;
+ const char *dbus_type;
+ GObject *obj = NULL;
+
+ dbus_type = _g_dbus_type_from_file_attribute_type (type);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &inner_struct_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&inner_struct_iter,
+ DBUS_TYPE_STRING,
+ &attribute))
+ _g_dbus_oom ();
+
+ if (dbus_type[0] == DBUS_TYPE_STRUCT)
+ dbus_type = get_object_signature ((GObject *)value_p);
+
+ if (!dbus_message_iter_open_container (&inner_struct_iter,
+ DBUS_TYPE_VARIANT,
+ dbus_type,
+ &variant_iter))
+ _g_dbus_oom ();
+
+ if (dbus_type[0] == DBUS_TYPE_STRING)
+ {
+ if (!dbus_message_iter_append_basic (&variant_iter,
+ DBUS_TYPE_STRING, &value_p))
+ _g_dbus_oom ();
+ }
+ else if (dbus_type[0] == DBUS_TYPE_ARRAY)
+ _g_dbus_message_iter_append_cstring (&variant_iter, (char *)value_p);
+ else if (dbus_type[0] == DBUS_STRUCT_BEGIN_CHAR)
+ append_object (&variant_iter, (GObject *)value_p);
+ else if (dbus_type[0] == DBUS_TYPE_BOOLEAN)
+ {
+ /* dbus bool is uint32, gboolean is just "int", convert */
+ dbus_bool_t bool = *(gboolean *)value_p;
+ if (!dbus_message_iter_append_basic (&variant_iter,
+ dbus_type[0], &bool))
+ _g_dbus_oom ();
+ }
+ else
+ {
+ /* All other types have the same size as dbus types */
+ if (!dbus_message_iter_append_basic (&variant_iter,
+ dbus_type[0], value_p))
+ _g_dbus_oom ();
+ }
+
+ if (obj)
+ g_object_unref (obj);
+
+ if (!dbus_message_iter_close_container (&inner_struct_iter, &variant_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (iter, &inner_struct_iter))
+ _g_dbus_oom ();
+}
+
+void
+_g_dbus_append_file_info (DBusMessageIter *iter,
+ GFileInfo *info)
+{
+ DBusMessageIter struct_iter, array_iter;
+ char **attributes;
+ int i;
+
+ attributes = g_file_info_list_attributes (info, NULL);
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iter))
+ _g_dbus_oom ();
+
+
+ if (!dbus_message_iter_open_container (&struct_iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (i = 0; attributes[i] != NULL; i++)
+ {
+ GFileAttributeType type;
+ gpointer value_p;
+
+ if (g_file_info_get_attribute_data (info, attributes[i], &type, &value_p, NULL))
+ _g_dbus_append_file_attribute (&array_iter, attributes [i], type, value_p);
+ }
+
+ g_strfreev (attributes);
+
+ if (!dbus_message_iter_close_container (&struct_iter, &array_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (iter, &struct_iter))
+ _g_dbus_oom ();
+}
+
+gboolean
+_g_dbus_get_file_attribute (DBusMessageIter *iter,
+ gchar **attribute,
+ GFileAttributeType *type,
+ GDbusAttributeValue *value)
+{
+ char *str;
+ char **strs;
+ int n_elements;
+ DBusMessageIter inner_struct_iter, variant_iter, cstring_iter, obj_iter;
+ const gchar *attribute_temp;
+ dbus_uint32_t obj_type;
+ dbus_bool_t dbus_bool;
+ GObject *obj;
+
+ dbus_message_iter_recurse (iter, &inner_struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_STRING)
+ goto error;
+
+ dbus_message_iter_get_basic (&inner_struct_iter, &attribute_temp);
+ *attribute = g_strdup (attribute_temp);
+
+ dbus_message_iter_next (&inner_struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_VARIANT)
+ goto error;
+
+ dbus_message_iter_recurse (&inner_struct_iter, &variant_iter);
+
+ switch (dbus_message_iter_get_arg_type (&variant_iter))
+ {
+ case DBUS_TYPE_STRING:
+ *type = G_FILE_ATTRIBUTE_TYPE_STRING;
+ dbus_message_iter_get_basic (&variant_iter, &str);
+ value->ptr = g_strdup (str);
+ break;
+ case DBUS_TYPE_ARRAY:
+ if (dbus_message_iter_get_element_type (&variant_iter) != DBUS_TYPE_BYTE)
+ goto error;
+
+ *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
+
+ dbus_message_iter_recurse (&variant_iter, &cstring_iter);
+ dbus_message_iter_get_fixed_array (&cstring_iter,
+ &str, &n_elements);
+ value->ptr = g_strndup (str, n_elements);
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ dbus_message_iter_get_basic (&variant_iter, &dbus_bool);
+ value->boolean = dbus_bool;
+ *type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
+ break;
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_UINT32;
+ break;
+ case DBUS_TYPE_INT32:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_INT32;
+ break;
+ case DBUS_TYPE_UINT64:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_UINT64;
+ break;
+ case DBUS_TYPE_INT64:
+ dbus_message_iter_get_basic (&variant_iter, value);
+ *type = G_FILE_ATTRIBUTE_TYPE_INT64;
+ break;
+ case DBUS_TYPE_STRUCT:
+ dbus_message_iter_recurse (&variant_iter, &obj_iter);
+ if (dbus_message_iter_get_arg_type (&obj_iter) != DBUS_TYPE_UINT32)
+ goto error;
+
+ *type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
+
+ dbus_message_iter_get_basic (&obj_iter, &obj_type);
+ obj = NULL;
+
+ dbus_message_iter_next (&obj_iter);
+ /* 0 == NULL */
+
+ if (obj_type == 1)
+ {
+ /* G_THEMED_ICON */
+ if (_g_dbus_message_iter_get_args (&obj_iter,
+ NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ &strs, &n_elements, 0))
+ {
+ obj = G_OBJECT (g_themed_icon_new_from_names (strs, n_elements));
+ dbus_free_string_array (strs);
+ }
+ }
+ else if (obj_type == 2)
+ {
+ /* G_FILE_ICON, w/ local file */
+ if (_g_dbus_message_iter_get_args (&obj_iter,
+ NULL,
+ G_DBUS_TYPE_CSTRING, &str,
+ 0))
+ {
+ GFile *file = g_file_new_for_path (str);
+ obj = G_OBJECT (g_file_icon_new (file));
+ g_free (str);
+ }
+ }
+ else
+ {
+ /* NULL (or unsupported) */
+ if (obj_type != 0)
+ g_warning ("Unsupported object type in file attribute");
+ }
+
+ value->ptr = obj;
+ break;
+ default:
+ goto error;
+ }
+
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+
+GFileInfo *
+_g_dbus_get_file_info (DBusMessageIter *iter,
+ GError **error)
+{
+ GFileInfo *info;
+ DBusMessageIter struct_iter, array_iter;
+ gchar *attribute;
+ GFileAttributeType type;
+ GDbusAttributeValue value;
+
+ info = g_file_info_new ();
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ goto error;
+
+ dbus_message_iter_recurse (iter, &struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY)
+ goto error;
+
+ dbus_message_iter_recurse (&struct_iter, &array_iter);
+
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ if (!_g_dbus_get_file_attribute (&array_iter, &attribute, &type, &value))
+ goto error;
+
+ g_file_info_set_attribute (info, attribute, type, _g_dbus_attribute_as_pointer (type, &value));
+
+ g_free (attribute);
+ _g_dbus_attribute_value_destroy (type, &value);
+
+ dbus_message_iter_next (&array_iter);
+ }
+
+ dbus_message_iter_next (iter);
+ return info;
+
+ error:
+ g_object_unref (info);
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid file info format"));
+ return NULL;
+}
+
+GFileAttributeInfoList *
+_g_dbus_get_attribute_info_list (DBusMessageIter *iter,
+ GError **error)
+{
+ GFileAttributeInfoList *list;
+ DBusMessageIter array_iter, struct_iter;
+ const char *name;
+ dbus_uint32_t type, flags;
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type (iter) != DBUS_TYPE_STRUCT)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid attribute info list content"));
+ return NULL;
+ }
+
+ list = g_file_attribute_info_list_new ();
+
+ dbus_message_iter_recurse (iter, &array_iter);
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ dbus_message_iter_recurse (&array_iter, &struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_STRING)
+ {
+ dbus_message_iter_get_basic (&struct_iter, &name);
+ dbus_message_iter_next (&struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&struct_iter, &type);
+ dbus_message_iter_next (&struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&struct_iter, &flags);
+
+ g_file_attribute_info_list_add (list, name, type, flags);
+ }
+ }
+ }
+
+ dbus_message_iter_next (&array_iter);
+ }
+
+ return list;
+}
+
+void
+_g_dbus_append_attribute_info_list (DBusMessageIter *iter,
+ GFileAttributeInfoList *list)
+{
+ DBusMessageIter array_iter, struct_iter;
+ int i;
+ dbus_uint32_t dbus_type, dbus_flags;
+
+ if (!dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_TYPE_UINT32_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING,
+ &array_iter))
+ _g_dbus_oom ();
+
+ for (i = 0; i < list->n_infos; i++)
+ {
+ if (!dbus_message_iter_open_container (&array_iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iter))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING, &list->infos[i].name))
+ _g_dbus_oom ();
+
+ dbus_type = list->infos[i].type;
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_UINT32, &dbus_type))
+ _g_dbus_oom ();
+
+ dbus_flags = list->infos[i].flags;
+ if (!dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_UINT32, &dbus_flags))
+ _g_dbus_oom ();
+
+ if (!dbus_message_iter_close_container (&array_iter, &struct_iter))
+ _g_dbus_oom ();
+ }
+
+ if (!dbus_message_iter_close_container (iter, &array_iter))
+ _g_dbus_oom ();
+}
diff --git a/gnome-2-24/common/gvfsdaemonprotocol.h b/gnome-2-24/common/gvfsdaemonprotocol.h
new file mode 100644
index 00000000..0e73c52e
--- /dev/null
+++ b/gnome-2-24/common/gvfsdaemonprotocol.h
@@ -0,0 +1,186 @@
+#ifndef __G_VFS_DAEMON_PROTOCOL_H__
+#define __G_VFS_DAEMON_PROTOCOL_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/* The well known name of the main daemon */
+#define G_VFS_DBUS_DAEMON_NAME "org.gtk.vfs.Daemon"
+
+/* The mount tracking interface in the main daemon */
+#define G_VFS_DBUS_MOUNTTRACKER_INTERFACE "org.gtk.vfs.MountTracker"
+#define G_VFS_DBUS_MOUNTTRACKER_PATH "/org/gtk/vfs/mounttracker"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT "lookupMount"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION "mountLocation"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS "listMounts"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT "registerMount"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_UNREGISTER_MOUNT "unregisterMount"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNT_TYPES "listMountTypes"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO "listMountableInfo"
+#define G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE "registerFuse"
+#define G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED "mounted"
+#define G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED "unmounted"
+
+/* Each mount (there might be several in a daemon) implements one of these interfaces
+ for standard i/o operations */
+#define G_VFS_DBUS_MOUNT_INTERFACE "org.gtk.vfs.Mount"
+#define G_VFS_DBUS_MOUNT_OP_UNMOUNT "Unmount"
+#define G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ "OpenForRead"
+#define G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE "OpenForWrite"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_INFO "QueryInfo"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO "QueryFilesystemInfo"
+#define G_VFS_DBUS_MOUNT_OP_ENUMERATE "Enumerate"
+#define G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR "CreateDirectoryMonitor"
+#define G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR "CreateFileMonitor"
+#define G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE "MountMountable"
+#define G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE "UnountMountable"
+#define G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE "EjectMountable"
+#define G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME "SetDisplayName"
+#define G_VFS_DBUS_MOUNT_OP_DELETE "Delete"
+#define G_VFS_DBUS_MOUNT_OP_TRASH "Trash"
+#define G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY "MakeDirectory"
+#define G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK "MakeSymbolicLink"
+#define G_VFS_DBUS_MOUNT_OP_COPY "Copy"
+#define G_VFS_DBUS_MOUNT_OP_MOVE "Move"
+#define G_VFS_DBUS_MOUNT_OP_PUSH "Push"
+#define G_VFS_DBUS_MOUNT_OP_PULL "Pull"
+#define G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE "SetAttribute"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES "QuerySettableAttributes"
+#define G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES "QueryWritableNamespaces"
+
+/* Progress callback interface for copy and move */
+#define G_VFS_DBUS_PROGRESS_INTERFACE "org.gtk.vfs.Progress"
+#define G_VFS_DBUS_PROGRESS_OP_PROGRESS "Progress"
+
+/* mount daemons that support mounting more mounts implement this,
+ and set the dbus name in the mountable description file */
+#define G_VFS_DBUS_MOUNTABLE_INTERFACE "org.gtk.vfs.Mountable"
+#define G_VFS_DBUS_MOUNTABLE_PATH "/org/gtk/vfs/mountable"
+#define G_VFS_DBUS_MOUNTABLE_OP_MOUNT "mount"
+
+#define G_VFS_DBUS_ERROR_SOCKET_FAILED "org.gtk.vfs.Error.SocketFailed"
+
+/* Each daemon (main and for mounts) implement this. */
+#define G_VFS_DBUS_DAEMON_INTERFACE "org.gtk.vfs.Daemon"
+#define G_VFS_DBUS_DAEMON_PATH "/org/gtk/vfs/Daemon"
+#define G_VFS_DBUS_OP_GET_CONNECTION "GetConnection"
+#define G_VFS_DBUS_OP_CANCEL "Cancel"
+
+/* Used by the dbus-proxying implementation of GMoutOperation */
+#define G_VFS_DBUS_MOUNT_OPERATION_INTERFACE "org.gtk.vfs.MountOperation"
+#define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD "askPassword"
+#define G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION "askQuestion"
+
+/* Implemented by the spawner of a process, the spawned process sends the
+ spawned message (with noreply) when it has spawned and gotten a dbus id */
+#define G_VFS_DBUS_SPAWNER_INTERFACE "org.gtk.vfs.Spawner"
+#define G_VFS_DBUS_OP_SPAWNED "spawned"
+
+/* Implemented by client side for a file enumerator */
+#define G_VFS_DBUS_ENUMERATOR_INTERFACE "org.gtk.vfs.Enumerator"
+#define G_VFS_DBUS_ENUMERATOR_OP_DONE "Done"
+#define G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO "GotInfo"
+
+#define G_VFS_DBUS_MONITOR_INTERFACE "org.gtk.vfs.Monitor"
+#define G_VFS_DBUS_MONITOR_OP_SUBSCRIBE "Subscribe"
+#define G_VFS_DBUS_MONITOR_OP_UNSUBSCRIBE "Unsubscribe"
+
+#define G_VFS_DBUS_MONITOR_CLIENT_INTERFACE "org.gtk.vfs.MonitorClient"
+#define G_VFS_DBUS_MONITOR_CLIENT_OP_CHANGED "Changed"
+
+
+/* Mounts time out in 10 minutes, since they can be slow, with auth, etc */
+#define G_VFS_DBUS_MOUNT_TIMEOUT_MSECS (1000*60*10)
+/* Normal ops are faster, one minute timeout */
+#define G_VFS_DBUS_TIMEOUT_MSECS (1000*60)
+
+typedef struct {
+ guint32 command;
+ guint32 seq_nr;
+ guint32 arg1;
+ guint32 arg2;
+ guint32 data_len;
+} GVfsDaemonSocketProtocolRequest;
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SIZE sizeof(GVfsDaemonSocketProtocolRequest)
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_READ 0
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_WRITE 1
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CLOSE 2
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_CANCEL 3
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_SET 4
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REQUEST_SEEK_END 5
+
+/*
+read, readahead reply:
+type, seek_generation, size, data
+
+seek reply:
+type, pos (64),
+
+error:
+type, code, size, data (size bytes, 2 strings: domain, message)
+*/
+
+typedef struct {
+ guint32 type;
+ guint32 seq_nr;
+ guint32 arg1;
+ guint32 arg2;
+} GVfsDaemonSocketProtocolReply;
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SIZE 16
+
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_DATA 0
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_ERROR 1
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_SEEK_POS 2
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_WRITTEN 3
+#define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED 4
+
+#define G_FILE_INFO_INNER_TYPE_AS_STRING \
+ DBUS_TYPE_ARRAY_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ DBUS_TYPE_STRING_AS_STRING \
+ DBUS_TYPE_VARIANT_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+#define G_FILE_INFO_TYPE_AS_STRING \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ G_FILE_INFO_INNER_TYPE_AS_STRING \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+
+typedef union {
+ gboolean boolean;
+ guint32 uint32;
+ guint64 uint64;
+ gpointer ptr;
+} GDbusAttributeValue;
+
+void _g_dbus_attribute_value_destroy (GFileAttributeType type,
+ GDbusAttributeValue *value);
+gpointer _g_dbus_attribute_as_pointer (GFileAttributeType type,
+ GDbusAttributeValue *value);
+const char*_g_dbus_type_from_file_attribute_type (GFileAttributeType type);
+void _g_dbus_append_file_attribute (DBusMessageIter *iter,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p);
+void _g_dbus_append_file_info (DBusMessageIter *iter,
+ GFileInfo *file_info);
+gboolean _g_dbus_get_file_attribute (DBusMessageIter *iter,
+ gchar **attribute,
+ GFileAttributeType *type,
+ GDbusAttributeValue *value);
+GFileInfo *_g_dbus_get_file_info (DBusMessageIter *iter,
+ GError **error);
+
+GFileAttributeInfoList *_g_dbus_get_attribute_info_list (DBusMessageIter *iter,
+ GError **error);
+void _g_dbus_append_attribute_info_list (DBusMessageIter *iter,
+ GFileAttributeInfoList *list);
+
+G_END_DECLS
+
+#endif /* __G_VFS_DAEMON_PROTOCOL_H__ */