Index: daemon/gvfsbackendnetwork.c
===================================================================
--- daemon/gvfsbackendnetwork.c	(revision 0)
+++ daemon/gvfsbackendnetwork.c	(revision 0)
@@ -0,0 +1,719 @@
+/* gvfs-backend-network.c - 
+ * Original work, Copyright (C) 2003 Red Hat, Inc
+ * GVFS port, Copyright (c) 2008 Andrew Walton.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *       Alexander Larsson <alexl@redhat.com>
+ *       Andrew Walton <awalton@svn.gnome.org> (port only)
+ */
+
+/* 
+  TODO: 
+	Add DNS-SD when there's an appropriate backend.
+	Add file/directory monitor events (only really necessary after we add DNS-SD).
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <glib/gurifuncs.h>
+
+#include <gconf/gconf-client.h>
+
+#include "gvfsbackendnetwork.h"
+#include "gvfsmonitor.h"
+#include "gvfsjobopenforread.h"
+#include "gvfsjobread.h"
+#include "gvfsjobcloseread.h"
+#include "gvfsjobqueryinfo.h"
+#include "gvfsjobenumerate.h"
+#include "gvfsjobcreatemonitor.h"
+#include "gvfsdaemonprotocol.h"
+
+#define PATH_GCONF_GVFS_SMB "/system/smb"
+#define PATH_GCONF_GVFS_SMB_WORKGROUP "/system/smb/workgroup"
+#define PATH_GCONF_GVFS_DNS_SD "/system/dns_sd"
+#define PATH_GCONF_GVFS_DNS_SD_DISPLAY_LOCAL "/system/dns_sd/display_local"
+#define PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS "/system/dns_sd/extra_domains"
+#define DEFAULT_WORKGROUP_NAME "X-GNOME-DEFAULT-WORKGROUP"
+
+typedef struct {
+	char *filename; 
+	char *display_name;
+	char *target_uri;
+	int prio;
+        char *contents;
+	GFile *root;
+	GIcon *icon;
+} NetworkFile;
+
+static NetworkFile root = { "/" };
+
+struct _GVfsBackendNetwork
+{
+	GVfsBackend parent_instance;
+	GVfsMonitor *root_monitor;
+	GMountSpec *mount_spec;
+
+	GList *files; /* list of NetworkFiles */
+
+	/* SMB Stuff */
+	gboolean have_smb;
+	char *current_workgroup; 
+
+#if 0
+	/* DNS-SD stuff */
+	gboolean have_dnssd;
+	GList *current_dns_sd_domains;
+	NetworkLocalSetting gconf_local_setting;
+	char *gconf_extra_domains;
+#endif
+};
+
+typedef struct _GVfsBackendNetwork GVfsBackendNetwork;
+
+G_DEFINE_TYPE (GVfsBackendNetwork, g_vfs_backend_network, G_VFS_TYPE_BACKEND);
+
+
+#if 0
+/* DNS-SD support machinery. */
+typedef enum {
+	NETWORK_LOCAL_DISABLED,
+	NETWORK_LOCAL_MERGED,
+	NETWORK_LOCAL_SEPARATE
+} NetworkLocalSetting;
+
+static NetworkLocalSetting
+parse_network_local_setting (const char *setting)
+{
+	if (setting == NULL)
+		return NETWORK_LOCAL_DISABLED;
+	if (strcmp (setting, "separate") == 0)
+		return NETWORK_LOCAL_SEPARATE;
+	if (strcmp (setting, "merged") == 0)
+		return NETWORK_LOCAL_MERGED;
+	return NETWORK_LOCAL_DISABLED;
+}
+
+/* >_> */
+static void
+network_file_new_for_dns_sd_domain (GVfsBackend *backend, const char *domain)
+{
+	char *filename, *target_uri;
+
+	NetworkFile *dns_sd_link;
+	dns_sd_link = g_slice_new (NetworkFile);
+
+	filename = g_strconcat ("dnssdlink-", domain, NULL);
+	target_uri = g_strdup_printf ("dns-sd://%s/", domain);
+	redirect->icon = g_themed_icon_new ("gnome-fs-network");
+
+	backend->files = g_list_prepend (backend->files, dns_sd_link);
+}
+
+static void
+notify_gconf_extra_domains_changed (GConfClient *client,
+				    guint        cnxn_id,
+				    GConfEntry  *entry,
+				    gpointer     data)
+{
+	GVfsBackendNetwork *backend = GVFS_BACKEND_NETWORK(data);
+
+	char *domain_string;
+	char **domains;
+	int i;
+
+	domain_string = gconf_client_get_string (client,
+ 		PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS, NULL);
+	
+	domains = g_strsplit (domain_string, ",", 0);
+
+	for (i = 0; domains[i] != NULL; i++) {
+		/* yeah, this is obviously wrong too, 
+		 * but we'll cross that bridge when we get there. */
+		network_file_new_for_dns_sd_domain (backend, domains[i]);
+	}
+	
+	g_strfreev (domains);
+	g_free(domain_string);
+}
+
+#endif
+
+/* Network "File" stuff; these are real "files";
+ * a stack of .desktop links to SMB and DNS-SD "domains"/"workgroups". */
+
+static void
+populate_file_contents (NetworkFile *file)
+{
+	const char * const *icons = g_themed_icon_get_names(G_THEMED_ICON(file->icon));
+	char *data;
+	data = g_strdup_printf ("[Desktop Entry]\n"
+				"Encoding=UTF-8\n"
+				"Name=%s\n"
+				"Type=FSDevice\n"
+				"Icon=%s\n"
+				"URL=%s\n",
+				file->display_name,
+				icons[0],
+				file->target_uri);
+
+	if (file->contents != NULL)
+		g_free (file->contents);
+
+	file->contents = data;
+}
+
+static NetworkFile *
+network_file_new (const char *filename, 
+		  const char *display_name, 
+		  const char *target_uri, 
+		  const char *icon)
+{
+	NetworkFile *file;
+	file = g_slice_new (NetworkFile);
+
+	file->filename = g_strdup (filename);
+	file->display_name = g_strdup (display_name);
+	file->target_uri = g_strdup (target_uri);
+	file->icon     = g_themed_icon_new (icon);
+	file->root = g_file_new_for_path ("/");
+	file->prio = 0;
+
+	populate_file_contents (file);
+
+	return file;
+}
+
+static void
+network_file_free (NetworkFile *file)
+{
+	if (file->filename)
+    		g_free (file->filename);
+
+ 	if (file->display_name)
+		g_free (file->display_name);
+
+	if (file->contents)
+		g_free (file->contents);
+
+	if (file->target_uri)
+		g_free (file->target_uri);
+ 
+	if (file->icon)
+		g_object_unref (file->icon);
+
+	if (file->root)
+		g_object_unref (file->root);
+
+	g_slice_free (NetworkFile, file);
+}
+
+#if 0
+/* we'll need this for DNS-SD */
+static gboolean
+network_file_equal (NetworkFile *a,
+                    NetworkFile *b)
+{
+	if (strcmp (a->filename, b->filename) != 0)
+		return FALSE;
+	if (strcmp (a->display_name, b->display_name) != 0)
+		return FALSE;
+
+	if (!g_icon_equal (a->icon, b->icon))
+		return FALSE;
+      
+	if ((a->root != NULL && b->root != NULL &&
+		!g_file_equal (a->root, b->root)) ||
+		(a->root != NULL && b->root == NULL) ||
+		(a->root == NULL && b->root != NULL))
+		return FALSE;
+
+	if (a->prio != b->prio)
+		return FALSE;
+
+	return TRUE;
+}
+#endif
+
+static void
+notify_gconf_value_changed (GConfClient *client,
+			    guint        cnxn_id,
+			    GConfEntry  *entry,
+			    gpointer     data)
+{
+	GVfsBackendNetwork *backend = G_VFS_BACKEND_NETWORK(data);
+
+	char *current_workgroup;
+
+	current_workgroup = gconf_client_get_string (client,
+		PATH_GCONF_GVFS_SMB_WORKGROUP, NULL);
+
+	g_free(backend->current_workgroup);
+	backend->current_workgroup = current_workgroup;
+
+	g_message ("GConf now says to use \"%s\" as our workgroup.", backend->current_workgroup);
+}
+
+static int
+sort_file_by_filename (NetworkFile *a, NetworkFile *b)
+{
+	return strcmp (a->filename, b->filename);
+}
+
+static void
+recompute_files (GVfsBackendNetwork *backend)
+{
+	NetworkFile *file;
+
+	g_list_foreach (backend->files, (GFunc)network_file_free, NULL);
+
+	if (backend->have_smb) {
+		file = network_file_new ("smblink-root", _("Windows Network"), "smb:///", "gnome-fs-network");
+		backend->files = g_list_prepend (backend->files, file);
+		if (backend->current_workgroup == NULL || !backend->current_workgroup[0])
+		{
+			char *workgroup = g_strdup_printf("smb://%s/", DEFAULT_WORKGROUP_NAME);
+			file = network_file_new ("smblink-workgroup", _("Default Workgroup"), workgroup, "gnome-fs-network");
+			backend->files = g_list_prepend (backend->files, file);
+			g_free(workgroup);
+		} else {
+			char *workgroup = g_strdup_printf("smb://%s/", backend->current_workgroup);
+			file = network_file_new ("smblink-workgroup", backend->current_workgroup, workgroup, "gnome-fs-network");
+			backend->files = g_list_prepend (backend->files, file);
+			g_free(workgroup);		
+		}
+	}
+
+
+	#if 0
+	/* TODO: implement me, DNS-SD */
+	if (backend->have_dnssd) {
+	
+	}
+	#endif
+
+	backend->files = g_list_sort (backend->files, (GCompareFunc)sort_file_by_filename);
+}
+
+static NetworkFile *
+lookup_network_file (GVfsBackendNetwork *backend,
+                     GVfsJob *job,
+                     const char *filename)
+{
+	GList *l;
+	NetworkFile *file;
+
+	if (*filename != '/')
+		goto out;
+
+	while (*filename == '/')
+		filename++;
+
+	if (*filename == 0)
+		return &root;
+	
+	if (strchr (filename, '/') != NULL)
+		goto out;
+	
+	for (l = backend->files; l != NULL; l = l->next)
+	{
+		file = l->data;
+		if (strcmp (file->filename, filename) == 0)
+			return file;
+	}
+
+	out:
+	g_vfs_job_failed (job, G_IO_ERROR,
+		G_IO_ERROR_NOT_FOUND,
+		_("File doesn't exist"));
+
+	return NULL;
+}
+
+
+static void
+file_info_from_file (NetworkFile *file,
+                     GFileInfo *info)
+{
+	char *uri;
+	g_message("Getting GFileInfo for %s", file->filename);
+	
+	g_file_info_set_name (info, file->filename);
+	g_file_info_set_display_name (info, file->display_name);
+
+	if (file->icon) {
+		g_file_info_set_icon (info, file->icon);
+	}
+
+	if (file->root)
+	{
+		uri = g_file_get_uri (file->root);
+		g_file_info_set_attribute_string(info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, uri);
+		g_free (uri);
+	}
+
+	g_file_info_set_sort_order (info, file->prio);
+
+	/* we have to call them regular files as they are not symlinks but .desktop links. */
+	g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
+	
+	gsize fsize;
+	if (file->contents != NULL) {
+		fsize = strlen(file->contents);
+	} else {
+		populate_file_contents (file);
+		fsize = strlen(file->contents);
+	}		
+
+	g_file_info_set_size(info, fsize);
+	g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE);
+	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);
+	g_file_info_set_content_type (info, "application/x-desktop");
+
+	/* little bit of stuff here to make looking up network links faster for those who 
+	 * who know about the STANDARD_TARGET_URI attrib. */
+	g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, file->target_uri);
+}
+
+/* Backend Functions */
+static gboolean
+try_enumerate (GVfsBackend *backend,
+               GVfsJobEnumerate *job,
+               const char *filename,
+               GFileAttributeMatcher *attribute_matcher,
+               GFileQueryInfoFlags flags)
+{
+	NetworkFile *file;
+	GList *l;
+	GFileInfo *info;
+
+	file = lookup_network_file (G_VFS_BACKEND_NETWORK (backend),
+		 G_VFS_JOB (job), filename);
+	
+	if (file != &root)
+	{
+		if (file != NULL)
+			g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+				G_IO_ERROR_NOT_DIRECTORY,
+				_("The file is not a directory"));
+		return TRUE;
+	}
+
+	/* Enumerate root */
+	for (l = G_VFS_BACKEND_NETWORK (backend)->files; l != NULL; l = l->next)
+	{
+		file = l->data;
+		g_message ("adding file to enumeration: %s", file->display_name);
+		
+		info = g_file_info_new ();
+		
+		file_info_from_file (file, info);
+		g_vfs_job_enumerate_add_info (job, info);
+		g_object_unref (info);
+	}
+
+	g_vfs_job_enumerate_done (job);
+	g_vfs_job_succeeded (job);
+	
+	return TRUE;
+}
+
+static gboolean
+try_query_info (GVfsBackend *backend,
+                GVfsJobQueryInfo *job,
+                const char *filename,
+                GFileQueryInfoFlags flags,
+                GFileInfo *info,
+                GFileAttributeMatcher *matcher)
+{
+	NetworkFile *file;
+
+	file = lookup_network_file (G_VFS_BACKEND_NETWORK (backend), G_VFS_JOB (job), filename);
+
+	if (file == &root)
+	{
+		GIcon *icon;
+      		g_file_info_set_name (info, "/");
+		g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
+		g_file_info_set_display_name (info, _("Network"));
+		icon = g_themed_icon_new ("gnome-fs-network");
+		g_file_info_set_icon (info, icon);
+		g_object_unref (icon);
+		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);
+		g_file_info_set_content_type (info, "inode/directory");
+	}
+	else if (file != NULL) {
+		file_info_from_file (file, info);
+	}
+
+	g_vfs_job_succeeded (G_VFS_JOB (job));
+  
+	return TRUE;
+}
+
+static gboolean
+try_mount (GVfsBackend *backend,
+           GVfsJobMount *job,
+           GMountSpec *mount_spec,
+           GMountSource *mount_source,
+           gboolean is_automount)
+{
+	GVfsBackendNetwork *network_backend = G_VFS_BACKEND_NETWORK (backend);
+	network_backend->root_monitor = g_vfs_monitor_new (backend);
+	recompute_files (network_backend);
+	g_vfs_job_succeeded (G_VFS_JOB (job));
+
+	return TRUE;
+}
+
+typedef struct {
+	NetworkFile *file;
+	gsize read_cursor;
+	gsize file_size;
+} ReadHandle;
+
+static void
+do_open_for_read (GVfsBackend *backend,
+		  GVfsJobOpenForRead *job,
+		  const char *filename)
+{
+	NetworkFile *file;
+	ReadHandle *handle;
+
+	file = lookup_network_file (G_VFS_BACKEND_NETWORK (backend),  G_VFS_JOB (job), filename);
+
+	if (file == &root) {
+		g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+			G_IO_ERROR_IS_DIRECTORY,
+			_("Can't open directory"));
+	}
+
+	handle = g_new0 (ReadHandle, 1);
+	handle->file = file;
+	handle->read_cursor = 0;
+	if (file->contents != NULL) {
+		handle->file_size = strlen (file->contents);
+	} else {
+		populate_file_contents(file);		
+		handle->file_size = strlen (file->contents);
+	}
+
+	g_vfs_job_open_for_read_set_can_seek (job, FALSE);
+	g_vfs_job_open_for_read_set_handle (job, GINT_TO_POINTER (handle));
+	g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+
+static void
+do_read (GVfsBackend *backend,
+	 GVfsJobRead *job,
+	 GVfsBackendHandle handle,
+	 char *buffer,
+	 gsize bytes_requested)
+{
+	ReadHandle *read_handle = (ReadHandle *)handle;
+	gsize read_size = bytes_requested;
+
+	if (read_handle->read_cursor >= read_handle->file_size ) {
+		/* EOF */
+		g_vfs_job_read_set_size (job, 0);
+	} else {
+		/* clamp the read size */
+		if (read_size >= read_handle->file_size - read_handle->read_cursor ) { 
+			read_size = read_handle->file_size - read_handle->read_cursor; 	
+		}
+
+		g_assert(read_size >= 0);
+		memcpy (buffer, read_handle->file->contents, read_size);			
+		g_vfs_job_read_set_size (job, read_size);
+		read_handle->read_cursor += read_size;
+	}
+	
+	g_vfs_job_succeeded (job);
+}
+
+static void
+do_close_read  (GVfsBackend *backend,
+	   	GVfsJobCloseRead *job,
+		GVfsBackendHandle handle)
+{
+	g_free (handle);
+	g_vfs_job_succeeded (job);
+}
+
+/* handles both file and dir monitors, 
+ * as we really don't "support" (e.g. fire events for) either, yet. */
+static gboolean
+try_create_monitor (GVfsBackend *backend,
+                    GVfsJobCreateMonitor *job,
+                    const char *filename,
+                    GFileMonitorFlags flags)
+{
+	NetworkFile *file;
+	GVfsBackendNetwork *network_backend;
+
+	network_backend = G_VFS_BACKEND_NETWORK (backend);
+
+	file = lookup_network_file (network_backend, G_VFS_JOB (job), filename);
+
+	if (file != &root)
+	{
+		g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
+			G_IO_ERROR_NOT_SUPPORTED,
+			_("Can't monitor file or directory."));
+		return TRUE;
+	}
+  
+	g_vfs_job_create_monitor_set_monitor (job, network_backend->root_monitor);
+	g_vfs_job_succeeded (G_VFS_JOB (job));
+
+	return TRUE;
+}
+
+static void
+g_vfs_backend_network_init (GVfsBackendNetwork *network_backend)
+{
+	GVfsBackend *backend = G_VFS_BACKEND (network_backend);
+	GMountSpec *mount_spec;
+	char *current_workgroup;
+	GConfClient *gconf_client;
+	const char * const* supported_vfs;
+	int i;
+
+#if 0
+	/* we're not exactly ready for this code yet... (lifted from GnomeVFS) */
+	gconf_client_add_dir (gconf_client, 
+		PATH_GCONF_GVFS_DNS_SD, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+	gconf_extra_domains = gconf_client_get_string (gconf_client, 
+		PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS, NULL);
+
+	add_dns_sd_domains (gconf_extra_domains);
+
+	gconf_client_notify_add (gconf_client, PATH_GCONF_GVFS_DNS_SD_EXTRA_DOMAINS, 
+		notify_gconf_extra_domains_changed, backend, NULL, NULL);
+
+	setting = gconf_client_get_string (gconf_client,
+		PATH_GCONF_GVFS_DNS_SD_DISPLAY_LOCAL, NULL);
+	gconf_local_setting = parse_network_local_setting (setting);
+	g_free (setting);
+
+	switch (gconf_local_setting) {
+		case NETWORK_LOCAL_MERGED:
+		add_redirect (backend, "dnssd-local-", "dns-sd://local/");
+			break;
+		case NETWORK_LOCAL_SEPARATE:
+			add_dns_sd_domain ("local");
+			break;
+		default:
+			break;
+	}
+
+#endif
+
+	gconf_client = gconf_client_get_default ();
+
+	gconf_client_add_dir (gconf_client, 
+		PATH_GCONF_GVFS_SMB, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+	current_workgroup = gconf_client_get_string (gconf_client, 
+		PATH_GCONF_GVFS_SMB_WORKGROUP, NULL);
+
+	g_message ("GConf says to use \"%s\" as our workgroup", current_workgroup);
+
+	if (current_workgroup == NULL || !current_workgroup[0]) {
+		/* it's okay if current_workgroup is null here, 
+		 * it's checked before the NetworkFile is added anyway. */
+		g_message ("...which is obviously invalid. We'll catch it later.");
+		network_backend->current_workgroup = NULL;
+	} else {
+		network_backend->current_workgroup = current_workgroup;
+	}
+
+	gconf_client_notify_add (gconf_client, PATH_GCONF_GVFS_SMB_WORKGROUP, 
+		notify_gconf_value_changed, backend, NULL, NULL);
+
+	g_object_unref (gconf_client);
+
+	supported_vfs = g_vfs_get_supported_uri_schemes (g_vfs_get_default ());
+
+	network_backend->have_smb = FALSE;
+	for (i=0; supported_vfs[i]!=NULL; i++)
+	{
+		if (strcmp(supported_vfs[i], "smb") == 0 )
+		{
+			g_message("GVFSd says we have Samba, so we're using it");
+			network_backend->have_smb = TRUE;
+		}
+	}
+
+	g_vfs_backend_set_display_name (backend, _("Network"));
+	g_vfs_backend_set_stable_name (backend, _("Network"));
+	g_vfs_backend_set_icon_name (backend, "gnome-fs-network");
+	g_vfs_backend_set_user_visible (backend, FALSE);
+
+	mount_spec = g_mount_spec_new ("network");
+	g_vfs_backend_set_mount_spec (backend, mount_spec);
+	network_backend->mount_spec = mount_spec;
+}
+
+
+static void
+g_vfs_backend_network_finalize (GObject *object)
+{
+	GVfsBackendNetwork *backend;
+
+	backend = G_VFS_BACKEND_NETWORK (object);
+
+	g_mount_spec_unref (backend->mount_spec);
+
+	g_object_unref (backend->root_monitor);
+  
+	if (G_OBJECT_CLASS (g_vfs_backend_network_parent_class)->finalize)
+		(*G_OBJECT_CLASS (g_vfs_backend_network_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_backend_network_class_init (GVfsBackendNetworkClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+  
+	gobject_class->finalize = g_vfs_backend_network_finalize;
+
+	backend_class->try_mount        = try_mount;
+	backend_class->try_query_info   = try_query_info;
+	backend_class->try_enumerate    = try_enumerate;
+	backend_class->try_create_dir_monitor = try_create_monitor;
+	backend_class->try_create_file_monitor = try_create_monitor;
+	backend_class->open_for_read    = do_open_for_read;
+	backend_class->read             = do_read;
+	backend_class->close_read       = do_close_read;
+}
Index: daemon/gvfsbackendnetwork.h
===================================================================
--- daemon/gvfsbackendnetwork.h	(revision 0)
+++ daemon/gvfsbackendnetwork.h	(revision 0)
@@ -0,0 +1,51 @@
+/* gvfs-backend-network.h - GIO - GLib Input, Output and Streaming Library
+ * Original work, Copyright (C) 2003 Red Hat, Inc
+ * GVFS port, Copyright (c) 2008 Andrew Walton.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the Gnome Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *       Alexander Larsson <alexl@redhat.com>
+ *       Andrew Walton <awalton@svn.gnome.org>
+ */
+
+#ifndef __G_VFS_BACKEND_NETWORK_H__
+#define __G_VFS_BACKEND_NETWORK_H__
+
+#include <gvfsbackend.h>
+#include <gmountspec.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_NETWORK         (g_vfs_backend_network_get_type ())
+#define G_VFS_BACKEND_NETWORK(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_BACKEND_NETWORK, GVfsBackendNetwork))
+#define G_VFS_BACKEND_NETWORK_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_BACKEND_NETWORK, GVfsBackendNetworkClass))
+#define G_VFS_IS_BACKEND_NETWORK(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_BACKEND_NETWORK))
+#define G_VFS_IS_BACKEND_NETWORK_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_BACKEND_NETWORK))
+#define G_VFS_BACKEND_NETWORK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_BACKEND_NETWORK, GVfsBackendNetworkClass))
+
+typedef struct _GVfsBackendNetworkClass   GVfsBackendNetworkClass;
+
+struct _GVfsBackendNetworkClass
+{
+  GVfsBackendClass parent_class;
+};
+
+GType g_vfs_backend_network_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_NETWORK_H__ */
Index: daemon/Makefile.am
===================================================================
--- daemon/Makefile.am	(revision 1270)
+++ daemon/Makefile.am	(working copy)
@@ -55,6 +55,12 @@
 libexec_PROGRAMS += gvfsd-cdda
 endif
 
+mount_in_files += network.mount.in
+if USE_GCONF
+mount_DATA += network.mount
+libexec_PROGRAMS += gvfsd-network
+endif
+
 EXTRA_DIST = gvfs-daemon.service.in $(mount_in_files)
 
 DISTCLEANFILES = gvfs-daemon.service $(mount_DATA)
@@ -215,6 +221,20 @@
 
 gvfsd_computer_LDADD = $(libraries)
 
+gvfsd_network_SOURCES = \
+	gvfsbackendnetwork.c gvfsbackendnetwork.h \
+	daemon-main.c daemon-main.h \
+	daemon-main-generic.c 
+
+gvfsd_network_CPPFLAGS = \
+	-DBACKEND_HEADER=gvfsbackendnetwork.h \
+	-DDEFAULT_BACKEND_TYPE=network \
+	-DMAX_JOB_THREADS=1 \
+	$(GCONF_CFLAGS) \
+	-DBACKEND_TYPES='"network", G_VFS_TYPE_BACKEND_NETWORK,'
+
+gvfsd_network_LDADD = $(libraries) $(GCONF_LIBS)
+
 gvfsd_burn_SOURCES = \
 	gvfsbackendburn.c gvfsbackendburn.h \
 	daemon-main.c daemon-main.h \
Index: daemon/network.mount.in
===================================================================
--- daemon/network.mount.in	(revision 0)
+++ daemon/network.mount.in	(revision 0)
@@ -0,0 +1,4 @@
+[Mount]
+Type=network
+Exec=@libexecdir@/gvfsd-network
+AutoMount=true
