📄 user_share.c
字号:
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- *//* * Copyright (C) 2004 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_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 <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#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"static GMainLoop *loop = NULL;static pid_t httpd_pid = 0;static guint disabled_timeout_tag = 0;static char *lookup_public_dir (void){ FILE *file; char *config_file; char buffer[512]; char *user_dir; char *p, *d; int len; int relative; config_file = g_build_filename (g_get_user_config_dir (), "user-dirs.dirs", NULL); file = fopen (config_file, "r"); free (config_file); if (file == NULL) goto error; user_dir = NULL; while (fgets (buffer, sizeof (buffer), file)) { /* Remove newline at end */ len = strlen (buffer); if (len > 0 && buffer[len-1] == '\n') buffer[len-1] = 0; p = buffer; while (*p == ' ' || *p == '\t') p++; if (!g_str_has_prefix (p, "XDG_PUBLICSHARE_DIR")) continue; p += strlen ("XDG_PUBLICSHARE_DIR"); while (*p == ' ' || *p == '\t') p++; if (*p != '=') continue; p++; while (*p == ' ' || *p == '\t') p++; if (*p != '"') continue; p++; relative = 0; if (strncmp (p, "$HOME/", 6) == 0) { p += 6; relative = 1; } else if (*p != '/') continue; if (relative) { user_dir = g_malloc (strlen (g_get_home_dir()) + 1 + strlen (p) + 1); strcpy (user_dir, g_get_home_dir ()); strcat (user_dir, "/"); } else { user_dir = g_malloc (strlen (p) + 1); *user_dir = 0; } d = user_dir + strlen (user_dir); while (*p && *p != '"') { if ((*p == '\\') && (*(p+1) != 0)) p++; *d++ = *p++; } *d = 0; } fclose (file); if (user_dir) return user_dir; error: return g_build_filename (g_get_home_dir (), "Public", NULL);}static intget_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_AVAHIstatic 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 gbooleancreate_service (void) { int ret; if (avahi_name == NULL) { avahi_name = g_strdup (get_share_name ()); } ret = avahi_entry_group_add_service (entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_PUBLISH_USE_MULTICAST, avahi_name, "_webdav._tcp", NULL, NULL, avahi_port, "u=guest", NULL); 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 voidavahi_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 gbooleaninit_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 gbooleanpublish_service (int port){ avahi_should_publish = TRUE; avahi_port = port; if (avahi_running) { create_service (); } return TRUE;}static voidstop_publishing (void){ avahi_should_publish = FALSE; avahi_entry_group_reset (entry_group);}#endif#ifdef HAVE_HOWLstatic sw_discovery_publish_id published_id = 0;static sw_discovery howl_session;static gbooleanhowl_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 voidset_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_resultpublish_reply (sw_discovery discovery, sw_discovery_publish_status status, sw_discovery_oid id, sw_opaque extra){ return SW_OKAY;}static gbooleanpublish_service (int port)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -