summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2008-12-01 09:24:00 +0000
committerAlexander Larsson <alexl@src.gnome.org>2008-12-01 09:24:00 +0000
commitf8875b2649a0f85624e0da7df96fa6d47840c4a9 (patch)
treedf7f32b8849652f03b597aead9f1b56d697d806a /daemon
parent6e89574f1656ff71f5aba339ff38e8e0417b172b (diff)
downloadgvfs-f8875b2649a0f85624e0da7df96fa6d47840c4a9.tar.gz
Added. Added. Added. Added.
2008-12-01 Alexander Larsson <alexl@redhat.com> * common/Makefile.am: * common/gvfsdnssdresolver.c: Added. * common/gvfsdnssdresolver.h: Added. * common/gvfsdnssdutils.c: Added. * common/gvfsdnssdutils.h: Added. * daemon/Makefile.am: * daemon/dav+sd.mount.in: Added. * daemon/dav.mount.in: * daemon/gvfsbackenddav.c: * daemon/gvfsbackenddnssd.c: * daemon/gvfsbackendnetwork.c: For references to dns-sd dav services, use a dav+sd: uri, since this is stable over e.g. port changes and as such work better in e.g. bookmarks. Patch from David Zeuthen (#555436) svn path=/trunk/; revision=2112
Diffstat (limited to 'daemon')
-rw-r--r--daemon/Makefile.am18
-rw-r--r--daemon/dav+sd.mount.in4
-rw-r--r--daemon/dav.mount.in2
-rw-r--r--daemon/gvfsbackenddav.c152
-rw-r--r--daemon/gvfsbackenddnssd.c218
-rw-r--r--daemon/gvfsbackendnetwork.c2
6 files changed, 307 insertions, 89 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 653018b8..035be2c1 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -42,6 +42,9 @@ mount_DATA = sftp.mount trash.mount computer.mount burn.mount localtest.mount
mount_in_files += http.mount.in dav.mount.in ftp.mount.in
if HAVE_HTTP
mount_DATA += http.mount dav.mount ftp.mount
+if HAVE_AVAHI
+mount_DATA += dav+sd.mount
+endif
libexec_PROGRAMS += gvfsd-http gvfsd-dav gvfsd-ftp
endif
@@ -304,7 +307,7 @@ gvfsd_dnssd_CPPFLAGS = \
$(AVAHI_CFLAGS) \
-DBACKEND_TYPES='"dns-sd", G_VFS_TYPE_BACKEND_DNS_SD,'
-gvfsd_dnssd_LDADD = $(libraries) $(AVAHI_LIBS)
+gvfsd_dnssd_LDADD = $(libraries) $(AVAHI_LIBS) $(top_builddir)/common/libgvfscommon-dnssd.la
gvfsd_archive_SOURCES = \
@@ -391,8 +394,15 @@ gvfsd_dav_CPPFLAGS = \
-DBACKEND_HEADER=gvfsbackenddav.h \
-DDEFAULT_BACKEND_TYPE=dav \
-DMAX_JOB_THREADS=1 \
- $(HTTP_CFLAGS) \
- -DBACKEND_TYPES='"dav", G_VFS_TYPE_BACKEND_DAV,'
+ $(HTTP_CFLAGS)
-gvfsd_dav_LDADD = $(libraries) $(HTTP_LIBS)
+if HAVE_AVAHI
+gvfsd_dav_CPPFLAGS += -DBACKEND_TYPES='"dav", G_VFS_TYPE_BACKEND_DAV, "dav+sd", G_VFS_TYPE_BACKEND_DAV, "davs+sd", G_VFS_TYPE_BACKEND_DAV,'
+else
+gvfsd_dav_CPPFLAGS += -DBACKEND_TYPES='"dav", G_VFS_TYPE_BACKEND_DAV,'
+endif
+gvfsd_dav_LDADD = $(libraries) $(HTTP_LIBS)
+if HAVE_AVAHI
+gvfsd_dav_LDADD += $(top_builddir)/common/libgvfscommon-dnssd.la
+endif
diff --git a/daemon/dav+sd.mount.in b/daemon/dav+sd.mount.in
new file mode 100644
index 00000000..45703270
--- /dev/null
+++ b/daemon/dav+sd.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=dav+sd;davs+sd
+Exec=@libexecdir@/gvfsd-dav
+AutoMount=false
diff --git a/daemon/dav.mount.in b/daemon/dav.mount.in
index 6e75bce7..6324625c 100644
--- a/daemon/dav.mount.in
+++ b/daemon/dav.mount.in
@@ -1,4 +1,4 @@
[Mount]
-Type=dav
+Type=dav;davs
Exec=@libexecdir@/gvfsd-dav
AutoMount=false
diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c
index 24c2b34c..a693ac90 100644
--- a/daemon/gvfsbackenddav.c
+++ b/daemon/gvfsbackenddav.c
@@ -61,10 +61,20 @@
#include "soup-input-stream.h"
#include "soup-output-stream.h"
+#ifdef HAVE_AVAHI
+#include "gvfsdnssdutils.h"
+#include "gvfsdnssdresolver.h"
+#endif
+
typedef struct _MountAuthData MountAuthData;
static void mount_auth_info_free (MountAuthData *info);
+
+#ifdef HAVE_AVAHI
+static void dns_sd_resolver_changed (GVfsDnsSdResolver *resolver, GVfsBackendDav *dav_backend);
+#endif
+
typedef struct _AuthInfo {
/* for server authentication */
@@ -91,6 +101,11 @@ struct _GVfsBackendDav
GVfsBackendHttp parent_instance;
MountAuthData auth_info;
+
+#ifdef HAVE_AVAHI
+ /* only set if we're handling a [dav|davs]+sd:// mounts */
+ GVfsDnsSdResolver *resolver;
+#endif
};
G_DEFINE_TYPE (GVfsBackendDav, g_vfs_backend_dav, G_VFS_TYPE_BACKEND_HTTP);
@@ -102,6 +117,14 @@ g_vfs_backend_dav_finalize (GObject *object)
dav_backend = G_VFS_BACKEND_DAV (object);
+#ifdef HAVE_AVAHI
+ if (dav_backend->resolver != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (dav_backend->resolver, dns_sd_resolver_changed, dav_backend);
+ g_object_unref (dav_backend->resolver);
+ }
+#endif
+
mount_auth_info_free (&(dav_backend->auth_info));
if (G_OBJECT_CLASS (g_vfs_backend_dav_parent_class)->finalize)
@@ -209,10 +232,10 @@ path_equal (const char *a, const char *b, gboolean relax)
a_len = strlen (a);
b_len = strlen (b);
- while (a[a_len - 1] == '/')
+ while (a_len > 0 && a[a_len - 1] == '/')
a_len--;
- while (b[b_len - 1] == '/')
+ while (b_len > 0 && b[b_len - 1] == '/')
b_len--;
if (a_len == b_len)
@@ -1392,11 +1415,32 @@ g_mount_spec_to_dav_uri (GMountSpec *spec)
}
static GMountSpec *
-g_mount_spec_from_dav_uri (SoupURI *uri)
+g_mount_spec_from_dav_uri (GVfsBackendDav *dav_backend,
+ SoupURI *uri)
{
GMountSpec *spec;
const char *ssl;
+#ifdef HAVE_AVAHI
+ if (dav_backend->resolver != NULL)
+ {
+ const char *type;
+ const char *service_type;
+
+ service_type = g_vfs_dns_sd_resolver_get_service_type (dav_backend->resolver);
+ if (strcmp (service_type, "_webdavs._tcp") == 0)
+ type = "davs+sd";
+ else
+ type = "dav+sd";
+
+ spec = g_mount_spec_new (type);
+ g_mount_spec_set (spec,
+ "host",
+ g_vfs_dns_sd_resolver_get_encoded_triple (dav_backend->resolver));
+ return spec;
+ }
+#endif
+
spec = g_mount_spec_new ("dav");
g_mount_spec_set (spec, "host", uri->host);
@@ -1423,6 +1467,63 @@ g_mount_spec_from_dav_uri (SoupURI *uri)
return spec;
}
+#ifdef HAVE_AVAHI
+static SoupURI *
+dav_uri_from_dns_sd_resolver (GVfsBackendDav *dav_backend)
+{
+ SoupURI *uri;
+ char *user;
+ char *path;
+ char *address;
+ const char *service_type;
+ guint port;
+
+ service_type = g_vfs_dns_sd_resolver_get_service_type (dav_backend->resolver);
+ address = g_vfs_dns_sd_resolver_get_address (dav_backend->resolver);
+ port = g_vfs_dns_sd_resolver_get_port (dav_backend->resolver);
+ user = g_vfs_dns_sd_resolver_lookup_txt_record (dav_backend->resolver, "u"); /* mandatory */
+ path = g_vfs_dns_sd_resolver_lookup_txt_record (dav_backend->resolver, "path"); /* optional */
+
+ /* TODO: According to http://www.dns-sd.org/ServiceTypes.html
+ * there's also a TXT record "p" for password. Handle this.
+ */
+
+ uri = soup_uri_new (NULL);
+
+ if (strcmp (service_type, "_webdavs._tcp") == 0)
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS);
+ else
+ soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP);
+
+ soup_uri_set_user (uri, user);
+
+ soup_uri_set_port (uri, port);
+
+ soup_uri_set_host (uri, address);
+
+ if (path != NULL)
+ soup_uri_set_path (uri, path);
+ else
+ soup_uri_set_path (uri, "/");
+
+
+ g_free (address);
+ g_free (user);
+ g_free (path);
+
+ return uri;
+}
+#endif
+
+#ifdef HAVE_AVAHI
+static void
+dns_sd_resolver_changed (GVfsDnsSdResolver *resolver,
+ GVfsBackendDav *dav_backend)
+{
+ /* TODO: handle when DNS-SD data changes */
+}
+#endif
+
/* ************************************************************************* */
/* Backend Functions */
static void
@@ -1432,6 +1533,7 @@ do_mount (GVfsBackend *backend,
GMountSource *mount_source,
gboolean is_automount)
{
+ GVfsBackendDav *dav_backend = G_VFS_BACKEND_DAV (backend);
MountAuthData *data;
SoupSession *session;
SoupMessage *msg_opts;
@@ -1444,10 +1546,43 @@ do_mount (GVfsBackend *backend,
gboolean res;
char *last_good_path;
char *display_name;
+ const char *host;
+ const char *type;
g_print ("+ mount\n");
- mount_base = g_mount_spec_to_dav_uri (mount_spec);
+ host = g_mount_spec_get (mount_spec, "host");
+ type = g_mount_spec_get (mount_spec, "type");
+
+#ifdef HAVE_AVAHI
+ /* resolve DNS-SD style URIs */
+ if ((strcmp (type, "dav+sd") == 0 || strcmp (type, "davs+sd") == 0) && host != NULL)
+ {
+ GError *error;
+
+ dav_backend->resolver = g_vfs_dns_sd_resolver_new_for_encoded_triple (host, "u");
+
+ error = NULL;
+ if (!g_vfs_dns_sd_resolver_resolve_sync (dav_backend->resolver,
+ NULL,
+ &error))
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ return;
+ }
+ g_signal_connect (dav_backend->resolver,
+ "changed",
+ (GCallback) dns_sd_resolver_changed,
+ dav_backend);
+
+ mount_base = dav_uri_from_dns_sd_resolver (dav_backend);
+ }
+ else
+#endif
+ {
+ mount_base = g_mount_spec_to_dav_uri (mount_spec);
+ }
if (mount_base == NULL)
{
@@ -1546,12 +1681,17 @@ do_mount (GVfsBackend *backend,
mount_base->path = last_good_path;
/* dup the mountspec, but only copy known fields */
- mount_spec = g_mount_spec_from_dav_uri (mount_base);
+ mount_spec = g_mount_spec_from_dav_uri (dav_backend, mount_base);
g_vfs_backend_set_mount_spec (backend, mount_spec);
g_vfs_backend_set_icon_name (backend, "folder-remote");
- display_name = g_strdup_printf (_("WebDAV on %s"), mount_base->host);
+#ifdef HAVE_AVAHI
+ if (dav_backend->resolver != NULL)
+ display_name = g_strdup (g_vfs_dns_sd_resolver_get_service_name (dav_backend->resolver));
+ else
+#endif
+ display_name = g_strdup_printf (_("WebDAV on %s"), mount_base->host);
g_vfs_backend_set_display_name (backend, display_name);
g_free (display_name);
diff --git a/daemon/gvfsbackenddnssd.c b/daemon/gvfsbackenddnssd.c
index 3a224a50..9ef21eaa 100644
--- a/daemon/gvfsbackenddnssd.c
+++ b/daemon/gvfsbackenddnssd.c
@@ -37,6 +37,7 @@
#include <avahi-glib/glib-malloc.h>
#include "gvfsbackenddnssd.h"
+#include "gvfsdnssdutils.h"
#include "gvfsdaemonprotocol.h"
#include "gvfsjobcreatemonitor.h"
@@ -45,15 +46,40 @@
#include "gvfsmonitor.h"
static struct {
- char *type;
- char *method;
- char *icon;
- gpointer handle;
+ char *type;
+ char *method;
+ gboolean use_dns_sd_uri;
+ char *icon;
} dns_sd_types[] = {
- {"_ftp._tcp", "ftp", "folder-remote-ftp"},
- {"_webdav._tcp", "dav", "folder-remote"},
- {"_webdavs._tcp", "davs", "folder-remote"},
- {"_sftp-ssh._tcp", "sftp", "folder-remote-ssh"},
+ {
+ "_ftp._tcp",
+ "ftp",
+ FALSE,
+ "folder-remote-ftp"
+ },
+ {
+ "_webdav._tcp",
+ "dav+sd",
+ TRUE,
+ "folder-remote-dav"
+ },
+ {
+ "_webdavs._tcp",
+ "davs+sd",
+ TRUE,
+ "folder-remote-davs"},
+ {
+ "_sftp-ssh._tcp",
+ "sftp",
+ FALSE,
+ "folder-remote-ssh"
+ },
+ {
+ "_ssh._tcp",
+ "sftp",
+ FALSE,
+ "folder-remote-ssh"
+ },
};
static AvahiClient *global_client = NULL;
@@ -62,15 +88,19 @@ static gboolean avahi_initialized = FALSE;
static GList *dnssd_backends = NULL;
typedef struct {
- char *file_name;
+ char *file_name;
char *name;
char *type;
+ char *domain;
char *target_uri;
+
GIcon *icon;
} LinkFile;
static LinkFile root = { "/" };
+static gboolean resolver_supports_mdns = FALSE;
+
struct _GVfsBackendDnsSd
{
GVfsBackend parent_instance;
@@ -164,7 +194,7 @@ get_icon_for_type (const char *type)
for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++)
{
if (strcmp (type, dns_sd_types[i].type) == 0)
- return g_themed_icon_new (dns_sd_types[i].icon);
+ return g_themed_icon_new_with_default_fallbacks (dns_sd_types[i].icon);
}
return g_themed_icon_new ("text-x-generic");
@@ -184,34 +214,18 @@ get_method_for_type (const char *type)
return NULL;
}
-static char *
-encode_filename (const char *service,
- const char *type)
+static gboolean
+use_dns_sd_uri_for_type (const char *type)
{
- GString *string;
- const char *p;
-
- string = g_string_new (NULL);
-
- p = service;
-
- while (*p)
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++)
{
- if (*p == '\\')
- g_string_append (string, "\\\\");
- else if (*p == '.')
- g_string_append (string, "\\.");
- else if (*p == '/')
- g_string_append (string, "\\s");
- else
- g_string_append_c (string, *p);
- p++;
+ if (strcmp (type, dns_sd_types[i].type) == 0)
+ return dns_sd_types[i].use_dns_sd_uri;
}
-
- g_string_append_c (string, '.');
- g_string_append (string, type);
-
- return g_string_free (string, FALSE);
+
+ return FALSE;
}
static LinkFile *
@@ -225,56 +239,89 @@ link_file_new (const char *name,
AvahiStringList *txt)
{
LinkFile *file;
- char *path, *user, *user_str;
- AvahiStringList *path_l, *user_l;
char a[128];
const char *method;
-
+ char *uri;
+
file = g_slice_new0 (LinkFile);
file->name = g_strdup (name);
file->type = g_strdup (type);
- file->file_name = encode_filename (name, type);
+ file->domain = g_strdup (domain);
file->icon = get_icon_for_type (type);
-
- path = NULL;
- user_str = NULL;
- if (txt != NULL)
- {
- path_l = avahi_string_list_find (txt, "path");
- if (path_l != NULL)
- avahi_string_list_get_pair (path_l, NULL, &path, NULL);
-
- user_l = avahi_string_list_find (txt, "u");
- if (user_l != NULL)
- {
- avahi_string_list_get_pair (user_l, NULL, &user, NULL);
-
- user_str = g_strconcat (user, "@", NULL);
- }
- }
-
- if (path == NULL)
- path = g_strdup ("/");
-
+ uri = g_vfs_get_dns_sd_uri_for_triple (name, type, domain);
+ file->file_name = g_path_get_basename (uri);
+ g_free (uri);
+
avahi_address_snprint (a, sizeof(a), address);
method = get_method_for_type (type);
- if (protocol == AVAHI_PROTO_INET6)
- /* an ipv6 address, follow rfc2732 */
- file->target_uri = g_strdup_printf ("%s://%s[%s]:%d%s",
- method,
- user_str?user_str:"",
- a, port, path);
+ if (use_dns_sd_uri_for_type (type))
+ {
+ char *encoded_triple;
+ encoded_triple = g_vfs_encode_dns_sd_triple (name, type, domain);
+ file->target_uri = g_strdup_printf ("%s://%s",
+ method,
+ encoded_triple);
+ g_free (encoded_triple);
+ }
else
- file->target_uri = g_strdup_printf ("%s://%s%s:%d%s",
- method,
- user_str?user_str:"",
- a, port, path);
- g_free (user_str);
- g_free (path);
+ {
+ char *path, *user, *user_str;
+ AvahiStringList *path_l, *user_l;
+
+ path = NULL;
+ user_str = NULL;
+ if (txt != NULL)
+ {
+ path_l = avahi_string_list_find (txt, "path");
+ if (path_l != NULL)
+ avahi_string_list_get_pair (path_l, NULL, &path, NULL);
+ user_l = avahi_string_list_find (txt, "u");
+ if (user_l != NULL)
+ {
+ avahi_string_list_get_pair (user_l, NULL, &user, NULL);
+ user_str = g_strconcat (user, "@", NULL);
+ }
+ }
+ if (path == NULL)
+ path = g_strdup ("/");
+
+ if (resolver_supports_mdns)
+ {
+ file->target_uri = g_strdup_printf ("%s://%s%s:%d%s",
+ method,
+ user_str != NULL ? user_str : "",
+ host_name, port, path);
+ }
+ else
+ {
+ if (protocol == AVAHI_PROTO_INET6)
+ {
+ /* an ipv6 address, follow rfc2732 */
+ file->target_uri = g_strdup_printf ("%s://%s[%s]:%d%s",
+ method,
+ user_str?user_str:"",
+ a,
+ port,
+ path);
+ }
+ else
+ {
+ file->target_uri = g_strdup_printf ("%s://%s%s:%d%s",
+ method,
+ user_str?user_str:"",
+ a,
+ port,
+ path);
+ }
+ }
+
+ g_free (user_str);
+ g_free (path);
+ }
return file;
}
@@ -285,6 +332,7 @@ link_file_free (LinkFile *file)
g_free (file->file_name);
g_free (file->name);
g_free (file->type);
+ g_free (file->domain);
g_free (file->target_uri);
if (file->icon)
@@ -357,7 +405,7 @@ file_info_from_file (LinkFile *file,
g_file_info_set_name (info, file->file_name);
g_file_info_set_display_name (info, file->name);
- if (file->icon)
+ if (file->icon)
g_file_info_set_icon (info, file->icon);
g_file_info_set_file_type (info, G_FILE_TYPE_SHORTCUT);
@@ -366,8 +414,7 @@ file_info_from_file (LinkFile *file,
g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_VIRTUAL, TRUE);
- g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI,
- file->target_uri);
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, file->target_uri);
}
/* Backend Functions */
@@ -427,13 +474,28 @@ try_query_info (GVfsBackend *backend,
if (file == &root)
{
GIcon *icon;
+ char *display_name;
+ char *s;
+
+ s = g_strdup (job->uri);
+ if (s[strlen(s) - 1] == '/') /* job->uri is guranteed to be longer than 1 byte */
+ s[strlen(s) - 1] = '\0';
+ display_name = g_path_get_basename (s);
+ if (strcmp (display_name, "local") == 0)
+ {
+ g_free (display_name);
+ display_name = g_strdup (_("Local Network"));
+ }
+ g_free (s);
+
g_file_info_set_name (info, "/");
g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
- /* TODO: Name */
- g_file_info_set_display_name (info, _("dns-sd"));
+ g_file_info_set_display_name (info, display_name);
icon = g_themed_icon_new ("network-workgroup");
g_file_info_set_icon (info, icon);
g_object_unref (icon);
+ g_free (display_name);
+
g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, FALSE);
g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, FALSE);
g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, FALSE);
@@ -689,6 +751,8 @@ g_vfs_backend_dns_sd_init (GVfsBackendDnsSd *network_backend)
g_vfs_backend_set_icon_name (backend, "network-workgroup");
g_vfs_backend_set_user_visible (backend, FALSE);
+ resolver_supports_mdns = (avahi_nss_support () > 0);
+
}
static void
diff --git a/daemon/gvfsbackendnetwork.c b/daemon/gvfsbackendnetwork.c
index d23438e7..939461e3 100644
--- a/daemon/gvfsbackendnetwork.c
+++ b/daemon/gvfsbackendnetwork.c
@@ -411,7 +411,7 @@ recompute_files (GVfsBackendNetwork *backend)
file = network_file_new (file_name,
domains[i],
link_uri,
- backend->server_icon);
+ backend->workgroup_icon);
files = g_list_prepend (files, file);
g_free (link_uri);
g_free (file_name);