summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am81
-rw-r--r--src/caja-share-bar.c215
-rw-r--r--src/caja-share-bar.h61
-rw-r--r--src/file-share-properties.c688
-rw-r--r--src/http.c481
-rw-r--r--src/http.h27
-rw-r--r--src/marshal.list1
-rw-r--r--src/obexftp.c162
-rw-r--r--src/obexftp.h29
-rw-r--r--src/obexpush.c563
-rw-r--r--src/obexpush.h32
-rw-r--r--src/share-extension.c299
-rw-r--r--src/user_share-common.c89
-rw-r--r--src/user_share-common.h30
-rw-r--r--src/user_share-private.c102
-rw-r--r--src/user_share-private.h57
-rw-r--r--src/user_share.c572
-rw-r--r--src/user_share.h25
18 files changed, 3514 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..90be13d
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,81 @@
+
+MARSHALFILES = marshal.c marshal.h
+BUILT_SOURCES = $(MARSHALFILES)
+
+marshal.c: marshal.h
+ $(AM_V_GEN) ( $(GLIB_GENMARSHAL) --prefix=marshal $(srcdir)/marshal.list --header --body > marshal.c )
+marshal.h: marshal.list
+ $(AM_V_GEN) ( $(GLIB_GENMARSHAL) --prefix=marshal $(srcdir)/marshal.list --header > marshal.h )
+
+
+bin_PROGRAMS= \
+ mate-file-share-properties
+
+libexec_PROGRAMS= \
+ mate-user-share
+
+noinst_LTLIBRARIES = libuser-share-common.la
+libuser_share_common_la_SOURCES = user_share-common.c user_share-common.h
+
+INCLUDES= \
+ -DPREFIX=\""$(prefix)"\" \
+ -DBINDIR=\""$(bindir)"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DUSER_SHARE_PROGRAM=\""$(libexecdir)/mate-user-share"\" \
+ -DMATELOCALEDIR=\""$(datadir)/locale"\" \
+ -DDATADIR=\""$(datadir)/mate-user-share/"\" \
+ -DHTTPD_CONFIG_TEMPLATE=\""$(datadir)/mate-user-share/dav_user_%s.conf"\" \
+ -DHTTPD_PROGRAM=\""$(HTTPD)"\" \
+ -DHTTPD_MODULES_PATH=\""$(MODULES_PATH)"\" \
+ -I$(top_srcdir) \
+ -I$(top_builddir) \
+ $(EXTENSION_CFLAGS) \
+ $(USER_SHARE_CFLAGS) \
+ $(USER_SHARE_CONFIG_CFLAGS) \
+ $(X_CFLAGS)
+
+mate_user_share_SOURCES = \
+ user_share.c \
+ user_share.h \
+ user_share-private.h \
+ user_share-private.c \
+ http.c \
+ http.h \
+ obexftp.c \
+ obexftp.h \
+ obexpush.c \
+ obexpush.h \
+ $(MARSHALFILES)
+
+mate_user_share_LDADD = \
+ libuser-share-common.la \
+ $(USER_SHARE_LIBS) \
+ $(SELINUX_LIBS) \
+ $(X_LIBS) $(X_PRE_LIBS) -lX11 $(X_EXTRA_LIBS)
+
+mate_file_share_properties_SOURCES = \
+ file-share-properties.c \
+ user_share-private.h \
+ user_share-private.c
+
+mate_file_share_properties_LDADD = \
+ $(USER_SHARE_CONFIG_LIBS)
+
+caja_extensiondir = $(CAJADIR)
+caja_extension_LTLIBRARIES = libcaja-share-extension.la
+
+libcaja_share_extension_la_SOURCES = \
+ caja-share-bar.c \
+ caja-share-bar.h \
+ share-extension.c \
+ $(NULL)
+
+libcaja_share_extension_la_LIBADD = libuser-share-common.la $(EXTENSION_LIBS)
+libcaja_share_extension_la_LDFLAGS = -avoid-version -module -no-undefined
+
+EXTRA_DIST = marshal.list
+
+CLEANFILES = $(BUILT_SOURCES)
+
+
+-include $(top_srcdir)/git.mk
diff --git a/src/caja-share-bar.c b/src/caja-share-bar.c
new file mode 100644
index 0000000..8741ac4
--- /dev/null
+++ b/src/caja-share-bar.c
@@ -0,0 +1,215 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: William Jon McCann <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include "caja-share-bar.h"
+
+static void caja_share_bar_finalize (GObject *object);
+
+#define CAJA_SHARE_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CAJA_TYPE_SHARE_BAR, CajaShareBarPrivate))
+
+struct CajaShareBarPrivate
+{
+ GtkWidget *button;
+ GtkWidget *label;
+ char *str;
+};
+
+enum {
+ PROP_0,
+ PROP_LABEL
+};
+
+enum {
+ ACTIVATE,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (CajaShareBar, caja_share_bar, GTK_TYPE_HBOX)
+
+GtkWidget *
+caja_share_bar_get_button (CajaShareBar *bar)
+{
+ GtkWidget *button;
+
+ g_return_val_if_fail (bar != NULL, NULL);
+
+ button = bar->priv->button;
+
+ return button;
+}
+
+static void
+caja_share_bar_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CajaShareBar *self;
+
+ self = CAJA_SHARE_BAR (object);
+
+ switch (prop_id) {
+ case PROP_LABEL: {
+ char *str;
+ g_free (self->priv->str);
+ str = g_strdup_printf ("<i>%s</i>", g_value_get_string (value));
+ gtk_label_set_markup (GTK_LABEL (self->priv->label), str);
+ self->priv->str = g_value_dup_string (value);
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+caja_share_bar_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CajaShareBar *self;
+
+ self = CAJA_SHARE_BAR (object);
+
+ switch (prop_id) {
+ case PROP_LABEL:
+ g_value_set_string (value, self->priv->str);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+caja_share_bar_class_init (CajaShareBarClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = caja_share_bar_finalize;
+ object_class->get_property = caja_share_bar_get_property;
+ object_class->set_property = caja_share_bar_set_property;
+
+ g_type_class_add_private (klass, sizeof (CajaShareBarPrivate));
+
+ g_object_class_install_property (G_OBJECT_CLASS(klass),
+ PROP_LABEL, g_param_spec_string ("label",
+ "label", "The widget's main label", NULL, G_PARAM_READWRITE));
+
+
+ signals [ACTIVATE] = g_signal_new ("activate",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CajaShareBarClass, activate),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+}
+
+static void
+button_clicked_cb (GtkWidget *button,
+ CajaShareBar *bar)
+{
+ g_signal_emit (bar, signals [ACTIVATE], 0);
+}
+
+static void
+caja_share_bar_init (CajaShareBar *bar)
+{
+ GtkWidget *label;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *image;
+ char *hint;
+
+ bar->priv = CAJA_SHARE_BAR_GET_PRIVATE (bar);
+
+ hbox = GTK_WIDGET (bar);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_widget_show (vbox);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+ label = gtk_label_new (_("Personal File Sharing"));
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_widget_show (label);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+
+ bar->priv->label = gtk_label_new ("");
+ hint = g_strdup_printf ("<i>%s</i>", "");
+ gtk_label_set_markup (GTK_LABEL (bar->priv->label), hint);
+ gtk_misc_set_alignment (GTK_MISC (bar->priv->label), 0.0, 0.5);
+ gtk_widget_show (bar->priv->label);
+ gtk_box_pack_start (GTK_BOX (vbox), bar->priv->label, TRUE, TRUE, 0);
+
+ bar->priv->button = gtk_button_new_with_label (_("Launch Preferences"));
+ gtk_widget_show (bar->priv->button);
+ gtk_box_pack_end (GTK_BOX (hbox), bar->priv->button, FALSE, FALSE, 0);
+
+ image = gtk_image_new_from_icon_name ("folder-remote", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image);
+ gtk_button_set_image (GTK_BUTTON (bar->priv->button), image);
+
+ g_signal_connect (bar->priv->button, "clicked",
+ G_CALLBACK (button_clicked_cb),
+ bar);
+
+ gtk_widget_set_tooltip_text (bar->priv->button,
+ _("Launch Personal File Sharing Preferences"));
+}
+
+static void
+caja_share_bar_finalize (GObject *object)
+{
+ CajaShareBar *bar;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CAJA_IS_SHARE_BAR (object));
+
+ bar = CAJA_SHARE_BAR (object);
+
+ g_return_if_fail (bar->priv != NULL);
+
+ G_OBJECT_CLASS (caja_share_bar_parent_class)->finalize (object);
+}
+
+GtkWidget *
+caja_share_bar_new (const char *label)
+{
+ GObject *result;
+
+ result = g_object_new (CAJA_TYPE_SHARE_BAR,
+ "label", label,
+ NULL);
+
+ return GTK_WIDGET (result);
+}
diff --git a/src/caja-share-bar.h b/src/caja-share-bar.h
new file mode 100644
index 0000000..0d3df12
--- /dev/null
+++ b/src/caja-share-bar.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: William Jon McCann <[email protected]>
+ *
+ */
+
+#ifndef __CAJA_SHARE_BAR_H
+#define __CAJA_SHARE_BAR_H
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define CAJA_TYPE_SHARE_BAR (caja_share_bar_get_type ())
+#define CAJA_SHARE_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CAJA_TYPE_SHARE_BAR, CajaShareBar))
+#define CAJA_SHARE_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CAJA_TYPE_SHARE_BAR, CajaShareBarClass))
+#define CAJA_IS_SHARE_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CAJA_TYPE_SHARE_BAR))
+#define CAJA_IS_SHARE_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CAJA_TYPE_SHARE_BAR))
+#define CAJA_SHARE_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CAJA_TYPE_SHARE_BAR, CajaShareBarClass))
+
+typedef struct CajaShareBarPrivate CajaShareBarPrivate;
+
+typedef struct
+{
+ GtkHBox box;
+
+ CajaShareBarPrivate *priv;
+} CajaShareBar;
+
+typedef struct
+{
+ GtkHBoxClass parent_class;
+
+ void (* activate) (CajaShareBar *bar);
+
+} CajaShareBarClass;
+
+GType caja_share_bar_get_type (void);
+GtkWidget *caja_share_bar_new (const char *label);
+
+GtkWidget *caja_share_bar_get_button (CajaShareBar *bar);
+
+G_END_DECLS
+
+#endif /* __GS_SHARE_BAR_H */
diff --git a/src/file-share-properties.c b/src/file-share-properties.c
new file mode 100644
index 0000000..d46958f
--- /dev/null
+++ b/src/file-share-properties.c
@@ -0,0 +1,688 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <mateconf/mateconf-client.h>
+#include <unique/uniqueapp.h>
+
+#include "user_share-private.h"
+
+#define REALM "Please log in as the user guest"
+#define USER "guest"
+
+static GtkBuilder* builder;
+
+
+static void
+write_out_password (const char *password)
+{
+ char *to_hash;
+ char *ascii_digest;
+ char *line;
+ char *filename;
+ FILE *file;
+
+ to_hash = g_strdup_printf ("%s:%s:%s", USER, REALM, password);
+ ascii_digest = g_compute_checksum_for_string (G_CHECKSUM_MD5, to_hash, strlen (to_hash));
+ g_free (to_hash);
+ line = g_strdup_printf ("%s:%s:%s\n", USER, REALM, ascii_digest);
+ g_free (ascii_digest);
+
+ filename = g_build_filename (g_get_user_config_dir (), "user-share", "passwd", NULL);
+
+ file = fopen (filename, "w");
+ if (file != NULL) {
+ fwrite (line, strlen (line), 1, file);
+ fclose (file);
+ }
+
+ g_free (filename);
+ g_free (line);
+}
+
+static void
+flush_password (void)
+{
+ GtkWidget *password_entry;
+ const char *password;
+
+ password_entry = GTK_WIDGET (gtk_builder_get_object (builder, "password_entry"));
+
+ if (g_object_get_data (G_OBJECT( password_entry), "user_edited")) {
+ password = gtk_entry_get_text (GTK_ENTRY (password_entry));
+ if (password != NULL && password[0] != 0)
+ write_out_password (password);
+ }
+}
+
+
+static void
+update_ui (void)
+{
+ MateConfClient *client;
+ gboolean enabled, bluetooth_enabled, bluetooth_write_enabled, require_pairing_enabled;
+ gboolean bluetooth_obexpush_enabled, bluetooth_obexpush_notify;
+ char *str;
+ PasswordSetting password_setting;
+ AcceptSetting accept_setting;
+ GtkWidget *check;
+ GtkWidget *password_combo;
+ GtkWidget *password_entry;
+ GtkWidget *bluetooth_check;
+ GtkWidget *allow_write_bluetooth_check;
+ GtkWidget *require_pairing_check;
+ GtkWidget *enable_obexpush_check;
+ GtkWidget *accept_obexpush_combo;
+ GtkWidget *notify_received_obexpush_check;
+
+ client = mateconf_client_get_default ();
+
+ enabled = mateconf_client_get_bool (client,
+ FILE_SHARING_ENABLED,
+ NULL);
+ bluetooth_enabled = mateconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_ENABLED,
+ NULL);
+ bluetooth_write_enabled = mateconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ NULL);
+ require_pairing_enabled = mateconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_REQUIRE_PAIRING,
+ NULL);
+ bluetooth_obexpush_enabled = mateconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED,
+ NULL);
+ bluetooth_obexpush_notify = mateconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_NOTIFY,
+ NULL);
+
+ str = mateconf_client_get_string (client, FILE_SHARING_REQUIRE_PASSWORD, NULL);
+ password_setting = password_setting_from_string (str);
+ g_free (str);
+
+ str = mateconf_client_get_string (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_ACCEPT_FILES, NULL);
+ accept_setting = accept_setting_from_string (str);
+ g_free (str);
+
+ check = GTK_WIDGET (gtk_builder_get_object (builder, "enable_check"));
+ password_combo = GTK_WIDGET (gtk_builder_get_object (builder, "password_combo"));
+ password_entry = GTK_WIDGET (gtk_builder_get_object (builder, "password_entry"));
+ bluetooth_check = GTK_WIDGET (gtk_builder_get_object (builder, "enable_bluetooth_check"));
+ allow_write_bluetooth_check = GTK_WIDGET (gtk_builder_get_object (builder, "allow_write_bluetooth_check"));
+ require_pairing_check = GTK_WIDGET (gtk_builder_get_object (builder, "require_pairing_check"));
+ enable_obexpush_check = GTK_WIDGET (gtk_builder_get_object (builder, "enable_obexpush_check"));
+ accept_obexpush_combo = GTK_WIDGET (gtk_builder_get_object (builder, "accept_obexpush_combo"));
+ notify_received_obexpush_check = GTK_WIDGET (gtk_builder_get_object (builder, "notify_received_obexpush_check"));
+
+ /* Network */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), enabled);
+ gtk_widget_set_sensitive (password_combo, enabled);
+ gtk_widget_set_sensitive (password_entry, enabled && password_setting != PASSWORD_NEVER);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (password_combo),
+ password_setting);
+
+ /* Bluetooth ObexFTP */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bluetooth_check), bluetooth_enabled);
+ gtk_widget_set_sensitive (allow_write_bluetooth_check, bluetooth_enabled);
+ gtk_widget_set_sensitive (require_pairing_check, bluetooth_enabled);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (allow_write_bluetooth_check),
+ bluetooth_write_enabled);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (require_pairing_check),
+ require_pairing_enabled);
+
+ /* Bluetooth ObexPush */
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (enable_obexpush_check), bluetooth_obexpush_enabled);
+ gtk_widget_set_sensitive (accept_obexpush_combo, bluetooth_obexpush_enabled);
+ gtk_widget_set_sensitive (notify_received_obexpush_check, bluetooth_obexpush_enabled);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (notify_received_obexpush_check),
+ bluetooth_obexpush_notify);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (accept_obexpush_combo),
+ accept_setting);
+
+ g_object_unref (client);
+}
+
+static void
+file_sharing_enabled_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+password_required_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+file_sharing_bluetooth_enabled_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+file_sharing_bluetooth_allow_write_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+file_sharing_bluetooth_require_pairing_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+file_sharing_bluetooth_obexpush_enabled_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+file_sharing_bluetooth_obexpush_accept_files_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+file_sharing_bluetooth_obexpush_notify_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+password_combo_changed (GtkComboBox *combo_box)
+{
+ MateConfClient *client;
+ guint setting;
+
+ setting = gtk_combo_box_get_active (combo_box);
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_string (client,
+ FILE_SHARING_REQUIRE_PASSWORD,
+ password_string_from_setting (setting),
+ NULL);
+ g_object_unref (client);
+}
+
+static void
+launch_share (void)
+{
+ char *argv[2];
+ int i;
+
+ i = 0;
+ argv[i++] = USER_SHARE_PROGRAM;
+ argv[i++] = NULL;
+
+ if (!g_spawn_async (NULL,
+ argv,
+ NULL,
+ 0, /* G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL */
+ NULL,
+ NULL,
+ NULL,
+ NULL)) {
+ g_warning ("Unable to start mate-user-share program");
+ }
+}
+
+static void
+enable_bluetooth_check_toggled (GtkWidget *check)
+{
+ MateConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_bool (client,
+ FILE_SHARING_BLUETOOTH_ENABLED,
+ enabled,
+ NULL);
+
+ g_object_unref (client);
+
+ if (enabled != FALSE)
+ launch_share ();
+}
+
+static void
+enable_check_toggled (GtkWidget *check)
+{
+ MateConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_bool (client,
+ FILE_SHARING_ENABLED,
+ enabled,
+ NULL);
+
+ g_object_unref (client);
+
+ if (enabled != FALSE)
+ launch_share ();
+}
+
+static void
+password_entry_changed (GtkEditable *editable)
+{
+ g_object_set_data (G_OBJECT (editable),
+ "user_edited", GINT_TO_POINTER (1));
+ flush_password ();
+}
+
+static void
+bluetooth_allow_write_check_toggled (GtkWidget *check)
+{
+ MateConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_bool (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ enabled,
+ NULL);
+
+ g_object_unref (client);
+}
+
+static void
+bluetooth_require_pairing_check_toggled (GtkWidget *check)
+{
+ MateConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_bool (client,
+ FILE_SHARING_BLUETOOTH_REQUIRE_PAIRING,
+ enabled,
+ NULL);
+
+ g_object_unref (client);
+}
+
+static void
+enable_obexpush_check_toggled (GtkWidget *check)
+{
+ MateConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_bool (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED,
+ enabled,
+ NULL);
+
+ g_object_unref (client);
+
+ if (enabled != FALSE)
+ launch_share ();
+}
+
+static void
+accept_obexpush_combo_changed (GtkComboBox *combo_box)
+{
+ MateConfClient *client;
+ guint setting;
+
+ setting = gtk_combo_box_get_active (combo_box);
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_string (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ACCEPT_FILES,
+ accept_string_from_setting (setting),
+ NULL);
+ g_object_unref (client);
+}
+
+static void
+notify_received_obexpush_check_toggled (GtkWidget *check)
+{
+ MateConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = mateconf_client_get_default ();
+
+ mateconf_client_set_bool (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_NOTIFY,
+ enabled,
+ NULL);
+
+ g_object_unref (client);
+}
+
+static GtkWidget *
+error_dialog (const char *title,
+ const char *reason,
+ GtkWindow *parent)
+{
+ GtkWidget *error_dialog;
+
+ if (reason == NULL)
+ reason = _("No reason");
+
+ error_dialog =
+ gtk_message_dialog_new (parent,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", title);
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (error_dialog), "%s", reason);
+
+ gtk_window_set_title (GTK_WINDOW (error_dialog), ""); /* as per HIG */
+ gtk_container_set_border_width (GTK_CONTAINER (error_dialog), 5);
+ gtk_dialog_set_default_response (GTK_DIALOG (error_dialog),
+ GTK_RESPONSE_OK);
+ gtk_window_set_modal (GTK_WINDOW (error_dialog), TRUE);
+
+ return error_dialog;
+}
+
+static void
+help_button_clicked (GtkButton *button, GtkWidget *window)
+{
+ GError *error = NULL;
+
+ if (gtk_show_uri (gtk_widget_get_screen (window), "ghelp:mate-user-share", gtk_get_current_event_time (), &error) == FALSE) {
+ GtkWidget *dialog;
+
+ dialog = error_dialog (_("Could not display the help contents."), error->message, GTK_WINDOW (window));
+ g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK
+ (gtk_widget_destroy), error_dialog);
+ gtk_window_present (GTK_WINDOW (dialog));
+
+ g_error_free (error);
+ }
+}
+
+static UniqueResponse
+message_received_cb (UniqueApp *app,
+ int command,
+ UniqueMessageData *message_data,
+ guint time_,
+ gpointer user_data)
+{
+ gtk_window_present (GTK_WINDOW (user_data));
+
+ return UNIQUE_RESPONSE_OK;
+}
+
+int
+main (int argc, char *argv[])
+{
+ GError *error = NULL;
+ MateConfClient *client;
+ GtkWidget *check;
+ GtkWidget *password_combo;
+ GtkWidget *password_entry;
+ GtkWidget *bluetooth_check;
+ GtkWidget *bluetooth_allow_write_check;
+ GtkWidget *require_pairing_check;
+ GtkWidget *enable_obexpush_check;
+ GtkWidget *accept_obexpush_combo;
+ GtkWidget *notify_received_obexpush_check;
+ GtkWidget *window;
+ GtkListStore *store;
+ GtkCellRenderer *cell;
+ GtkTreeIter iter;
+ UniqueApp *app;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init (&argc, &argv);
+
+ app = unique_app_new ("org.mate.user-share.properties", NULL);
+ if (unique_app_is_running (app)) {
+ gdk_notify_startup_complete ();
+ unique_app_send_message (app, UNIQUE_ACTIVATE, NULL);
+ return 0;
+ }
+
+ builder = gtk_builder_new ();
+ gtk_builder_add_from_file (builder, DATADIR"file-share-properties.ui", &error);
+
+ if (error) {
+ GtkWidget *dialog;
+
+ dialog = error_dialog (_("Could not build interface."), error->message, NULL);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ g_error_free (error);
+ return 1;
+ }
+
+ window = GTK_WIDGET (gtk_builder_get_object (builder, "user_share_dialog"));
+ g_signal_connect (G_OBJECT (window), "delete_event",
+ G_CALLBACK (gtk_main_quit), NULL);
+ g_signal_connect (app, "message-received",
+ G_CALLBACK (message_received_cb), window);
+
+ client = mateconf_client_get_default ();
+ mateconf_client_add_dir (client,
+ FILE_SHARING_DIR,
+ MATECONF_CLIENT_PRELOAD_RECURSIVE,
+ NULL);
+
+ check = GTK_WIDGET (gtk_builder_get_object (builder, "enable_check"));
+ password_combo = GTK_WIDGET (gtk_builder_get_object (builder, "password_combo"));
+ password_entry = GTK_WIDGET (gtk_builder_get_object (builder, "password_entry"));
+ bluetooth_check = GTK_WIDGET (gtk_builder_get_object (builder, "enable_bluetooth_check"));
+ bluetooth_allow_write_check = GTK_WIDGET (gtk_builder_get_object (builder, "allow_write_bluetooth_check"));
+ require_pairing_check = GTK_WIDGET (gtk_builder_get_object (builder, "require_pairing_check"));
+ enable_obexpush_check = GTK_WIDGET (gtk_builder_get_object (builder, "enable_obexpush_check"));
+ accept_obexpush_combo = GTK_WIDGET (gtk_builder_get_object (builder, "accept_obexpush_combo"));
+ notify_received_obexpush_check = GTK_WIDGET (gtk_builder_get_object (builder, "notify_received_obexpush_check"));
+
+ store = gtk_list_store_new (1, G_TYPE_STRING);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (password_combo),
+ GTK_TREE_MODEL (store));
+ cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (password_combo), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (password_combo), cell,
+ "text", 0,
+ NULL);
+
+ /* Keep in same order as enum */
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0,
+ _("Never"), -1);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0,
+ _("When writing files"), -1);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0,
+ _("Always"), -1);
+ g_object_unref (store);
+
+ /* We can't read the password from the text, just set it to something */
+ gtk_entry_set_text (GTK_ENTRY (password_entry), "none");
+ g_object_set_data (G_OBJECT (password_entry),
+ "user_edited", GINT_TO_POINTER (0));
+ g_signal_connect (password_entry,
+ "changed", G_CALLBACK (password_entry_changed), NULL);
+
+ /* Accept files combo */
+ store = gtk_list_store_new (1, G_TYPE_STRING);
+ gtk_combo_box_set_model (GTK_COMBO_BOX (accept_obexpush_combo),
+ GTK_TREE_MODEL (store));
+ cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (accept_obexpush_combo), cell, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (accept_obexpush_combo), cell,
+ "text", 0,
+ NULL);
+
+ /* Keep in same order as enum */
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0,
+ _("Always"), -1);
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0,
+ _("Only for set up devices"), -1);
+ //FIXME implement
+#if 0
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter, 0,
+ _("Ask"), -1);
+#endif
+ g_object_unref (store);
+
+ update_ui ();
+
+ g_signal_connect (check,
+ "toggled", G_CALLBACK (enable_check_toggled), NULL);
+ g_signal_connect (password_combo,
+ "changed", G_CALLBACK (password_combo_changed), NULL);
+ g_signal_connect (bluetooth_check,
+ "toggled", G_CALLBACK (enable_bluetooth_check_toggled), NULL);
+ g_signal_connect (bluetooth_allow_write_check,
+ "toggled", G_CALLBACK (bluetooth_allow_write_check_toggled), NULL);
+ g_signal_connect (require_pairing_check,
+ "toggled", G_CALLBACK (bluetooth_require_pairing_check_toggled), NULL);
+ g_signal_connect (enable_obexpush_check,
+ "toggled", G_CALLBACK (enable_obexpush_check_toggled), NULL);
+ g_signal_connect (accept_obexpush_combo,
+ "changed", G_CALLBACK (accept_obexpush_combo_changed), NULL);
+ g_signal_connect (notify_received_obexpush_check,
+ "toggled", G_CALLBACK (notify_received_obexpush_check_toggled), NULL);
+
+ g_signal_connect (GTK_WIDGET (gtk_builder_get_object (builder, "close_button")),
+ "clicked", G_CALLBACK (gtk_main_quit), NULL);
+ g_signal_connect (GTK_WIDGET (gtk_builder_get_object (builder, "help_button")),
+ "clicked", G_CALLBACK (help_button_clicked),
+ gtk_builder_get_object (builder, "user_share_dialog"));
+
+ mateconf_client_notify_add (client,
+ FILE_SHARING_ENABLED,
+ file_sharing_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_REQUIRE_PASSWORD,
+ password_required_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ENABLED,
+ file_sharing_bluetooth_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ file_sharing_bluetooth_allow_write_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_REQUIRE_PAIRING,
+ file_sharing_bluetooth_require_pairing_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED,
+ file_sharing_bluetooth_obexpush_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ACCEPT_FILES,
+ file_sharing_bluetooth_obexpush_accept_files_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_NOTIFY,
+ file_sharing_bluetooth_obexpush_notify_changed,
+ NULL,
+ NULL,
+ NULL);
+
+ g_object_unref (client);
+
+ gtk_widget_show (GTK_WIDGET (gtk_builder_get_object (builder, "user_share_dialog")));
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/src/http.c b/src/http.c
new file mode 100644
index 0000000..64d4706
--- /dev/null
+++ b/src/http.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <X11/Xlib.h>
+
+#ifdef HAVE_DBUS_1_1
+#include <dbus/dbus.h>
+#endif
+
+#include <mateconf/mateconf-client.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#endif
+
+#include "user_share-common.h"
+#include "user_share-private.h"
+#include "http.h"
+
+/* From avahi-common/domain.h */
+#define AVAHI_LABEL_MAX 64
+
+#ifdef HAVE_DBUS_1_1
+static char *dbus_session_id;
+#endif
+
+static pid_t httpd_pid = 0;
+
+static int
+get_port (void)
+{
+ int sock;
+ struct sockaddr_in addr;
+ int reuse;
+ socklen_t len;
+
+ sock = socket (PF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ return -1;
+ }
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sin_port = 0;
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ reuse = 1;
+ setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse));
+ if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) == -1) {
+ close (sock);
+ return -1;
+ }
+
+ len = sizeof (addr);
+ if (getsockname (sock, (struct sockaddr *)&addr, &len) == -1) {
+ close (sock);
+ return -1;
+ }
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
+ /* XXX This exposes a potential race condition, but without this,
+ * httpd will not start on the above listed platforms due to the fact
+ * that SO_REUSEADDR is also needed when Apache binds to the listening
+ * socket. At this time, Apache does not support that socket option.
+ */
+ close (sock);
+#endif
+ return ntohs (addr.sin_port);
+}
+
+static char *
+truncate_name (const char *name)
+{
+ const char *end;
+
+ end = g_utf8_find_prev_char (name, name + 64);
+ g_assert (end != NULL);
+ return g_strndup (name, end - name);
+}
+
+static char *
+get_share_name (void)
+{
+ static char *name = NULL;
+ const char *host_name;
+ char *str;
+
+ if (name == NULL) {
+ host_name = g_get_host_name ();
+ if (strcmp (host_name, "localhost") == 0) {
+ /* Translators: The %s will get filled in with the user name
+ of the user, to form a genitive. If this is difficult to
+ translate correctly so that it will work correctly in your
+ language, you may use something equivalent to
+ "Public files of %s", or leave out the %s altogether.
+ In the latter case, please put "%.0s" somewhere in the string,
+ which will match the user name string passed by the C code,
+ but not put the user name in the final string. This is to
+ avoid the warning that msgfmt might otherwise generate. */
+ name = g_strdup_printf (_("%s's public files"), g_get_user_name ());
+ } else {
+ /* Translators: This is similar to the string before, only it
+ has the hostname in it too. */
+ name = g_strdup_printf (_("%s's public files on %s"),
+ g_get_user_name (),
+ host_name);
+ }
+
+ }
+ /* And truncate */
+ if (strlen (name) < AVAHI_LABEL_MAX)
+ return name;
+
+ str = truncate_name (name);
+ g_free (name);
+ name = str;
+
+ return name;
+}
+
+#ifdef HAVE_DBUS_1_1
+static void
+init_dbus() {
+ /* The only use we make of D-BUS is to fetch the session BUS ID so we can export
+ * it via mDNS, so we connect and then immediately disconnect. If we were using
+ * the D-BUS session BUS for something persistent, the following code should use
+ * dbus_bus_get() and skip the shutdown. (Avahi uses the D-BUS _system_ bus
+ * internally.)
+ */
+
+ DBusError derror;
+ DBusConnection *connection;
+
+ dbus_error_init(&derror);
+
+ connection = dbus_bus_get_private(DBUS_BUS_SESSION, &derror);
+ if (connection == NULL) {
+ g_printerr("Failed to connect to session bus: %s", derror.message);
+ dbus_error_free(&derror);
+ return;
+ }
+
+ dbus_session_id = dbus_bus_get_id(connection, &derror);
+ if (dbus_session_id == NULL) {
+ /* This can happen if the D-BUS library has been upgraded to 1.1, but the
+ * user's session hasn't yet been restarted
+ */
+ g_printerr("Failed to get session BUS ID: %s", derror.message);
+ dbus_error_free(&derror);
+ }
+
+ dbus_connection_set_exit_on_disconnect(connection, FALSE);
+ dbus_connection_close(connection);
+ dbus_connection_unref(connection);
+}
+#endif
+
+static void
+ensure_conf_dir (void)
+{
+ char *dirname;
+
+ dirname = g_build_filename (g_get_user_config_dir (), "user-share", NULL);
+ g_mkdir_with_parents (dirname, 0755);
+ g_free (dirname);
+}
+
+static void
+httpd_child_setup (gpointer user_data)
+{
+#ifdef HAVE_SELINUX
+ char *mycon;
+ /* If selinux is enabled, avoid transitioning to the httpd_t context,
+ as this normally means you can't read the users homedir. */
+ if (is_selinux_enabled()) {
+ if (getcon (&mycon) < 0) {
+ abort ();
+ }
+ if (setexeccon (mycon) < 0)
+ abort ();
+ freecon (mycon);
+ }
+#endif
+}
+
+static const char *known_httpd_locations [] = {
+ HTTPD_PROGRAM,
+ "/usr/sbin/httpd",
+ "/usr/sbin/httpd2",
+ "/usr/sbin/apache2",
+ NULL
+};
+
+static char*
+get_httpd_program ()
+{
+ int i;
+
+ for (i = 0; known_httpd_locations[i]; i++) {
+ if (known_httpd_locations[i][0] == '\0') {
+ /* empty string as first element, happens when
+ * configured --with-httpd=auto */
+ continue;
+ }
+ if (g_file_test (known_httpd_locations[i], G_FILE_TEST_IS_EXECUTABLE)
+ && ! g_file_test (known_httpd_locations[i], G_FILE_TEST_IS_DIR)) {
+ return g_strdup (known_httpd_locations[i]);
+ }
+ }
+ return NULL;
+}
+
+static const char *known_httpd_modules_locations [] = {
+ HTTPD_MODULES_PATH,
+ "/etc/httpd/modules",
+ "/usr/lib/apache2/modules",
+ NULL
+};
+
+static gchar*
+get_httpd_modules_path ()
+{
+ int i;
+
+ for (i = 0; known_httpd_modules_locations[i]; i++) {
+ if (known_httpd_modules_locations[i][0] == '\0') {
+ /* empty string as first element, happens when
+ * configured --with-httpd=auto */
+ continue;
+ }
+ if (g_file_test (known_httpd_modules_locations[i], G_FILE_TEST_IS_EXECUTABLE)
+ && g_file_test (known_httpd_modules_locations[i], G_FILE_TEST_IS_DIR)) {
+ return g_strdup (known_httpd_modules_locations[i]);
+ }
+ }
+ return NULL;
+}
+
+static GRegex *version_regex = NULL;
+
+static char*
+get_httpd_config (const char *httpd_program)
+{
+ gchar *standard_output;
+ gchar *cmd_line;
+ GMatchInfo *match_info;
+ gchar *version_number = NULL;
+ gchar *config;
+
+ cmd_line = g_strdup_printf ("%s -v", httpd_program);
+ if (! g_spawn_command_line_sync (cmd_line, &standard_output, NULL, NULL, NULL)) {
+ g_free (cmd_line);
+ return NULL;
+ }
+ g_free (cmd_line);
+
+ if (version_regex == NULL) {
+ version_regex = g_regex_new ("\\d\\.\\d", 0, 0, NULL);
+ }
+
+ if (g_regex_match (version_regex, standard_output, 0, &match_info)) {
+ while (g_match_info_matches (match_info)) {
+ version_number = g_match_info_fetch (match_info, 0);
+ break;
+ }
+ g_match_info_free (match_info);
+ g_free (standard_output);
+ } else {
+ /* Failed to parse httpd version number */
+ g_warning ("Could not parse '%s' as a version for httpd", standard_output);
+ g_free (standard_output);
+ /* assume it is 2.2 */
+ version_number = g_strdup ("2.2");
+ }
+
+ config = g_strdup_printf (HTTPD_CONFIG_TEMPLATE, version_number);
+ g_free (version_number);
+
+ return config;
+}
+
+static gboolean
+spawn_httpd (int port, pid_t *pid_out)
+{
+ char *free1, *free2, *free3, *free4, *free5, *free6, *free7, *free8, *free9;
+ gboolean res;
+ char *argv[10];
+ char *env[10];
+ int i;
+ gint status;
+ char *pid_filename;
+ char *pidfile;
+ GError *error;
+ gboolean got_pidfile;
+ MateConfClient *client;
+ char *str;
+ char *public_dir;
+
+ public_dir = lookup_public_dir ();
+ ensure_conf_dir ();
+
+ i = 0;
+ free1 = argv[i++] = get_httpd_program ();
+ if (argv[0] == NULL) {
+ fprintf (stderr, "error finding httpd server\n");
+ return FALSE;
+ }
+
+ argv[i++] = "-f";
+ free2 = argv[i++] = get_httpd_config (argv[0]);
+ argv[i++] = "-C";
+ free3 = argv[i++] = g_strdup_printf ("Listen %d", port);
+
+ client = mateconf_client_get_default ();
+ str = mateconf_client_get_string (client,
+ FILE_SHARING_REQUIRE_PASSWORD, NULL);
+
+ if (str && strcmp (str, "never") == 0) {
+ /* Do nothing */
+ } else if (str && strcmp (str, "on_write") == 0){
+ argv[i++] = "-D";
+ argv[i++] = "RequirePasswordOnWrite";
+ } else {
+ /* always, or safe fallback */
+ argv[i++] = "-D";
+ argv[i++] = "RequirePasswordAlways";
+ }
+ g_free (str);
+ g_object_unref (client);
+
+ argv[i] = NULL;
+
+ i = 0;
+ free4 = env[i++] = g_strdup_printf ("HOME=%s", g_get_home_dir());
+ free5 = env[i++] = g_strdup_printf ("XDG_PUBLICSHARE_DIR=%s", public_dir);
+ free6 = env[i++] = g_strdup_printf ("XDG_CONFIG_HOME=%s", g_get_user_config_dir ());
+ free7 = env[i++] = g_strdup_printf ("GUS_SHARE_NAME=%s", get_share_name ());
+ free8 = env[i++] = g_strdup_printf ("GUS_LOGIN_LABEL=%s", "Please log in as the user guest");
+ free9 = env[i++] = g_strdup_printf ("HTTP_MODULES_PATH=%s",get_httpd_modules_path ());
+ env[i++] = "LANG=C";
+ env[i] = NULL;
+
+ pid_filename = g_build_filename (g_get_user_config_dir (), "user-share", "pid", NULL);
+
+ /* Remove pid file before spawning to avoid races with child and old pidfile */
+ unlink (pid_filename);
+
+ error = NULL;
+ res = g_spawn_sync (g_get_home_dir(),
+ argv, env, 0,
+ httpd_child_setup, NULL,
+ NULL, NULL,
+ &status,
+ &error);
+ g_free (free1);
+ g_free (free2);
+ g_free (free3);
+ g_free (free4);
+ g_free (free5);
+ g_free (free6);
+ g_free (free7);
+ g_free (free8);
+ g_free (free9);
+ g_free (public_dir);
+
+ if (!res) {
+ fprintf (stderr, "error spawning httpd: %s\n",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ if (status != 0) {
+ g_free (pid_filename);
+ return FALSE;
+ }
+
+ got_pidfile = FALSE;
+ error = NULL;
+ for (i = 0; i < 5; i++) {
+ if (error != NULL)
+ g_error_free (error);
+ error = NULL;
+ if (g_file_get_contents (pid_filename, &pidfile, NULL, &error)) {
+ got_pidfile = TRUE;
+ *pid_out = atoi (pidfile);
+ g_free (pidfile);
+ break;
+ }
+ sleep (1);
+ }
+
+ g_free (pid_filename);
+
+ if (!got_pidfile) {
+ fprintf (stderr, "error opening httpd pidfile: %s\n", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+kill_httpd (void)
+{
+ if (httpd_pid != 0) {
+ kill (httpd_pid, SIGTERM);
+
+ /* Allow child time to die, we can't waitpid, because its
+ not a direct child */
+ sleep (1);
+ }
+ httpd_pid = 0;
+}
+
+void
+http_up (void)
+{
+ guint port;
+
+ port = get_port ();
+ if (!spawn_httpd (port, &httpd_pid)) {
+ fprintf (stderr, "spawning httpd failed\n");
+ }
+}
+
+void
+http_down (void)
+{
+ kill_httpd ();
+}
+
+gboolean
+http_init (void)
+{
+#ifdef HAVE_DBUS_1_1
+ init_dbus();
+#endif
+
+ return TRUE;
+}
+
+pid_t
+http_get_pid (void)
+{
+ return httpd_pid;
+}
diff --git a/src/http.h b/src/http.h
new file mode 100644
index 0000000..b3ea42b
--- /dev/null
+++ b/src/http.h
@@ -0,0 +1,27 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ *
+ */
+
+void http_up (void);
+void http_down (void);
+gboolean http_init (void);
+pid_t http_get_pid (void);
diff --git a/src/marshal.list b/src/marshal.list
new file mode 100644
index 0000000..05bd165
--- /dev/null
+++ b/src/marshal.list
@@ -0,0 +1 @@
+VOID:STRING,STRING,UINT64
diff --git a/src/obexftp.c b/src/obexftp.c
new file mode 100644
index 0000000..6d94c97
--- /dev/null
+++ b/src/obexftp.c
@@ -0,0 +1,162 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Bastien Nocera <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <mateconf/mateconf-client.h>
+
+#include <string.h>
+
+#include "obexftp.h"
+#include "user_share-common.h"
+#include "user_share-private.h"
+
+static DBusGConnection *connection = NULL;
+static DBusGProxy *manager_proxy = NULL;
+static DBusGProxy *server_proxy = NULL;
+
+void
+obexftp_up (void)
+{
+ GError *err = NULL;
+ MateConfClient *client;
+ char *public_dir, *server;
+ gboolean allow_write, require_pairing;
+
+ client = mateconf_client_get_default ();
+ require_pairing = mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_REQUIRE_PAIRING, NULL);
+
+ server = NULL;
+ if (manager_proxy == NULL) {
+ manager_proxy = dbus_g_proxy_new_for_name (connection,
+ "org.openobex",
+ "/org/openobex",
+ "org.openobex.Manager");
+ if (dbus_g_proxy_call (manager_proxy, "CreateBluetoothServer",
+ &err, G_TYPE_STRING, "00:00:00:00:00:00", G_TYPE_STRING, "ftp", G_TYPE_BOOLEAN, require_pairing, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &server, G_TYPE_INVALID) == FALSE) {
+ g_printerr ("Creating Bluetooth ObexFTP server failed: %s\n",
+ err->message);
+ g_error_free (err);
+ g_object_unref (manager_proxy);
+ manager_proxy = NULL;
+ return;
+ }
+ }
+
+ public_dir = lookup_public_dir ();
+ allow_write = mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ALLOW_WRITE, NULL);
+ g_object_unref (client);
+
+ if (server_proxy == NULL) {
+ server_proxy = dbus_g_proxy_new_for_name (connection,
+ "org.openobex",
+ server,
+ "org.openobex.Server");
+ g_free (server);
+ }
+ if (dbus_g_proxy_call (server_proxy, "Start", &err,
+ G_TYPE_STRING, public_dir, G_TYPE_BOOLEAN, allow_write, G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE) {
+ if (g_error_matches (err, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION) != FALSE &&
+ dbus_g_error_has_name (err, "org.openobex.Error.Started") != FALSE) {
+ g_error_free (err);
+ g_message ("already started, ignoring error");
+ g_free (public_dir);
+ return;
+ }
+ g_printerr ("Starting Bluetooth ObexFTP server failed: %s\n",
+ err->message);
+ g_error_free (err);
+ g_free (public_dir);
+ g_object_unref (server_proxy);
+ server_proxy = NULL;
+ g_object_unref (manager_proxy);
+ manager_proxy = NULL;
+ return;
+ }
+
+ g_free (public_dir);
+}
+
+static void
+obexftp_stop (gboolean stop_manager)
+{
+ GError *err = NULL;
+
+ if (server_proxy == NULL)
+ return;
+
+ if (dbus_g_proxy_call (server_proxy, "Close", &err, G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
+ if (err == NULL ||
+ g_error_matches (err, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION) == FALSE ||
+ dbus_g_error_has_name (err, "org.openobex.Error.NotStarted") == FALSE) {
+ if (err != NULL) {
+ g_printerr ("Stopping Bluetooth ObexFTP server failed: %s\n",
+ err->message);
+ g_error_free (err);
+ }
+ return;
+ }
+ g_error_free (err);
+ }
+
+ if (stop_manager != FALSE) {
+ g_object_unref (server_proxy);
+ server_proxy = NULL;
+ g_object_unref (manager_proxy);
+ manager_proxy = NULL;
+ }
+}
+
+void
+obexftp_down (void)
+{
+ obexftp_stop (TRUE);
+}
+
+void
+obexftp_restart (void)
+{
+ obexftp_stop (FALSE);
+ obexftp_up ();
+}
+
+gboolean
+obexftp_init (void)
+{
+ GError *err = NULL;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
+ if (connection == NULL) {
+ g_printerr ("Connecting to session bus failed: %s\n",
+ err->message);
+ g_error_free (err);
+ return FALSE;
+ }
+
+ dbus_connection_set_exit_on_disconnect (dbus_g_connection_get_connection (connection), FALSE);
+ return TRUE;
+}
diff --git a/src/obexftp.h b/src/obexftp.h
new file mode 100644
index 0000000..c199fd1
--- /dev/null
+++ b/src/obexftp.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Bastien Nocera <[email protected]>
+ *
+ */
+
+#include <glib.h>
+
+void obexftp_up (void);
+void obexftp_down (void);
+void obexftp_restart (void);
+gboolean obexftp_init (void);
diff --git a/src/obexpush.c b/src/obexpush.c
new file mode 100644
index 0000000..c7cb725
--- /dev/null
+++ b/src/obexpush.c
@@ -0,0 +1,563 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Bastien Nocera <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+#include <libmatenotify/notify.h>
+#include <dbus/dbus-glib.h>
+#include <mateconf/mateconf-client.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <canberra-gtk.h>
+
+#include <string.h>
+
+#include "marshal.h"
+#include "obexpush.h"
+#include "user_share.h"
+#include "user_share-private.h"
+
+#define DBUS_TYPE_G_STRING_VARIANT_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
+
+static DBusGConnection *connection = NULL;
+static DBusGProxy *manager_proxy = NULL;
+static DBusGProxy *server_proxy = NULL;
+static AcceptSetting accept_setting = -1;
+static gboolean show_notifications = FALSE;
+
+static GtkStatusIcon *statusicon = NULL;
+static guint num_notifications = 0;
+
+static void
+hide_statusicon (void)
+{
+ num_notifications--;
+ if (num_notifications == 0)
+ gtk_status_icon_set_visible (statusicon, FALSE);
+}
+
+static void
+on_close_notification (NotifyNotification *notification)
+{
+ hide_statusicon ();
+ g_object_unref (notification);
+}
+
+static void
+notification_launch_action_on_file_cb (NotifyNotification *notification,
+ const char *action,
+ const char *file_uri)
+{
+ GdkScreen *screen;
+ GAppLaunchContext *ctx;
+ GTimeVal val;
+
+ g_assert (action != NULL);
+
+ g_get_current_time (&val);
+
+#if GTK_CHECK_VERSION(2,14,0)
+ ctx = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ());
+ screen = gdk_screen_get_default ();
+ gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (ctx), screen);
+ gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (ctx), val.tv_sec);
+#else
+ ctx = NULL;
+ screen = NULL;
+#endif
+
+ /* We launch the file viewer for the file */
+ if (g_str_equal (action, "display") != FALSE) {
+ if (g_app_info_launch_default_for_uri (file_uri, ctx, NULL) == FALSE) {
+ g_warning ("Failed to launch the file viewer\n");
+ }
+ }
+
+ /* we open the Downloads folder */
+ if (g_str_equal (action, "reveal") != FALSE) {
+ GFile *file;
+ GFile *parent;
+ gchar *parent_uri;
+
+ file = g_file_new_for_uri (file_uri);
+ parent = g_file_get_parent (file);
+ parent_uri = g_file_get_uri (parent);
+ g_object_unref (file);
+ g_object_unref (parent);
+
+ if (!g_app_info_launch_default_for_uri (parent_uri, ctx, NULL)) {
+ g_warning ("Failed to launch the file manager\n");
+ }
+
+ g_free (parent_uri);
+ }
+
+ notify_notification_close (notification, NULL);
+ /* No need to call hide_statusicon(), closing the notification
+ * will call the close callback */
+}
+
+static void
+show_notification (const char *filename)
+{
+ char *file_uri, *notification_text, *display, *mime_type;
+ NotifyNotification *notification;
+ ca_context *ctx;
+ GAppInfo *app;
+
+ file_uri = g_filename_to_uri (filename, NULL, NULL);
+ if (file_uri == NULL) {
+ g_warning ("Could not make a filename from '%s'", filename);
+ return;
+ }
+
+ display = g_filename_display_basename (filename);
+ /* Translators: %s is the name of the filename received */
+ notification_text = g_strdup_printf(_("You received \"%s\" via Bluetooth"), display);
+ g_free (display);
+ notification = notify_notification_new (_("You received a file"),
+ notification_text,
+ "dialog-information");
+
+ notify_notification_set_timeout (notification, NOTIFY_EXPIRES_DEFAULT);
+
+ mime_type = g_content_type_guess (filename, NULL, 0, NULL);
+ app = g_app_info_get_default_for_type (mime_type, FALSE);
+ if (app != NULL) {
+ g_object_unref (app);
+ notify_notification_add_action (notification, "display", _("Open File"),
+ (NotifyActionCallback) notification_launch_action_on_file_cb,
+ g_strdup (file_uri), (GFreeFunc) g_free);
+ }
+ notify_notification_add_action (notification, "reveal", _("Reveal File"),
+ (NotifyActionCallback) notification_launch_action_on_file_cb,
+ g_strdup (file_uri), (GFreeFunc) g_free);
+
+ g_free (file_uri);
+
+ g_signal_connect (G_OBJECT (notification), "closed", G_CALLBACK (on_close_notification), notification);
+
+ if (!notify_notification_show (notification, NULL)) {
+ g_warning ("failed to send notification\n");
+ }
+ g_free (notification_text);
+
+ /* Now we do the audio notification */
+ ctx = ca_gtk_context_get ();
+ ca_context_play (ctx, 0,
+ CA_PROP_EVENT_ID, "complete-download",
+ CA_PROP_EVENT_DESCRIPTION, _("File reception complete"),
+ NULL);
+}
+
+static void
+show_icon (void)
+{
+ if (statusicon == NULL) {
+ statusicon = gtk_status_icon_new_from_icon_name ("mate-obex-server");
+ } else {
+ gtk_status_icon_set_visible (statusicon, TRUE);
+ }
+ num_notifications++;
+}
+
+static gboolean
+device_is_authorised (const char *bdaddr)
+{
+ DBusGConnection *connection;
+ DBusGProxy *manager;
+ GError *error = NULL;
+ GPtrArray *adapters;
+ gboolean retval = FALSE;
+ guint i;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+ if (connection == NULL)
+ return FALSE;
+
+ manager = dbus_g_proxy_new_for_name (connection, "org.bluez",
+ "/", "org.bluez.Manager");
+ if (manager == NULL) {
+ dbus_g_connection_unref (connection);
+ return FALSE;
+ }
+
+ if (dbus_g_proxy_call (manager, "ListAdapters", &error, G_TYPE_INVALID, dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &adapters, G_TYPE_INVALID) == FALSE) {
+ g_object_unref (manager);
+ dbus_g_connection_unref (connection);
+ return FALSE;
+ }
+
+ for (i = 0; i < adapters->len; i++) {
+ DBusGProxy *adapter, *device;
+ char *device_path;
+ GHashTable *props;
+
+ g_message ("checking adapter %s", g_ptr_array_index (adapters, i));
+
+ adapter = dbus_g_proxy_new_for_name (connection, "org.bluez",
+ g_ptr_array_index (adapters, i), "org.bluez.Adapter");
+
+ if (dbus_g_proxy_call (adapter, "FindDevice", NULL,
+ G_TYPE_STRING, bdaddr, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &device_path, G_TYPE_INVALID) == FALSE)
+ {
+ g_object_unref (adapter);
+ continue;
+ }
+
+ device = dbus_g_proxy_new_for_name (connection, "org.bluez", device_path, "org.bluez.Device");
+
+ if (dbus_g_proxy_call (device, "GetProperties", NULL,
+ G_TYPE_INVALID, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+ &props, G_TYPE_INVALID) != FALSE)
+ {
+ GValue *value;
+ gboolean bonded;
+
+ value = g_hash_table_lookup (props, "Paired");
+ bonded = g_value_get_boolean (value);
+ g_message ("%s is %s", bdaddr, bonded ? "bonded" : "not bonded");
+
+ if (bonded) {
+ g_hash_table_destroy (props);
+ g_object_unref (device);
+ g_object_unref (adapter);
+ retval = TRUE;
+ break;
+ }
+ }
+ g_object_unref(adapter);
+ }
+
+ g_ptr_array_free (adapters, TRUE);
+
+ g_object_unref(manager);
+ dbus_g_connection_unref(connection);
+
+ return retval;
+}
+
+static void
+transfer_started_cb (DBusGProxy *session,
+ const char *filename,
+ const char *local_path,
+ guint64 size,
+ gpointer user_data)
+{
+ GHashTable *dict;
+ DBusGProxy *server = (DBusGProxy *) user_data;
+ GError *error = NULL;
+ gboolean authorise;
+
+ g_message ("transfer started on %s", local_path);
+ g_object_set_data_full (G_OBJECT (session), "filename", g_strdup (local_path), (GDestroyNotify) g_free);
+
+ show_icon ();
+
+ /* First transfer of the session */
+ if (g_object_get_data (G_OBJECT (session), "bdaddr") == NULL) {
+ const char *bdaddr;
+
+ if (dbus_g_proxy_call (server, "GetServerSessionInfo", &error,
+ DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (session), G_TYPE_INVALID,
+ DBUS_TYPE_G_STRING_VARIANT_HASHTABLE, &dict, G_TYPE_INVALID) == FALSE) {
+ g_printerr ("Getting Server session info failed: %s\n",
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+ bdaddr = g_hash_table_lookup (dict, "BluetoothAddress");
+ g_message ("transfer started for device %s", bdaddr);
+
+ g_object_set_data_full (G_OBJECT (session), "bdaddr", g_strdup (bdaddr), (GDestroyNotify) g_free);
+ /* Initial accept method is undefined, we do that lower down */
+ g_object_set_data (G_OBJECT (session), "accept-method", GINT_TO_POINTER (-1));
+ g_hash_table_destroy (dict);
+ }
+
+ /* Accept method changed */
+ if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), "accept-method")) != accept_setting) {
+ const char *bdaddr;
+
+ bdaddr = g_object_get_data (G_OBJECT (session), "bdaddr");
+
+ if (bdaddr == NULL) {
+ g_warning ("Couldn't get the Bluetooth address for the device, rejecting the transfer");
+ authorise = FALSE;
+ } else if (accept_setting == ACCEPT_ALWAYS) {
+ authorise = TRUE;
+ } else if (accept_setting == ACCEPT_BONDED) {
+ authorise = device_is_authorised (bdaddr);
+ } else {
+ //FIXME implement
+ g_warning ("\"Ask\" authorisation method not implemented");
+ authorise = FALSE;
+ }
+ g_object_set_data (G_OBJECT (session), "authorise", GINT_TO_POINTER (authorise));
+ }
+
+ g_message ("accept_setting: %d", accept_setting);
+
+ authorise = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), "authorise"));
+ if (authorise != FALSE) {
+ if (dbus_g_proxy_call (session, "Accept", &error, G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
+ g_printerr ("Failed to accept file transfer: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+ g_message ("authorised transfer");
+ } else {
+ if (dbus_g_proxy_call (session, "Reject", &error, G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
+ g_printerr ("Failed to reject file transfer: %s\n", error->message);
+ g_error_free (error);
+ return;
+ }
+ g_message ("rejected transfer");
+ g_object_set_data (G_OBJECT (session), "filename", NULL);
+ }
+}
+
+static void
+transfer_completed_cb (DBusGProxy *session,
+ gpointer user_data)
+{
+ MateConfClient *client;
+ gboolean display_notify;
+ const char *filename;
+
+ filename = (const char *) g_object_get_data (G_OBJECT (session), "filename");
+
+ g_message ("file finish transfer: %s", filename);
+
+ if (filename == NULL)
+ return;
+
+ client = mateconf_client_get_default ();
+ display_notify = mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_NOTIFY, NULL);
+ g_object_unref (client);
+
+ if (display_notify) {
+ show_notification (filename);
+ } else {
+ hide_statusicon ();
+ }
+ g_object_set_data (G_OBJECT (session), "filename", NULL);
+}
+
+static void
+cancelled_cb (DBusGProxy *session,
+ gpointer user_data)
+{
+ //FIXME implement properly, we never actually finished the transfer
+ g_message ("transfered was cancelled by the sender");
+ transfer_completed_cb (session, user_data);
+ hide_statusicon ();
+}
+
+static void
+error_occurred_cb (DBusGProxy *session,
+ const char *error_name,
+ const char *error_message,
+ gpointer user_data)
+{
+ //FIXME implement properly
+ g_message ("transfer error occurred: %s", error_message);
+ transfer_completed_cb (session, user_data);
+}
+
+static void
+session_created_cb (DBusGProxy *server, const char *session_path, gpointer user_data)
+{
+ DBusGProxy *session;
+
+ session = dbus_g_proxy_new_for_name (connection,
+ "org.openobex",
+ session_path,
+ "org.openobex.ServerSession");
+
+ dbus_g_proxy_add_signal (session, "TransferStarted",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(session, "TransferStarted",
+ G_CALLBACK (transfer_started_cb), server, NULL);
+ dbus_g_proxy_add_signal (session, "TransferCompleted",
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(session, "TransferCompleted",
+ G_CALLBACK (transfer_completed_cb), server, NULL);
+ dbus_g_proxy_add_signal (session, "Cancelled",
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(session, "Cancelled",
+ G_CALLBACK (cancelled_cb), server, NULL);
+ dbus_g_proxy_add_signal (session, "ErrorOccurred",
+ G_TYPE_INVALID, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(session, "ErrorOccurred",
+ G_CALLBACK (error_occurred_cb), server, NULL);
+}
+
+void
+obexpush_up (void)
+{
+ GError *err = NULL;
+ char *download_dir, *server;
+
+ server = NULL;
+ if (manager_proxy == NULL) {
+ manager_proxy = dbus_g_proxy_new_for_name (connection,
+ "org.openobex",
+ "/org/openobex",
+ "org.openobex.Manager");
+ if (dbus_g_proxy_call (manager_proxy, "CreateBluetoothServer",
+ &err, G_TYPE_STRING, "00:00:00:00:00:00", G_TYPE_STRING, "opp", G_TYPE_BOOLEAN, FALSE, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &server, G_TYPE_INVALID) == FALSE) {
+ g_printerr ("Creating Bluetooth ObexPush server failed: %s\n",
+ err->message);
+ g_error_free (err);
+ g_object_unref (manager_proxy);
+ manager_proxy = NULL;
+ return;
+ }
+ }
+
+ download_dir = lookup_download_dir ();
+
+ if (server_proxy == NULL) {
+ server_proxy = dbus_g_proxy_new_for_name (connection,
+ "org.openobex",
+ server,
+ "org.openobex.Server");
+ g_free (server);
+
+ dbus_g_proxy_add_signal (server_proxy, "SessionCreated",
+ DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(server_proxy, "SessionCreated",
+ G_CALLBACK (session_created_cb), NULL, NULL);
+ }
+
+ if (dbus_g_proxy_call (server_proxy, "Start", &err,
+ G_TYPE_STRING, download_dir, G_TYPE_BOOLEAN, TRUE, G_TYPE_BOOLEAN, FALSE, G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE) {
+ if (g_error_matches (err, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION) != FALSE &&
+ dbus_g_error_has_name (err, "org.openobex.Error.Started") != FALSE) {
+ g_error_free (err);
+ g_message ("already started, ignoring error");
+ g_free (download_dir);
+ return;
+ }
+ g_printerr ("Starting Bluetooth ObexPush server failed: %s\n",
+ err->message);
+ g_error_free (err);
+ g_free (download_dir);
+ g_object_unref (server_proxy);
+ server_proxy = NULL;
+ g_object_unref (manager_proxy);
+ manager_proxy = NULL;
+ return;
+ }
+
+ g_free (download_dir);
+}
+
+static void
+obexpush_stop (gboolean stop_manager)
+{
+ GError *err = NULL;
+
+ if (server_proxy == NULL)
+ return;
+
+ if (dbus_g_proxy_call (server_proxy, "Close", &err, G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
+ if (g_error_matches (err, DBUS_GERROR, DBUS_GERROR_REMOTE_EXCEPTION) == FALSE ||
+ dbus_g_error_has_name (err, "org.openobex.Error.NotStarted") == FALSE) {
+ g_printerr ("Stopping Bluetooth ObexPush server failed: %s\n",
+ err->message);
+ g_error_free (err);
+ return;
+ }
+ g_error_free (err);
+ }
+
+ if (stop_manager != FALSE) {
+ g_object_unref (server_proxy);
+ server_proxy = NULL;
+ g_object_unref (manager_proxy);
+ manager_proxy = NULL;
+ }
+
+ //FIXME stop all the notifications
+}
+
+void
+obexpush_down (void)
+{
+ obexpush_stop (TRUE);
+}
+
+void
+obexpush_restart (void)
+{
+ obexpush_stop (FALSE);
+ obexpush_up ();
+}
+
+gboolean
+obexpush_init (void)
+{
+ GError *err = NULL;
+
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
+ if (connection == NULL) {
+ g_printerr ("Connecting to session bus failed: %s\n",
+ err->message);
+ g_error_free (err);
+ return FALSE;
+ }
+
+ dbus_g_object_register_marshaller (marshal_VOID__STRING_STRING_UINT64,
+ G_TYPE_NONE,
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
+
+ if (!notify_init("mate-user-share")) {
+ g_warning("Unable to initialize the notification system\n");
+ }
+
+ dbus_connection_set_exit_on_disconnect (dbus_g_connection_get_connection (connection), FALSE);
+
+ return TRUE;
+}
+
+void
+obexpush_set_accept_files_policy (AcceptSetting setting)
+{
+ accept_setting = setting;
+}
+
+void
+obexpush_set_notify (gboolean enabled)
+{
+ show_notifications = enabled;
+}
diff --git a/src/obexpush.h b/src/obexpush.h
new file mode 100644
index 0000000..3ac624c
--- /dev/null
+++ b/src/obexpush.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Bastien Nocera <[email protected]>
+ *
+ */
+
+#include <glib.h>
+#include "user_share-private.h"
+
+void obexpush_up (void);
+void obexpush_down (void);
+void obexpush_restart (void);
+gboolean obexpush_init (void);
+void obexpush_set_accept_files_policy (AcceptSetting accept_setting);
+void obexpush_set_notify (gboolean enabled);
diff --git a/src/share-extension.c b/src/share-extension.c
new file mode 100644
index 0000000..59aead6
--- /dev/null
+++ b/src/share-extension.c
@@ -0,0 +1,299 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ * Copyright (C) 2003 Novell, Inc.
+ * Copyright (C) 2003-2004 Red Hat, Inc.
+ * Copyright (C) 2005 William Jon McCann <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <libcaja-extension/caja-menu-provider.h>
+#include <libcaja-extension/caja-location-widget-provider.h>
+
+#include "caja-share-bar.h"
+#include "user_share-common.h"
+
+#define CAJA_TYPE_USER_SHARE (caja_user_share_get_type ())
+#define CAJA_USER_SHARE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CAJA_TYPE_USER_SHARE, CajaUserShare))
+#define CAJA_IS_USER_SHARE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CAJA_TYPE_USER_SHARE))
+
+typedef struct _CajaUserSharePrivate CajaUserSharePrivate;
+
+typedef struct
+{
+ GObject parent_slot;
+ CajaUserSharePrivate *priv;
+} CajaUserShare;
+
+typedef struct
+{
+ GObjectClass parent_slot;
+} CajaUserShareClass;
+
+#define CAJA_USER_SHARE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CAJA_TYPE_USER_SHARE, CajaUserSharePrivate))
+
+struct _CajaUserSharePrivate
+{
+ GSList *widget_list;
+};
+
+static GType caja_user_share_get_type (void);
+static void caja_user_share_register_type (GTypeModule *module);
+
+static GObjectClass *parent_class;
+
+
+static void
+launch_process (char **argv, GtkWindow *parent)
+{
+ GError *error;
+ GtkWidget *dialog;
+
+ error = NULL;
+ if (!g_spawn_async (NULL,
+ argv, NULL,
+ 0,
+ NULL, NULL,
+ NULL,
+ &error)) {
+
+
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK, _("Unable to launch the Personal File Sharing preferences"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ g_error_free (error);
+ }
+}
+
+static void
+launch_prefs_on_window (GtkWindow *window)
+{
+ char *argv [2];
+
+ argv [0] = g_build_filename (BINDIR, "mate-file-share-properties", NULL);
+ argv [1] = NULL;
+
+ launch_process (argv, window);
+
+ g_free (argv [0]);
+}
+
+static void
+bar_activated_cb (CajaShareBar *bar,
+ gpointer data)
+{
+ launch_prefs_on_window (GTK_WINDOW (data));
+}
+
+static void
+destroyed_callback (GtkWidget *widget,
+ CajaUserShare *share)
+{
+ share->priv->widget_list = g_slist_remove (share->priv->widget_list, widget);
+}
+
+static void
+add_widget (CajaUserShare *share,
+ GtkWidget *widget)
+{
+ share->priv->widget_list = g_slist_prepend (share->priv->widget_list, widget);
+
+ g_signal_connect (widget, "destroy",
+ G_CALLBACK (destroyed_callback),
+ share);
+}
+
+static GtkWidget *
+caja_user_share_get_location_widget (CajaLocationWidgetProvider *iface,
+ const char *uri,
+ GtkWidget *window)
+{
+ GFile *file;
+ GtkWidget *bar;
+ CajaUserShare *share;
+ guint i;
+ gboolean enable = FALSE;
+ GFile *home;
+ const GUserDirectory special_dirs[] = { G_USER_DIRECTORY_PUBLIC_SHARE, G_USER_DIRECTORY_DOWNLOAD };
+ gboolean is_dir[] = { FALSE, FALSE };
+
+ file = g_file_new_for_uri (uri);
+ home = g_file_new_for_path (g_get_home_dir ());
+
+ /* We don't show anything in $HOME */
+ if (g_file_equal (home, file)) {
+ g_object_unref (home);
+ g_object_unref (file);
+ return NULL;
+ }
+
+ g_object_unref (home);
+
+ for (i = 0; i < G_N_ELEMENTS (special_dirs); i++) {
+ GFile *dir;
+ dir = lookup_dir_with_fallback (special_dirs[i]);
+ if (g_file_equal (dir, file)) {
+ enable = TRUE;
+ is_dir[i] = TRUE;
+ }
+ g_object_unref (dir);
+ }
+
+ if (enable == FALSE)
+ return NULL;
+
+ share = CAJA_USER_SHARE (iface);
+
+ if (is_dir[0] != FALSE && is_dir[1] != FALSE) {
+ bar = caja_share_bar_new (_("You can share files from this folder and receive files to it"));
+ } else if (is_dir[0] != FALSE) {
+ bar = caja_share_bar_new (_("You can share files from this folder over the network and Bluetooth"));
+ } else {
+ bar = caja_share_bar_new (_("You can receive files over Bluetooth into this folder"));
+ }
+
+ add_widget (share, caja_share_bar_get_button (CAJA_SHARE_BAR (bar)));
+
+ g_signal_connect (bar, "activate",
+ G_CALLBACK (bar_activated_cb),
+ window);
+
+ gtk_widget_show (bar);
+
+ g_object_unref (file);
+
+ return bar;
+}
+
+static void
+caja_user_share_location_widget_provider_iface_init (CajaLocationWidgetProviderIface *iface)
+{
+ iface->get_widget = caja_user_share_get_location_widget;
+}
+
+static void
+caja_user_share_instance_init (CajaUserShare *share)
+{
+ share->priv = CAJA_USER_SHARE_GET_PRIVATE (share);
+}
+
+static void
+caja_user_share_finalize (GObject *object)
+{
+ CajaUserShare *share;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CAJA_IS_USER_SHARE (object));
+
+ share = CAJA_USER_SHARE (object);
+
+ g_return_if_fail (share->priv != NULL);
+
+ if (share->priv->widget_list != NULL) {
+ g_slist_free (share->priv->widget_list);
+ }
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+caja_user_share_class_init (CajaUserShareClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = caja_user_share_finalize;
+
+ g_type_class_add_private (klass, sizeof (CajaUserSharePrivate));
+}
+
+static GType share_type = 0;
+
+static GType
+caja_user_share_get_type (void)
+{
+ return share_type;
+}
+
+static void
+caja_user_share_register_type (GTypeModule *module)
+{
+ static const GTypeInfo info = {
+ sizeof (CajaUserShareClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) caja_user_share_class_init,
+ NULL,
+ NULL,
+ sizeof (CajaUserShare),
+ 0,
+ (GInstanceInitFunc) caja_user_share_instance_init,
+ };
+
+ static const GInterfaceInfo location_widget_provider_iface_info = {
+ (GInterfaceInitFunc) caja_user_share_location_widget_provider_iface_init,
+ NULL,
+ NULL
+ };
+
+ share_type = g_type_module_register_type (module,
+ G_TYPE_OBJECT,
+ "CajaUserShare",
+ &info, 0);
+
+ g_type_module_add_interface (module,
+ share_type,
+ CAJA_TYPE_LOCATION_WIDGET_PROVIDER,
+ &location_widget_provider_iface_info);
+}
+
+void
+caja_module_initialize (GTypeModule *module)
+{
+ caja_user_share_register_type (module);
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+}
+
+void
+caja_module_shutdown (void)
+{
+}
+
+void
+caja_module_list_types (const GType **types,
+ int *num_types)
+{
+ static GType type_list [1];
+
+ type_list[0] = CAJA_TYPE_USER_SHARE;
+
+ *types = type_list;
+ *num_types = 1;
+}
diff --git a/src/user_share-common.c b/src/user_share-common.c
new file mode 100644
index 0000000..ae2fd2c
--- /dev/null
+++ b/src/user_share-common.c
@@ -0,0 +1,89 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2009 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ * Bastien Nocera <[email protected]>
+ *
+ */
+
+#include "user_share-common.h"
+
+static char *
+lookup_special_dir (GUserDirectory directory,
+ const char *name,
+ gboolean create_dir)
+{
+ const char *special_dir;
+ char *dir;
+
+ special_dir = g_get_user_special_dir (directory);
+ if (special_dir != NULL && strcmp (special_dir, g_get_home_dir ()) != 0) {
+ if (create_dir != FALSE)
+ g_mkdir_with_parents (special_dir, 0755);
+ return g_strdup (special_dir);
+ }
+
+ dir = g_build_filename (g_get_home_dir (), name, NULL);
+ if (create_dir != FALSE)
+ g_mkdir_with_parents (dir, 0755);
+ return dir;
+}
+
+char *
+lookup_public_dir (void)
+{
+ return lookup_special_dir (G_USER_DIRECTORY_PUBLIC_SHARE,
+ "Public",
+ TRUE);
+}
+
+char *
+lookup_download_dir (void)
+{
+ return lookup_special_dir (G_USER_DIRECTORY_DOWNLOAD,
+ "Downloads",
+ TRUE);
+}
+
+GFile *
+lookup_dir_with_fallback (GUserDirectory directory)
+{
+ GFile *file;
+ char *path;
+ const char *name;
+
+ if (directory == G_USER_DIRECTORY_PUBLIC_SHARE)
+ name = "Public";
+ else if (directory == G_USER_DIRECTORY_DOWNLOAD)
+ name = "Downloads";
+ else
+ g_assert_not_reached ();
+
+ path = lookup_special_dir (directory,
+ name,
+ FALSE);
+
+ if (path == NULL)
+ return NULL;
+
+ file = g_file_new_for_path (path);
+ g_free (path);
+
+ return file;
+}
diff --git a/src/user_share-common.h b/src/user_share-common.h
new file mode 100644
index 0000000..d2895ad
--- /dev/null
+++ b/src/user_share-common.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2009 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ * Bastien Nocera <[email protected]>
+ *
+ */
+
+#include <glib.h>
+#include <gio/gio.h>
+
+char *lookup_public_dir (void);
+char *lookup_download_dir (void);
+GFile *lookup_dir_with_fallback (GUserDirectory directory);
diff --git a/src/user_share-private.c b/src/user_share-private.c
new file mode 100644
index 0000000..4ffd12e
--- /dev/null
+++ b/src/user_share-private.c
@@ -0,0 +1,102 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ * Bastien Nocera <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "user_share-private.h"
+
+static char *password_setting_strings[] = {
+ "never",
+ "on_write",
+ "always"
+};
+
+static char *accept_file_strings[] = {
+ "always",
+ "bonded",
+ "ask"
+};
+
+const char *
+password_string_from_setting (PasswordSetting setting)
+{
+
+ if (setting >= 0 && setting <= PASSWORD_ALWAYS)
+ return password_setting_strings[setting];
+
+ /* Fallback on secure pref */
+ return password_setting_strings[PASSWORD_ALWAYS];
+}
+
+PasswordSetting
+password_setting_from_string (const char *str)
+{
+ if (str != NULL) {
+ if (strcmp (str, "never") == 0) {
+ return PASSWORD_NEVER;
+ }
+ if (strcmp (str, "always") == 0) {
+ return PASSWORD_ALWAYS;
+ }
+ if (strcmp (str, "on_write") == 0) {
+ return PASSWORD_ON_WRITE;
+ }
+ }
+
+ /* Fallback on secure pref */
+ return PASSWORD_ALWAYS;
+}
+
+const char *
+accept_string_from_setting (AcceptSetting setting)
+{
+
+ if (setting >= 0 && setting <= ACCEPT_ASK)
+ return accept_file_strings[setting];
+
+ /* Fallback on secure pref */
+ return accept_file_strings[ACCEPT_BONDED];
+}
+
+AcceptSetting
+accept_setting_from_string (const char *str)
+{
+ if (str != NULL) {
+ if (strcmp (str, "always") == 0) {
+ return ACCEPT_ALWAYS;
+ }
+ if (strcmp (str, "bonded") == 0 ||
+ strcmp (str, "bonded_and_trusted") == 0) {
+ return ACCEPT_BONDED;
+ }
+ if (strcmp (str, "ask") == 0) {
+ return ACCEPT_ASK;
+ }
+ }
+
+ /* Fallback on secure pref */
+ return ACCEPT_BONDED;
+}
diff --git a/src/user_share-private.h b/src/user_share-private.h
new file mode 100644
index 0000000..4ce936c
--- /dev/null
+++ b/src/user_share-private.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ * Bastien Nocera <[email protected]>
+ *
+ */
+
+#ifndef _USER_SHARE_PRIVATE_H_
+#define _USER_SHARE_PRIVATE_H_
+
+#define FILE_SHARING_DIR "/desktop/mate/file_sharing"
+#define FILE_SHARING_ENABLED FILE_SHARING_DIR "/enabled"
+#define FILE_SHARING_BLUETOOTH_ENABLED FILE_SHARING_DIR "/bluetooth_enabled"
+#define FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED FILE_SHARING_DIR "/bluetooth_obexpush_enabled"
+
+#define FILE_SHARING_REQUIRE_PASSWORD FILE_SHARING_DIR "/require_password"
+#define FILE_SHARING_BLUETOOTH_ALLOW_WRITE FILE_SHARING_DIR "/bluetooth_allow_write"
+#define FILE_SHARING_BLUETOOTH_REQUIRE_PAIRING FILE_SHARING_DIR "/bluetooth_require_pairing"
+#define FILE_SHARING_BLUETOOTH_OBEXPUSH_ACCEPT_FILES FILE_SHARING_DIR "/bluetooth_accept_files"
+#define FILE_SHARING_BLUETOOTH_OBEXPUSH_NOTIFY FILE_SHARING_DIR "/bluetooth_notify"
+
+typedef enum {
+ PASSWORD_NEVER,
+ PASSWORD_ON_WRITE,
+ PASSWORD_ALWAYS
+} PasswordSetting;
+
+typedef enum {
+ ACCEPT_ALWAYS,
+ ACCEPT_BONDED,
+ ACCEPT_ASK
+} AcceptSetting;
+
+const char *password_string_from_setting (PasswordSetting setting);
+PasswordSetting password_setting_from_string (const char *str);
+
+const char *accept_string_from_setting (AcceptSetting setting);
+AcceptSetting accept_setting_from_string (const char *str);
+
+#endif /* _USER_SHARE_PRIVATE_H_ */
diff --git a/src/user_share.c b/src/user_share.c
new file mode 100644
index 0000000..e55863a
--- /dev/null
+++ b/src/user_share.c
@@ -0,0 +1,572 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ *
+ */
+
+#include "config.h"
+
+#include <gdk/gdkx.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <bluetooth-client.h>
+#include <X11/Xlib.h>
+
+#include "user_share.h"
+#include "user_share-private.h"
+#include "user_share-common.h"
+#include "http.h"
+#include "obexftp.h"
+#include "obexpush.h"
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include <mateconf/mateconf-client.h>
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+/* ConsoleKit */
+#define CK_NAME "org.freedesktop.ConsoleKit"
+#define CK_INTERFACE "org.freedesktop.ConsoleKit"
+#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
+#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+
+static guint disabled_timeout_tag = 0;
+static gboolean has_console = TRUE;
+
+static BluetoothClient *client = NULL;
+static gboolean bluetoothd_enabled = FALSE;
+
+#define OBEX_ENABLED (bluetoothd_enabled && has_console)
+
+static void
+obex_services_start (void)
+{
+ MateConfClient *client;
+
+ if (bluetoothd_enabled == FALSE ||
+ has_console == FALSE)
+ return;
+
+ client = mateconf_client_get_default ();
+
+ if (mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED, NULL) == TRUE) {
+ obexpush_up ();
+ }
+ if (mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ENABLED, NULL) == TRUE) {
+ obexftp_up ();
+ }
+
+ g_object_unref (client);
+}
+
+static void
+obex_services_shutdown (void)
+{
+ obexpush_down ();
+ obexftp_down ();
+}
+
+static void
+sessionchanged_cb (void)
+{
+ DBusGConnection *dbus_connection;
+ DBusGProxy *proxy_ck_manager;
+ DBusGProxy *proxy_ck_session;
+
+ gchar *ck_session_path;
+ gboolean is_active = FALSE;
+ GError *error = NULL;
+
+ g_message ("Active session changed");
+
+ dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (!dbus_connection) {
+ g_warning ("Unable to connect to dbus");
+ dbus_g_connection_unref (dbus_connection);
+ return;
+ }
+
+ proxy_ck_manager = dbus_g_proxy_new_for_name (dbus_connection,
+ CK_NAME,
+ CK_MANAGER_PATH,
+ CK_MANAGER_INTERFACE);
+ if (dbus_g_proxy_call (proxy_ck_manager, "GetCurrentSession",
+ &error, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &ck_session_path,
+ G_TYPE_INVALID) == FALSE) {
+ g_warning ("Couldn't request the name: %s", error->message);
+ dbus_g_connection_unref (dbus_connection);
+ g_object_unref (proxy_ck_manager);
+ g_error_free (error);
+ return;
+ }
+
+ proxy_ck_session = dbus_g_proxy_new_for_name (dbus_connection,
+ CK_NAME,
+ ck_session_path,
+ CK_SESSION_INTERFACE);
+
+ if (dbus_g_proxy_call (proxy_ck_session, "IsActive",
+ &error, G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &is_active,
+ G_TYPE_INVALID) == FALSE) {
+
+ g_warning ("Couldn't request the name: %s", error->message);
+ dbus_g_connection_unref (dbus_connection);
+ g_object_unref (proxy_ck_manager);
+ g_object_unref (proxy_ck_session);
+ g_error_free (error);
+ return;
+ }
+
+ has_console = is_active;
+ if (is_active) {
+ obex_services_start ();
+ } else {
+ obex_services_shutdown ();
+ }
+
+ dbus_g_connection_unref (dbus_connection);
+ g_free (ck_session_path);
+ g_object_unref (proxy_ck_manager);
+ g_object_unref (proxy_ck_session);
+ if (error != NULL) {
+ g_error_free (error);
+ }
+}
+
+static void
+consolekit_init (void)
+{
+ DBusGConnection *dbus_connection;
+ DBusGProxy *proxy_ck_manager;
+ DBusGProxy *proxy_ck_session;
+ DBusGProxy *proxy_ck_seat;
+ gchar *ck_session_path;
+ gchar *ck_seat_path;
+ GError *error = NULL;
+
+ dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+
+ if (!dbus_connection) {
+ g_warning ("Unable to connect to dbus");
+ dbus_g_connection_unref (dbus_connection);
+ return;
+ }
+
+ proxy_ck_manager = dbus_g_proxy_new_for_name (dbus_connection,
+ CK_NAME,
+ CK_MANAGER_PATH,
+ CK_MANAGER_INTERFACE);
+ if (dbus_g_proxy_call (proxy_ck_manager, "GetCurrentSession",
+ &error, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &ck_session_path,
+ G_TYPE_INVALID) == FALSE) {
+
+ g_warning ("Couldn't request the name: %s", error->message);
+ g_object_unref (proxy_ck_manager);
+ return;
+ }
+
+ proxy_ck_session = dbus_g_proxy_new_for_name (dbus_connection,
+ CK_NAME,
+ ck_session_path,
+ CK_SESSION_INTERFACE);
+ if (dbus_g_proxy_call (proxy_ck_session, "GetSeatId",
+ &error, G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &ck_seat_path,
+ G_TYPE_INVALID) == FALSE) {
+
+ g_warning ("Couldn't request the name: %s", error->message);
+ g_object_unref (proxy_ck_session);
+ return;
+ }
+
+ proxy_ck_seat = dbus_g_proxy_new_for_name (dbus_connection,
+ CK_NAME,
+ ck_seat_path,
+ CK_SEAT_INTERFACE);
+ dbus_g_proxy_add_signal (proxy_ck_seat, "ActiveSessionChanged",
+ G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (proxy_ck_seat, "ActiveSessionChanged",
+ G_CALLBACK (sessionchanged_cb), NULL, NULL);
+ if (error != NULL) {
+ g_error_free (error);
+ }
+ g_object_unref (proxy_ck_manager);
+ g_object_unref (proxy_ck_session);
+ g_free (ck_seat_path);
+ dbus_g_connection_unref (dbus_connection);
+}
+
+static void
+default_adapter_changed (GObject *gobject,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ char *adapter;
+ gboolean adapter_powered;
+
+ g_object_get (G_OBJECT (client),
+ "default-adapter", &adapter,
+ "default-adapter-powered", &adapter_powered,
+ NULL);
+ if (adapter != NULL && *adapter != '\0') {
+ bluetoothd_enabled = adapter_powered;
+ } else {
+ bluetoothd_enabled = FALSE;
+ }
+
+ /* Were we called as init, or as a callback */
+ if (gobject != NULL) {
+ if (bluetoothd_enabled != FALSE)
+ obex_services_start ();
+ else
+ obex_services_shutdown ();
+ }
+}
+
+static void
+bluez_init (void)
+{
+ client = bluetooth_client_new ();
+ default_adapter_changed (NULL, NULL, NULL);
+ g_signal_connect (G_OBJECT (client), "notify::default-adapter",
+ G_CALLBACK (default_adapter_changed), NULL);
+ g_signal_connect (G_OBJECT (client), "notify::default-adapter-powered",
+ G_CALLBACK (default_adapter_changed), NULL);
+}
+
+static void
+migrate_old_configuration (void)
+{
+ const char *old_config_dir;
+ const char *new_config_dir;
+
+ old_config_dir = g_build_filename (g_get_home_dir (), ".mate2", "user-share", NULL);
+ new_config_dir = g_build_filename (g_get_user_config_dir (), "user-share", NULL);
+ if (g_file_test (old_config_dir, G_FILE_TEST_IS_DIR))
+ g_rename (old_config_dir, new_config_dir);
+
+}
+
+static void
+require_password_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ /* Need to restart to get new password setting */
+ if (http_get_pid () != 0) {
+ http_down ();
+ http_up ();
+ }
+}
+
+/* File sharing was disabled for some time, exit now */
+/* If we re-enable it in the ui, this will be restarted anyway */
+static gboolean
+disabled_timeout_callback (gpointer user_data)
+{
+ MateConfClient* client = (MateConfClient *) user_data;
+ http_down ();
+
+ if (mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ENABLED, NULL) == FALSE &&
+ mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED, NULL) == FALSE)
+ _exit (0);
+ return FALSE;
+}
+
+static void
+file_sharing_enabled_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ gboolean enabled;
+
+ if (disabled_timeout_tag != 0) {
+ g_source_remove (disabled_timeout_tag);
+ disabled_timeout_tag = 0;
+ }
+
+ enabled = mateconf_client_get_bool (client,
+ FILE_SHARING_ENABLED, NULL);
+ if (enabled) {
+ if (http_get_pid () == 0) {
+ http_up ();
+ }
+ } else {
+ http_down ();
+ disabled_timeout_tag = g_timeout_add_seconds (3,
+ (GSourceFunc)disabled_timeout_callback,
+ client);
+ }
+}
+
+static void
+file_sharing_bluetooth_allow_write_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ if (mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ENABLED, NULL) != FALSE)
+ obexftp_restart ();
+}
+
+static void
+file_sharing_bluetooth_require_pairing_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ if (mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ENABLED, NULL) != FALSE) {
+ /* We need to fully reset the session,
+ * otherwise the new setting isn't taken into account */
+ obexftp_down ();
+ obexftp_up ();
+ }
+}
+
+static void
+file_sharing_bluetooth_enabled_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ if (mateconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_ENABLED, NULL) == FALSE) {
+ obexftp_down ();
+ if (mateconf_client_get_bool (client, FILE_SHARING_ENABLED, NULL) == FALSE &&
+ mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED, NULL) == FALSE) {
+ _exit (0);
+ }
+ } else if (OBEX_ENABLED) {
+ obexftp_up ();
+ }
+}
+
+static void
+file_sharing_bluetooth_obexpush_enabled_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ if (mateconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED, NULL) == FALSE) {
+ obexpush_down ();
+ if (mateconf_client_get_bool (client, FILE_SHARING_ENABLED, NULL) == FALSE &&
+ mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ENABLED, NULL) == FALSE) {
+ _exit (0);
+ }
+ } else if (OBEX_ENABLED) {
+ obexpush_up ();
+ }
+}
+
+static void
+file_sharing_bluetooth_obexpush_accept_files_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ AcceptSetting setting;
+ char *str;
+
+ str = mateconf_client_get_string (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_ACCEPT_FILES, NULL);
+ setting = accept_setting_from_string (str);
+ g_free (str);
+
+ obexpush_set_accept_files_policy (setting);
+}
+
+static void
+file_sharing_bluetooth_obexpush_notify_changed (MateConfClient* client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ obexpush_set_notify (mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_NOTIFY, NULL));
+}
+
+static RETSIGTYPE
+cleanup_handler (int sig)
+{
+ http_down ();
+ obexftp_down ();
+ obexpush_down ();
+ _exit (2);
+}
+
+static int
+x_io_error_handler (Display *xdisplay)
+{
+ http_down ();
+ obexftp_down ();
+ _exit (2);
+}
+
+int
+main (int argc, char **argv)
+{
+ MateConfClient *client;
+ Display *xdisplay;
+ int x_fd;
+ Window selection_owner;
+ Atom xatom;
+
+ bindtextdomain (GETTEXT_PACKAGE, MATELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ gtk_init (&argc, &argv);
+
+ if (g_strcmp0 (g_get_real_name (), "root") == 0) {
+ g_warning ("mate-user-share cannot be started as root for security reasons.");
+ return 1;
+ }
+
+ signal (SIGPIPE, SIG_IGN);
+ signal (SIGINT, cleanup_handler);
+ signal (SIGHUP, cleanup_handler);
+ signal (SIGTERM, cleanup_handler);
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ if (xdisplay == NULL) {
+ g_warning ("Can't open display");
+ return 1;
+ }
+
+ xatom = XInternAtom (xdisplay, "_MATE_USER_SHARE", FALSE);
+ selection_owner = XGetSelectionOwner (xdisplay, xatom);
+
+ if (selection_owner != None) {
+ /* There is an owner already, quit */
+ return 1;
+ }
+
+ selection_owner = XCreateSimpleWindow (xdisplay,
+ RootWindow (xdisplay, 0),
+ 0, 0, 1, 1,
+ 0, 0, 0);
+ XSetSelectionOwner (xdisplay, xatom, selection_owner, CurrentTime);
+
+ if (XGetSelectionOwner (xdisplay, xatom) != selection_owner) {
+ /* Didn't get the selection */
+ return 1;
+ }
+
+ migrate_old_configuration ();
+
+ client = mateconf_client_get_default ();
+ if (mateconf_client_get_bool (client, FILE_SHARING_ENABLED, NULL) == FALSE &&
+ mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ENABLED, NULL) == FALSE &&
+ mateconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED, NULL) == FALSE)
+ return 1;
+
+ x_fd = ConnectionNumber (xdisplay);
+ XSetIOErrorHandler (x_io_error_handler);
+
+ if (http_init () == FALSE)
+ return 1;
+ if (obexftp_init () == FALSE)
+ return 1;
+ if (obexpush_init () == FALSE)
+ return 1;
+
+ mateconf_client_add_dir (client,
+ FILE_SHARING_DIR,
+ MATECONF_CLIENT_PRELOAD_RECURSIVE,
+ NULL);
+
+ mateconf_client_notify_add (client,
+ FILE_SHARING_ENABLED,
+ file_sharing_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_REQUIRE_PASSWORD,
+ require_password_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ENABLED,
+ file_sharing_bluetooth_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ file_sharing_bluetooth_allow_write_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_REQUIRE_PAIRING,
+ file_sharing_bluetooth_require_pairing_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ENABLED,
+ file_sharing_bluetooth_obexpush_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_ACCEPT_FILES,
+ file_sharing_bluetooth_obexpush_accept_files_changed,
+ NULL,
+ NULL,
+ NULL);
+ mateconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_OBEXPUSH_NOTIFY,
+ file_sharing_bluetooth_obexpush_notify_changed,
+ NULL,
+ NULL,
+ NULL);
+
+ g_object_unref (client);
+
+ bluez_init ();
+ consolekit_init ();
+
+ /* Initial setting */
+ file_sharing_enabled_changed (client, 0, NULL, NULL);
+ file_sharing_bluetooth_enabled_changed (client, 0, NULL, NULL);
+ file_sharing_bluetooth_obexpush_accept_files_changed (client, 0, NULL, NULL);
+ file_sharing_bluetooth_obexpush_notify_changed (client, 0, NULL, NULL);
+ file_sharing_bluetooth_obexpush_enabled_changed (client, 0, NULL, NULL);
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/src/user_share.h b/src/user_share.h
new file mode 100644
index 0000000..1ce6f73
--- /dev/null
+++ b/src/user_share.h
@@ -0,0 +1,25 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors: Alexander Larsson <[email protected]>
+ *
+ */
+
+char *lookup_public_dir (void);
+char *lookup_download_dir (void);