diff options
Diffstat (limited to 'src/user_share.c')
-rw-r--r-- | src/user_share.c | 572 |
1 files changed, 572 insertions, 0 deletions
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; +} |