gnome-user-share r187 - in trunk: . po
- From: hadess svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-user-share r187 - in trunk: . po
- Date: Tue, 22 Jan 2008 12:54:02 +0000 (GMT)
Author: hadess
Date: Tue Jan 22 12:54:01 2008
New Revision: 187
URL: http://svn.gnome.org/viewvc/gnome-user-share?rev=187&view=rev
Log:
2008-01-22 Bastien Nocera <hadess hadess net>
* Makefile.am: upd
* configure.in: Require dbus-glib
* desktop_gnome_file_sharing.schemas.in:
* file-share-properties.c:
Add UI for the Bluetooth file sharing
* http.c:
* http.h: Split from user_share.c
* obexftp.c:
* obexftp.h: New files with ObexFTP support
* user_share.c: Remove HTTP code and add ObexFTP support
* user_share.h: new file
Add ObexFTP server support to gnome-user-share, requires
obex-data-server (Closes: #509938)
2008-01-22 Bastien Nocera <hadess hadess net>
* POTFILES.in: update for new files
Added:
trunk/http.c
trunk/http.h
trunk/obexftp.c
trunk/obexftp.h
trunk/user_share.h
Modified:
trunk/ChangeLog
trunk/Makefile.am
trunk/configure.in
trunk/desktop_gnome_file_sharing.schemas.in
trunk/file-share-properties.c
trunk/file-share-properties.glade
trunk/po/ChangeLog
trunk/po/POTFILES.in
trunk/user_share.c
Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am (original)
+++ trunk/Makefile.am Tue Jan 22 12:54:01 2008
@@ -43,8 +43,13 @@
$(USER_SHARE_CONFIG_CFLAGS) \
$(X_CFLAGS)
-gnome_user_share_SOURCES = \
- user_share.c
+gnome_user_share_SOURCES = \
+ user_share.c \
+ user_share.h \
+ http.c \
+ http.h \
+ obexftp.c \
+ obexftp.h
gnome_user_share_LDADD = \
$(HOWL_LIBS) \
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Tue Jan 22 12:54:01 2008
@@ -69,7 +69,7 @@
AC_MSG_ERROR([Neither avahi nor howl detected. Gnome-user-share needs a mDNS implementation.])
fi
-PKG_CHECK_MODULES(USER_SHARE, glib-2.0 >= 2.15.2 gconf-2.0 $DBUS_MODULES)
+PKG_CHECK_MODULES(USER_SHARE, glib-2.0 >= 2.15.2 gconf-2.0 dbus-glib-1 $DBUS_MODULES)
AC_SUBST(USER_SHARE_CFLAGS)
AC_SUBST(USER_SHARE_LIBS)
Modified: trunk/desktop_gnome_file_sharing.schemas.in
==============================================================================
--- trunk/desktop_gnome_file_sharing.schemas.in (original)
+++ trunk/desktop_gnome_file_sharing.schemas.in Tue Jan 22 12:54:01 2008
@@ -8,8 +8,8 @@
<type>bool</type>
<default>false</default>
<locale name="C">
- <short>Share Public directory</short>
- <long>If this is true, the Public directory in the users home directory will be shared when the user is logged in.</long>
+ <short>Share Public directory over the network</short>
+ <long>If this is true, the Public directory in the users home directory will be shared over the network when the user is logged in.</long>
</locale>
</schema>
<schema>
@@ -23,5 +23,27 @@
<long>When to ask for passwords. Possible values are "never", "on_write", and "always".</long>
</locale>
</schema>
+ <schema>
+ <key>/schemas/desktop/gnome/file_sharing/bluetooth_enabled</key>
+ <applyto>/desktop/gnome/file_sharing/bluetooth_enabled</applyto>
+ <owner>gnome-user-share</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Share Public directory over Bluetooth</short>
+ <long>If this is true, the Public directory in the users home directory will be shared over Bluetooth when the user is logged in.</long>
+ </locale>
+ </schema>
+ <schema>
+ <key>/schemas/desktop/gnome/file_sharing/bluetooth_allow_write</key>
+ <applyto>/desktop/gnome/file_sharing/bluetooth_allow_write</applyto>
+ <owner>gnome-user-share</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Whether to allow Bluetooth clients to write files.</short>
+ <long>Whether to allow Bluetooth clients to write files, or share the files read-only.</long>
+ </locale>
+ </schema>
</schemalist>
</gconfschemafile>
Modified: trunk/file-share-properties.c
==============================================================================
--- trunk/file-share-properties.c (original)
+++ trunk/file-share-properties.c Tue Jan 22 12:54:01 2008
@@ -33,7 +33,9 @@
#define FILE_SHARING_DIR "/desktop/gnome/file_sharing"
#define FILE_SHARING_ENABLED "/desktop/gnome/file_sharing/enabled"
+#define FILE_SHARING_BLUETOOTH_ENABLED "/desktop/gnome/file_sharing/bluetooth_enabled"
#define FILE_SHARING_REQUIRE_PASSWORD "/desktop/gnome/file_sharing/require_password"
+#define FILE_SHARING_BLUETOOTH_ALLOW_WRITE "/desktop/gnome/file_sharing/bluetooth_allow_write"
#define REALM "Please log in as the user guest"
#define USER "guest"
@@ -130,34 +132,50 @@
update_ui (void)
{
GConfClient *client;
- gboolean enabled;
+ gboolean enabled, bluetooth_enabled, bluetooth_write_enabled;
char *str;
PasswordSetting password_setting;
GtkWidget *check;
GtkWidget *password_combo;
GtkWidget *password_entry;
+ GtkWidget *bluetooth_check;
+ GtkWidget *allow_write_bluetooth_check;
client = gconf_client_get_default ();
enabled = gconf_client_get_bool (client,
FILE_SHARING_ENABLED,
NULL);
+ bluetooth_enabled = gconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_ENABLED,
+ NULL);
+ bluetooth_write_enabled = gconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ NULL);
+
str = gconf_client_get_string (client, FILE_SHARING_REQUIRE_PASSWORD, NULL);
password_setting = password_setting_from_string (str);
g_free (str);
-
+
check = glade_xml_get_widget (ui, "enable_check");
password_combo = glade_xml_get_widget (ui, "password_combo");
password_entry = glade_xml_get_widget (ui, "password_entry");
-
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check),
- enabled);
+ bluetooth_check = glade_xml_get_widget (ui, "enable_bluetooth_check");
+ allow_write_bluetooth_check = glade_xml_get_widget (ui, "allow_write_bluetooth_check");
+
+ 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);
-
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bluetooth_check), bluetooth_enabled);
+ gtk_widget_set_sensitive (allow_write_bluetooth_check, bluetooth_enabled);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (allow_write_bluetooth_check),
+ bluetooth_write_enabled);
+
g_object_unref (client);
}
@@ -179,6 +197,23 @@
update_ui ();
}
+static void
+file_sharing_bluetooth_enabled_changed (GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
+
+static void
+file_sharing_bluetooth_allow_write_changed (GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
+{
+ update_ui ();
+}
static void
password_combo_changed (GtkComboBox *combo_box)
@@ -198,25 +233,11 @@
}
static void
-enable_check_toggled (GtkWidget *check)
+launch_share (void)
{
- GConfClient *client;
- gboolean enabled;
- char *argv[2];
- int i;
-
- enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
-
- client = gconf_client_get_default ();
+ char *argv[2];
+ int i;
- gconf_client_set_bool (client,
- FILE_SHARING_ENABLED,
- enabled,
- NULL);
-
- g_object_unref (client);
-
- if (enabled) {
i = 0;
argv[i++] = USER_SHARE_PROGRAM;
argv[i++] = NULL;
@@ -229,19 +250,77 @@
NULL,
NULL,
NULL)) {
- g_warning ("Unable to start gnome-user-share program");
+ g_warning ("Unable to start gnome-user-share program");
}
- }
+}
+
+static void
+enable_bluetooth_check_toggled (GtkWidget *check)
+{
+ GConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = gconf_client_get_default ();
+
+ gconf_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)
+{
+ GConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = gconf_client_get_default ();
+
+ gconf_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 ();
+ g_object_set_data (G_OBJECT (editable),
+ "user_edited", GINT_TO_POINTER (1));
+ flush_password ();
}
+static void
+bluetooth_allow_write_check_toggled (GtkWidget *check)
+{
+ GConfClient *client;
+ gboolean enabled;
+
+ enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check));
+
+ client = gconf_client_get_default ();
+
+ gconf_client_set_bool (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ enabled,
+ NULL);
+
+ g_object_unref (client);
+}
int
main (int argc, char *argv[])
@@ -250,6 +329,8 @@
GtkWidget *check;
GtkWidget *password_combo;
GtkWidget *password_entry;
+ GtkWidget *bluetooth_check;
+ GtkWidget *bluetooth_allow_write_check;
GtkWidget *window;
GtkListStore *store;
GtkCellRenderer *cell;
@@ -278,6 +359,8 @@
check = glade_xml_get_widget (ui, "enable_check");
password_combo = glade_xml_get_widget (ui, "password_combo");
password_entry = glade_xml_get_widget (ui, "password_entry");
+ bluetooth_check = glade_xml_get_widget (ui, "enable_bluetooth_check");
+ bluetooth_allow_write_check = glade_xml_get_widget (ui, "allow_write_bluetooth_check");
store = gtk_list_store_new (1, G_TYPE_STRING);
gtk_combo_box_set_model (GTK_COMBO_BOX (password_combo),
@@ -313,6 +396,11 @@
"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 (glade_xml_get_widget (ui, "close_button"),
"clicked", G_CALLBACK (gtk_main_quit), NULL);
@@ -329,6 +417,18 @@
NULL,
NULL,
NULL);
+ gconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ENABLED,
+ file_sharing_bluetooth_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ file_sharing_bluetooth_allow_write_changed,
+ NULL,
+ NULL,
+ NULL);
g_object_unref (client);
Modified: trunk/file-share-properties.glade
==============================================================================
--- trunk/file-share-properties.glade (original)
+++ trunk/file-share-properties.glade Tue Jan 22 12:54:01 2008
@@ -5,7 +5,6 @@
<widget class="GtkDialog" id="user_share_dialog">
<property name="border_width">12</property>
- <property name="visible">False</property>
<property name="title" translatable="yes">File Sharing Preferences</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
@@ -17,6 +16,8 @@
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
@@ -73,7 +74,7 @@
<child>
<widget class="GtkTable" id="table2">
<property name="visible">True</property>
- <property name="n_rows">3</property>
+ <property name="n_rows">5</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">6</property>
@@ -93,6 +94,10 @@
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="mnemonic_widget">password_combo</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
@@ -107,6 +112,8 @@
<child>
<widget class="GtkComboBox" id="password_combo">
<property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
@@ -131,6 +138,10 @@
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="mnemonic_widget">password_entry</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
@@ -151,6 +162,7 @@
<property name="max_length">0</property>
<property name="text"></property>
<property name="has_frame">True</property>
+ <property name="invisible_char">â</property>
<property name="activates_default">False</property>
</widget>
<packing>
@@ -183,6 +195,50 @@
<property name="y_options"></property>
</packing>
</child>
+
+ <child>
+ <widget class="GtkCheckButton" id="enable_bluetooth_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Share Public files over Bluetooth</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="allow_write_bluetooth_check">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Allow remote devices to write to modify files</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
</widget>
</child>
</widget>
@@ -201,6 +257,10 @@
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
</widget>
<packing>
<property name="type">label_item</property>
Added: trunk/http.c
==============================================================================
--- (empty file)
+++ trunk/http.c Tue Jan 22 12:54:01 2008
@@ -0,0 +1,625 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Nautilus 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.
+ *
+ * Nautilus 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 <alexl redhat com>
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <X11/Xlib.h>
+
+#ifdef HAVE_DBUS_1_1
+#include <dbus/dbus.h>
+#endif
+
+#ifdef HAVE_AVAHI
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-common/alternative.h>
+#include <avahi-common/error.h>
+#include <avahi-glib/glib-watch.h>
+#include <avahi-glib/glib-malloc.h>
+#endif /* HAVE_AVAHI */
+
+#ifdef HAVE_HOWL
+/* Workaround broken howl installing config.h */
+#undef PACKAGE
+#undef VERSION
+#include <howl.h>
+#endif /* HAVE_HOWL */
+
+#include <gconf/gconf-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.h"
+#include "http.h"
+
+#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 *
+get_share_name (void)
+{
+ static char *name = NULL;
+ const char *host_name;
+
+ 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);
+ }
+
+ }
+ 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
+
+#ifdef HAVE_AVAHI
+
+static AvahiClient *avahi_client = NULL;
+static gboolean avahi_should_publish = FALSE;
+static gboolean avahi_running = FALSE;
+static int avahi_port = 0;
+static AvahiEntryGroup *entry_group = NULL;
+static char *avahi_name = NULL;
+
+static AvahiStringList*
+new_text_record_list (const char *first_key,
+ const char *first_value,
+ ...)
+{
+ va_list args;
+ const char *k;
+ const char *v;
+ AvahiStringList *list;
+
+ if (first_key == NULL)
+ return NULL;
+
+ list = NULL;
+
+ list = avahi_string_list_add_pair (list, first_key, first_value);
+
+ va_start (args, first_value);
+ k = va_arg (args, const char*);
+ if (k)
+ v = va_arg (args, const char*);
+ while (k != NULL) {
+ list = avahi_string_list_add_pair (list, k, v);
+
+ k = va_arg (args, const char*);
+ if (k)
+ v = va_arg (args, const char*);
+ }
+
+ va_end(args);
+
+ return list;
+}
+
+static gboolean
+create_service (void) {
+ int ret;
+ AvahiStringList *txt_records;
+
+ if (avahi_name == NULL) {
+ avahi_name = g_strdup (get_share_name ());
+ }
+
+ txt_records = new_text_record_list ("u", "guest",
+#ifdef HAVE_DBUS_1_1
+ /* This must be last */
+ dbus_session_id != NULL ? "org.freedesktop.od.session" : NULL, dbus_session_id,
+#endif
+ NULL);
+
+ ret = avahi_entry_group_add_service_strlst (entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
+ AVAHI_PUBLISH_USE_MULTICAST,
+ avahi_name, "_webdav._tcp", NULL, NULL,
+ avahi_port,
+ txt_records);
+
+ avahi_string_list_free(txt_records);
+
+ if (ret < 0) {
+ return FALSE;
+ }
+
+ ret = avahi_entry_group_commit (entry_group);
+
+ if (ret < 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+entry_group_callback (AvahiEntryGroup *g,
+ AvahiEntryGroupState state,
+ void *userdata)
+{
+ if (state == AVAHI_ENTRY_GROUP_ESTABLISHED) {
+ } else if (state == AVAHI_ENTRY_GROUP_COLLISION) {
+ char *n;
+
+ /* A service name collision happened. Let's pick a new name */
+ n = avahi_alternative_service_name (avahi_name);
+ g_free (avahi_name);
+ avahi_name = n;
+
+ fprintf (stderr, "Service name collision, renaming service to '%s'\n", avahi_name);
+
+ /* And recreate the services */
+ create_service();
+ }
+}
+
+static void
+avahi_client_callback (AvahiClient *client, AvahiClientState state, void *userdata)
+{
+ if (state == AVAHI_CLIENT_S_RUNNING) {
+ avahi_running = TRUE;
+ if (avahi_should_publish) {
+ create_service ();
+ }
+ } else if (state == AVAHI_CLIENT_S_COLLISION) {
+ avahi_entry_group_reset (entry_group);
+ } else if (state == AVAHI_CLIENT_FAILURE) {
+ avahi_running = FALSE;
+ }
+}
+
+static gboolean
+init_avahi (void)
+{
+ AvahiGLibPoll *poll;
+ int error;
+
+ avahi_set_allocator (avahi_glib_allocator ());
+
+ poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
+
+ /* Create a new AvahiClient instance */
+ avahi_client = avahi_client_new (avahi_glib_poll_get (poll),
+ AVAHI_CLIENT_NO_FAIL,
+ avahi_client_callback,
+ NULL,
+ &error);
+ if (avahi_client == NULL) {
+ return FALSE;
+ }
+
+ entry_group = avahi_entry_group_new (avahi_client, entry_group_callback, NULL);
+ if (entry_group == NULL) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+publish_service (int port)
+{
+ avahi_should_publish = TRUE;
+ avahi_port = port;
+ if (avahi_running) {
+ create_service ();
+ }
+ return TRUE;
+}
+
+static void
+stop_publishing (void)
+{
+ avahi_should_publish = FALSE;
+ avahi_entry_group_reset (entry_group);
+}
+#endif
+
+#ifdef HAVE_HOWL
+
+static sw_discovery_publish_id published_id = 0;
+static sw_discovery howl_session;
+
+static gboolean
+howl_input (GIOChannel *io_channel,
+ GIOCondition cond,
+ gpointer callback_data)
+{
+ sw_discovery session;
+ session = callback_data;
+ sw_salt salt;
+
+ if (sw_discovery_salt (session, &salt) == SW_OKAY) {
+ sw_salt_lock (salt);
+ sw_discovery_read_socket (session);
+ sw_salt_unlock (salt);
+ }
+ return TRUE;
+}
+
+static void
+set_up_howl_session (sw_discovery session)
+{
+ int fd;
+ GIOChannel *channel;
+
+ fd = sw_discovery_socket (session);
+
+ channel = g_io_channel_unix_new (fd);
+ g_io_add_watch (channel,
+ G_IO_IN,
+ howl_input, session);
+ g_io_channel_unref (channel);
+}
+
+static sw_result
+publish_reply (sw_discovery discovery,
+ sw_discovery_publish_status status,
+ sw_discovery_oid id,
+ sw_opaque extra)
+{
+ return SW_OKAY;
+}
+
+
+static gboolean
+publish_service (int port)
+{
+ sw_result result;
+
+ result = sw_discovery_publish (howl_session, 0,
+ get_share_name (),
+ "_webdav._tcp",
+ NULL, NULL,
+ port,
+ /* TODO: should be u=guest */
+ /* text */ (unsigned char *) "", 0,
+ publish_reply, NULL, &published_id);
+ if (result != SW_OKAY) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+stop_publishing (void)
+{
+ if (published_id != 0)
+ sw_discovery_cancel (howl_session, published_id);
+ published_id = 0;
+}
+#endif /* HAVE_HOWL */
+
+
+static void
+ensure_conf_dir (void)
+{
+ char *dirname;
+
+ dirname = g_build_filename (g_get_home_dir (), ".gnome2", "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 gboolean
+spawn_httpd (int port, pid_t *pid_out)
+{
+ char *free1, *free2, *free3;
+ gboolean res;
+ char *argv[10];
+ char *env[10];
+ int i;
+ gint status;
+ char *pid_filename;
+ char *pidfile;
+ GError *error;
+ gboolean got_pidfile;
+ GConfClient *client;
+ char *str;
+ char *public_dir;
+
+ public_dir = lookup_public_dir ();
+ ensure_conf_dir ();
+
+ i = 0;
+ argv[i++] = HTTPD_PROGRAM;
+ argv[i++] = "-f";
+ argv[i++] = HTTPD_CONFIG;
+ argv[i++] = "-C";
+ free1 = argv[i++] = g_strdup_printf ("Listen %d", port);
+
+ client = gconf_client_get_default ();
+ str = gconf_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;
+ free2 = env[i++] = g_strdup_printf("HOME=%s", g_get_home_dir());
+ free3 = env[i++] = g_strdup_printf("XDG_PUBLICSHARE_DIR=%s", public_dir);
+ env[i++] = "LANG=C";
+ env[i] = NULL;
+
+ pid_filename = g_build_filename (g_get_home_dir (), ".gnome2/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 (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");
+ } else {
+ if (!publish_service (port)) {
+ fprintf (stderr, "publishing failed\n");
+ }
+ }
+}
+
+void
+http_down (void)
+{
+ kill_httpd ();
+ stop_publishing ();
+}
+
+gboolean
+http_init (void)
+{
+#ifdef HAVE_DBUS_1_1
+ init_dbus();
+#endif
+
+#ifdef HAVE_AVAHI
+ if (!init_avahi ()) {
+ /* Print out the error string */
+ fprintf (stderr, "avahi init failed\n");
+ return FALSE;
+ }
+#endif
+#ifdef HAVE_HOWL
+ if (sw_discovery_init (&howl_session) != SW_OKAY) {
+ fprintf (stderr, "howl init failed\n");
+ return FALSE;
+ }
+ set_up_howl_session (howl_session);
+#endif
+
+ return TRUE;
+}
+
+pid_t
+http_get_pid (void)
+{
+ return httpd_pid;
+}
+
Added: trunk/http.h
==============================================================================
--- (empty file)
+++ trunk/http.h Tue Jan 22 12:54:01 2008
@@ -0,0 +1,28 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Nautilus 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.
+ *
+ * Nautilus 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 <alexl redhat com>
+ *
+ */
+
+void http_up (void);
+void http_down (void);
+gboolean http_init (void);
+pid_t http_get_pid (void);
+
Added: trunk/obexftp.c
==============================================================================
--- (empty file)
+++ trunk/obexftp.c Tue Jan 22 12:54:01 2008
@@ -0,0 +1,152 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Nautilus 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.
+ *
+ * Nautilus 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 <hadess hadess net>
+ *
+ */
+
+#include "config.h"
+
+#include <dbus/dbus-glib.h>
+#include <gconf/gconf-client.h>
+
+#include <string.h>
+
+#include "obexftp.h"
+#include "user_share.h"
+
+static DBusGConnection *connection = NULL;
+static DBusGProxy *manager_proxy = NULL;
+static DBusGProxy *server_proxy = NULL;
+
+void
+obexftp_up (void)
+{
+ GError *err = NULL;
+ GConfClient *client;
+ char *public_dir, *session;
+ gboolean allow_write;
+
+ session = 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_INVALID,
+ G_TYPE_STRING, &session, G_TYPE_INVALID) == FALSE) {
+ g_printerr ("Creating Bluetooth server failed: %s\n",
+ err->message);
+ g_error_free (err);
+ g_object_unref (manager_proxy);
+ manager_proxy = NULL;
+ return;
+ }
+ }
+
+ public_dir = lookup_public_dir ();
+ client = gconf_client_get_default ();
+ allow_write = gconf_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",
+ session,
+ "org.openobex.Server");
+ g_free (session);
+ }
+ if (dbus_g_proxy_call (server_proxy, "Start", &err,
+ G_TYPE_STRING, public_dir, G_TYPE_BOOLEAN, !allow_write, G_TYPE_INVALID,
+ G_TYPE_INVALID) == FALSE) {
+ g_printerr ("Starting Bluetooth server session 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, "Stop", &err, G_TYPE_INVALID, G_TYPE_INVALID) == FALSE) {
+ const gchar *error_name = NULL;
+
+ if (err != NULL && err->code == DBUS_GERROR_REMOTE_EXCEPTION)
+ error_name = dbus_g_error_get_name (err);
+ if (error_name == NULL ||
+ (error_name != NULL && strcmp (error_name, "org.openobex.Error.NotStarted") != 0)) {
+ g_printerr ("Stopping Bluetooth server session 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;
+ }
+
+ return TRUE;
+}
+
Added: trunk/obexftp.h
==============================================================================
--- (empty file)
+++ trunk/obexftp.h Tue Jan 22 12:54:01 2008
@@ -0,0 +1,30 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Nautilus 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.
+ *
+ * Nautilus 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 <hadess hadess net>
+ *
+ */
+
+#include <glib.h>
+
+void obexftp_up (void);
+void obexftp_down (void);
+void obexftp_restart (void);
+gboolean obexftp_init (void);
+
Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in (original)
+++ trunk/po/POTFILES.in Tue Jan 22 12:54:01 2008
@@ -5,4 +5,5 @@
file-share-properties.glade
gnome-user-share-properties.desktop.in
gnome-user-share.desktop.in.in
+http.c
user_share.c
Modified: trunk/user_share.c
==============================================================================
--- trunk/user_share.c (original)
+++ trunk/user_share.c Tue Jan 22 12:54:01 2008
@@ -1,7 +1,7 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
- * Copyright (C) 2004 Red Hat, Inc.
+ * Copyright (C) 2004-2008 Red Hat, Inc.
*
* Nautilus is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -27,25 +27,9 @@
#include <glib/gi18n.h>
#include <X11/Xlib.h>
-#ifdef HAVE_DBUS_1_1
-#include <dbus/dbus.h>
-#endif
-
-#ifdef HAVE_AVAHI
-#include <avahi-client/client.h>
-#include <avahi-client/publish.h>
-#include <avahi-common/alternative.h>
-#include <avahi-common/error.h>
-#include <avahi-glib/glib-watch.h>
-#include <avahi-glib/glib-malloc.h>
-#endif /* HAVE_AVAHI */
-
-#ifdef HAVE_HOWL
-/* Workaround broken howl installing config.h */
-#undef PACKAGE
-#undef VERSION
-#include <howl.h>
-#endif /* HAVE_HOWL */
+#include "user_share.h"
+#include "http.h"
+#include "obexftp.h"
#include <gconf/gconf-client.h>
@@ -55,28 +39,11 @@
#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
-
-#define FILE_SHARING_DIR "/desktop/gnome/file_sharing"
-#define FILE_SHARING_ENABLED "/desktop/gnome/file_sharing/enabled"
-#define FILE_SHARING_REQUIRE_PASSWORD "/desktop/gnome/file_sharing/require_password"
-
-#ifdef HAVE_DBUS_1_1
-static char *dbus_session_id;
-#endif
static GMainLoop *loop = NULL;
-static pid_t httpd_pid = 0;
static guint disabled_timeout_tag = 0;
-static char *
+char *
lookup_public_dir (void)
{
const char *public_dir;
@@ -93,704 +60,217 @@
return dir;
}
-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 *
-get_share_name (void)
-{
- static char *name = NULL;
- const char *host_name;
-
- 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);
- }
-
- }
- 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
-
-#ifdef HAVE_AVAHI
-
-static AvahiClient *avahi_client = NULL;
-static gboolean avahi_should_publish = FALSE;
-static gboolean avahi_running = FALSE;
-static int avahi_port = 0;
-static AvahiEntryGroup *entry_group = NULL;
-static char *avahi_name = NULL;
-
-static AvahiStringList*
-new_text_record_list (const char *first_key,
- const char *first_value,
- ...)
-{
- va_list args;
- const char *k;
- const char *v;
- AvahiStringList *list;
-
- if (first_key == NULL)
- return NULL;
-
- list = NULL;
-
- list = avahi_string_list_add_pair (list, first_key, first_value);
-
- va_start (args, first_value);
- k = va_arg (args, const char*);
- if (k)
- v = va_arg (args, const char*);
- while (k != NULL) {
- list = avahi_string_list_add_pair (list, k, v);
-
- k = va_arg (args, const char*);
- if (k)
- v = va_arg (args, const char*);
- }
-
- va_end(args);
-
- return list;
-}
-
-static gboolean
-create_service (void) {
- int ret;
- AvahiStringList *txt_records;
-
- if (avahi_name == NULL) {
- avahi_name = g_strdup (get_share_name ());
- }
-
- txt_records = new_text_record_list ("u", "guest",
-#ifdef HAVE_DBUS_1_1
- /* This must be last */
- dbus_session_id != NULL ? "org.freedesktop.od.session" : NULL, dbus_session_id,
-#endif
- NULL);
-
- ret = avahi_entry_group_add_service_strlst (entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
- AVAHI_PUBLISH_USE_MULTICAST,
- avahi_name, "_webdav._tcp", NULL, NULL,
- avahi_port,
- txt_records);
-
- avahi_string_list_free(txt_records);
-
- if (ret < 0) {
- return FALSE;
+require_password_changed (GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
+{
+ /* Need to restart to get new password setting */
+ if (http_get_pid () != 0) {
+ http_down ();
+ http_up ();
}
-
- ret = avahi_entry_group_commit (entry_group);
-
- if (ret < 0) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-entry_group_callback (AvahiEntryGroup *g,
- AvahiEntryGroupState state,
- void *userdata)
-{
- if (state == AVAHI_ENTRY_GROUP_ESTABLISHED) {
- } else if (state == AVAHI_ENTRY_GROUP_COLLISION) {
- char *n;
-
- /* A service name collision happened. Let's pick a new name */
- n = avahi_alternative_service_name (avahi_name);
- g_free (avahi_name);
- avahi_name = n;
-
- fprintf (stderr, "Service name collision, renaming service to '%s'\n", avahi_name);
-
- /* And recreate the services */
- create_service();
- }
-}
-
-static void
-avahi_client_callback (AvahiClient *client, AvahiClientState state, void *userdata)
-{
- if (state == AVAHI_CLIENT_S_RUNNING) {
- avahi_running = TRUE;
- if (avahi_should_publish) {
- create_service ();
- }
- } else if (state == AVAHI_CLIENT_S_COLLISION) {
- avahi_entry_group_reset (entry_group);
- } else if (state == AVAHI_CLIENT_FAILURE) {
- avahi_running = FALSE;
- }
}
+/* File sharing was disabled for some time, exit now */
+/* If we re-enable it in the ui, this will be restarted anyway */
static gboolean
-init_avahi (void)
+disabled_timeout_callback (gpointer user_data)
{
- AvahiGLibPoll *poll;
- int error;
+ GConfClient* client = (GConfClient *) user_data;
+ http_down ();
- avahi_set_allocator (avahi_glib_allocator ());
-
- poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
-
- /* Create a new AvahiClient instance */
- avahi_client = avahi_client_new (avahi_glib_poll_get (poll),
- AVAHI_CLIENT_NO_FAIL,
- avahi_client_callback,
- NULL,
- &error);
- if (avahi_client == NULL) {
- return FALSE;
- }
-
- entry_group = avahi_entry_group_new (avahi_client, entry_group_callback, NULL);
- if (entry_group == NULL) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static gboolean
-publish_service (int port)
-{
- avahi_should_publish = TRUE;
- avahi_port = port;
- if (avahi_running) {
- create_service ();
- }
- return TRUE;
+ if (gconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_ENABLED, NULL) == FALSE)
+ _exit (0);
+ return FALSE;
}
static void
-stop_publishing (void)
+file_sharing_enabled_changed (GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
{
- avahi_should_publish = FALSE;
- avahi_entry_group_reset (entry_group);
-}
-#endif
+ gboolean enabled;
-#ifdef HAVE_HOWL
-
-static sw_discovery_publish_id published_id = 0;
-static sw_discovery howl_session;
-
-static gboolean
-howl_input (GIOChannel *io_channel,
- GIOCondition cond,
- gpointer callback_data)
-{
- sw_discovery session;
- session = callback_data;
- sw_salt salt;
-
- if (sw_discovery_salt (session, &salt) == SW_OKAY) {
- sw_salt_lock (salt);
- sw_discovery_read_socket (session);
- sw_salt_unlock (salt);
+ if (disabled_timeout_tag != 0) {
+ g_source_remove (disabled_timeout_tag);
+ disabled_timeout_tag = 0;
}
- return TRUE;
-}
-
-static void
-set_up_howl_session (sw_discovery session)
-{
- int fd;
- GIOChannel *channel;
-
- fd = sw_discovery_socket (session);
-
- channel = g_io_channel_unix_new (fd);
- g_io_add_watch (channel,
- G_IO_IN,
- howl_input, session);
- g_io_channel_unref (channel);
-}
-
-static sw_result
-publish_reply (sw_discovery discovery,
- sw_discovery_publish_status status,
- sw_discovery_oid id,
- sw_opaque extra)
-{
- return SW_OKAY;
-}
-
-
-static gboolean
-publish_service (int port)
-{
- sw_result result;
- result = sw_discovery_publish (howl_session, 0,
- get_share_name (),
- "_webdav._tcp",
- NULL, NULL,
- port,
- /* TODO: should be u=guest */
- /* text */ (unsigned char *) "", 0,
- publish_reply, NULL, &published_id);
- if (result != SW_OKAY) {
- return FALSE;
- }
- return TRUE;
+ enabled = gconf_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 (3*1000,
+ (GSourceFunc)disabled_timeout_callback,
+ client);
+ }
}
static void
-stop_publishing (void)
+file_sharing_bluetooth_allow_write_changed (GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
{
- if (published_id != 0)
- sw_discovery_cancel (howl_session, published_id);
- published_id = 0;
+ obexftp_restart ();
}
-#endif /* HAVE_HOWL */
-
static void
-ensure_conf_dir (void)
+file_sharing_bluetooth_enabled_changed (GConfClient* client,
+ guint cnxn_id,
+ GConfEntry *entry,
+ gpointer data)
{
- char *dirname;
-
- dirname = g_build_filename (g_get_home_dir (), ".gnome2", "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 (gconf_client_get_bool (client,
+ FILE_SHARING_BLUETOOTH_ENABLED, NULL) == FALSE) {
+ obexftp_down ();
+ if (gconf_client_get_bool (client,
+ FILE_SHARING_ENABLED, NULL) == FALSE) {
+ _exit (0);
}
- if (setexeccon (mycon) < 0)
- abort ();
- freecon (mycon);
+ } else {
+ obexftp_up ();
}
-#endif
}
-static gboolean
-spawn_httpd (int port, pid_t *pid_out)
-{
- char *free1, *free2, *free3;
- gboolean res;
- char *argv[10];
- char *env[10];
- int i;
- gint status;
- char *pid_filename;
- char *pidfile;
- GError *error;
- gboolean got_pidfile;
- GConfClient *client;
- char *str;
- char *public_dir;
-
- public_dir = lookup_public_dir ();
- ensure_conf_dir ();
-
- i = 0;
- argv[i++] = HTTPD_PROGRAM;
- argv[i++] = "-f";
- argv[i++] = HTTPD_CONFIG;
- argv[i++] = "-C";
- free1 = argv[i++] = g_strdup_printf ("Listen %d", port);
-
- client = gconf_client_get_default ();
- str = gconf_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;
- free2 = env[i++] = g_strdup_printf("HOME=%s", g_get_home_dir());
- free3 = env[i++] = g_strdup_printf("XDG_PUBLICSHARE_DIR=%s", public_dir);
- env[i++] = "LANG=C";
- env[i] = NULL;
-
- pid_filename = g_build_filename (g_get_home_dir (), ".gnome2/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 (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;
-}
-
-
static RETSIGTYPE
cleanup_handler (int sig)
{
- kill_httpd ();
- _exit (2);
-}
-
-/* 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 (void)
-{
- kill_httpd ();
- exit (0);
-
- return FALSE;
-}
-
-static void
-up (void)
-{
- guint port;
-
- port = get_port ();
- if (!spawn_httpd (port, &httpd_pid)) {
- fprintf (stderr, "spawning httpd failed\n");
- } else {
- if (!publish_service (port)) {
- fprintf (stderr, "publishing failed\n");
- }
- }
-}
-
-static void
-down (void)
-{
- kill_httpd ();
- stop_publishing ();
-}
-
-static void
-require_password_changed (GConfClient* client,
- guint cnxn_id,
- GConfEntry *entry,
- gpointer data)
-{
- /* Need to restart to get new password setting */
- if (httpd_pid != 0) {
- down ();
- up ();
- }
-}
-
-static void
-file_sharing_enabled_changed (GConfClient* client,
- guint cnxn_id,
- GConfEntry *entry,
- gpointer data)
-{
- gboolean enabled;
-
- if (disabled_timeout_tag != 0) {
- g_source_remove (disabled_timeout_tag);
- disabled_timeout_tag = 0;
- }
-
- enabled = gconf_client_get_bool (client,
- FILE_SHARING_ENABLED, NULL);
- if (enabled) {
- if (httpd_pid == 0) {
- up ();
- }
- } else {
- down ();
- disabled_timeout_tag = g_timeout_add (3*1000,
- (GSourceFunc)disabled_timeout_callback,
- NULL);
- }
+ http_down ();
+ obexftp_down ();
+ _exit (2);
}
static int
x_io_error_handler (Display *xdisplay)
{
- kill_httpd ();
- _exit (2);
+ http_down ();
+ obexftp_down ();
+ _exit (2);
}
static gboolean
x_input (GIOChannel *io_channel,
- GIOCondition cond,
- gpointer callback_data)
+ GIOCondition cond,
+ gpointer callback_data)
{
- Display *xdisplay;
- XEvent ignored;
+ Display *xdisplay;
+ XEvent ignored;
- xdisplay = callback_data;
- while (XPending (xdisplay)) {
+ xdisplay = callback_data;
+ while (XPending (xdisplay)) {
XNextEvent (xdisplay, &ignored);
- }
- return TRUE;
+ }
+ return TRUE;
}
int
main (int argc, char **argv)
{
- GConfClient *client;
- Display *xdisplay;
- int x_fd;
- GIOChannel *channel;
- Window selection_owner;
- Atom xatom;
-
- g_type_init ();
- loop = g_main_loop_new (NULL, FALSE);
-
- signal (SIGPIPE, SIG_IGN);
- signal (SIGINT, cleanup_handler);
- signal (SIGHUP, cleanup_handler);
- signal (SIGTERM, cleanup_handler);
-
- xdisplay = XOpenDisplay (NULL);
- if (xdisplay == NULL) {
+ GConfClient *client;
+ Display *xdisplay;
+ int x_fd;
+ GIOChannel *channel;
+ Window selection_owner;
+ Atom xatom;
+
+ g_type_init ();
+ loop = g_main_loop_new (NULL, FALSE);
+
+ signal (SIGPIPE, SIG_IGN);
+ signal (SIGINT, cleanup_handler);
+ signal (SIGHUP, cleanup_handler);
+ signal (SIGTERM, cleanup_handler);
+
+ xdisplay = XOpenDisplay (NULL);
+ if (xdisplay == NULL) {
fprintf (stderr, "Can't open display\n");
return 1;
- }
-
- xatom = XInternAtom (xdisplay, "_GNOME_USER_SHARE", FALSE);
- selection_owner = XGetSelectionOwner (xdisplay, xatom);
-
- if (selection_owner != None) {
+ }
+
+ xatom = XInternAtom (xdisplay, "_GNOME_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) {
+ }
+
+ 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;
- }
+ }
- client = gconf_client_get_default ();
- if (gconf_client_get_bool (client, FILE_SHARING_ENABLED, NULL) == FALSE)
- return 1;
-
- x_fd = ConnectionNumber (xdisplay);
- XSetIOErrorHandler (x_io_error_handler);
-
- channel = g_io_channel_unix_new (x_fd);
- g_io_add_watch (channel,
- G_IO_IN,
- x_input, xdisplay);
- g_io_channel_unref (channel);
-
-#ifdef HAVE_DBUS_1_1
- init_dbus();
-#endif
-
-#ifdef HAVE_AVAHI
- if (!init_avahi ()) {
- /* Print out the error string */
- fprintf (stderr, "avahi init failed\n");
+ client = gconf_client_get_default ();
+ if (gconf_client_get_bool (client, FILE_SHARING_ENABLED, NULL) == FALSE &&
+ gconf_client_get_bool (client, FILE_SHARING_BLUETOOTH_ENABLED, NULL) == FALSE)
return 1;
- }
-#endif
-#ifdef HAVE_HOWL
- if (sw_discovery_init (&howl_session) != SW_OKAY) {
- fprintf (stderr, "howl init failed\n");
+
+ x_fd = ConnectionNumber (xdisplay);
+ XSetIOErrorHandler (x_io_error_handler);
+
+ channel = g_io_channel_unix_new (x_fd);
+ g_io_add_watch (channel,
+ G_IO_IN,
+ x_input, xdisplay);
+ g_io_channel_unref (channel);
+
+ if (http_init () == FALSE)
+ return 1;
+ if (obexftp_init () == FALSE)
return 1;
- }
- set_up_howl_session (howl_session);
-#endif
-
- gconf_client_add_dir (client,
- FILE_SHARING_DIR,
- GCONF_CLIENT_PRELOAD_RECURSIVE,
- NULL);
-
- gconf_client_notify_add (client,
- FILE_SHARING_ENABLED,
- file_sharing_enabled_changed,
- NULL,
- NULL,
- NULL);
- gconf_client_notify_add (client,
- FILE_SHARING_REQUIRE_PASSWORD,
- require_password_changed,
- NULL,
- NULL,
- NULL);
- g_object_unref (client);
-
- /* Initial setting */
- file_sharing_enabled_changed (client, 0, NULL, NULL);
-
- g_main_loop_run (loop);
-
- return 0;
+
+ gconf_client_add_dir (client,
+ FILE_SHARING_DIR,
+ GCONF_CLIENT_PRELOAD_RECURSIVE,
+ NULL);
+
+ gconf_client_notify_add (client,
+ FILE_SHARING_ENABLED,
+ file_sharing_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ FILE_SHARING_REQUIRE_PASSWORD,
+ require_password_changed,
+ NULL,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ENABLED,
+ file_sharing_bluetooth_enabled_changed,
+ NULL,
+ NULL,
+ NULL);
+ gconf_client_notify_add (client,
+ FILE_SHARING_BLUETOOTH_ALLOW_WRITE,
+ file_sharing_bluetooth_allow_write_changed,
+ NULL,
+ NULL,
+ NULL);
+ g_object_unref (client);
+
+ /* Initial setting */
+ file_sharing_enabled_changed (client, 0, NULL, NULL);
+ file_sharing_bluetooth_enabled_changed (client, 0, NULL, NULL);
+
+ g_main_loop_run (loop);
+
+ return 0;
}
+
Added: trunk/user_share.h
==============================================================================
--- (empty file)
+++ trunk/user_share.h Tue Jan 22 12:54:01 2008
@@ -0,0 +1,31 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+
+/*
+ * Copyright (C) 2004-2008 Red Hat, Inc.
+ *
+ * Nautilus 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.
+ *
+ * Nautilus 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 <alexl redhat com>
+ *
+ */
+
+#define FILE_SHARING_DIR "/desktop/gnome/file_sharing"
+#define FILE_SHARING_ENABLED "/desktop/gnome/file_sharing/enabled"
+#define FILE_SHARING_BLUETOOTH_ENABLED "/desktop/gnome/file_sharing/bluetooth_enabled"
+#define FILE_SHARING_REQUIRE_PASSWORD "/desktop/gnome/file_sharing/require_password"
+#define FILE_SHARING_BLUETOOTH_ALLOW_WRITE "/desktop/gnome/file_sharing/bluetooth_allow_write"
+
+char *lookup_public_dir (void);
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]