Re: [PATCH] "Fixup" smb:/// entries



Am Montag, den 25.12.2006, 02:26 +0100 schrieb Christian Neumair:
> Am Montag, den 25.12.2006, 02:12 +0100 schrieb Christian Neumair:
> > The attached patch is a crude hack (like most of smb:///) to "fix" the
> > issue that Nautilus messes up MIME types of smb://(/) contents all the
> > time (thus flipping directory and launcher MIME types), by constructing
> > separate "smb:///foo.desktop" and "smb://foo" entries. At the moment, I
> > think the issue is that Nautilus/GnomeVFS use some textual mechanism for
> > comparing URIs that ignores subsequent slashes, not realizing that
> > smb:///foo and smb://foo are different entities, and goes crazy when
> > trying to follow a link pointing to itself, pretending to be both a
> > directory and a launcher.
> > 
> > We don't really have a concept when "proto://" and "proto:///" are
> > considered identical, IIRC some modules even convert the URI to string
> > and skip these slashes in its handlers. From a user perspective, having
> > a root URI and a separate host construction seems unintuitive, so this
> > might actually be the more "correct" route.
> > 
> > Hopefully fixes http://bugzilla.gnome.org/show_bug.cgi?id=356093
> 
> Eww sorry, please let me rethink this one. It's getting late, and I
> heard to much Jazz. I probably identified the cause of the issue
> correctly, but the patch breaks the file info name, at least for work
> group/server links.

Although the original but report seems to have been a VFS daemon issue,
I'm attaching a patch that will clarify the desktop files to end in
".desktop" (so that even their file names are a hint that they are
links), and attaches some documentation where it is neccessary.

It is definitly just a face lift, but computer:/// also uses special
file extensions to clarify that we're dealing with links.

It will also prevent the module from generating links from "smb:///foo"
to "smb://foo", which is IMO quite unintuitive because you can easily
confuse them.

How the SMB module will work after the patch:

We have a toplevel SMB directory smb:/// that will contain links to all
workgroups, i.e.
for each workgroup "my_workgroup", it contains a file named
"smb:///my_workgroup.desktop"
that will link to "smb://my_workgroup/".

For each of these workgroups, we enumerate the servers
"my_server1", ..., "my_serverN",
and put them as server links to
"smb://my_workgroup/my_server1.desktop", ...,
"smb://my_workgroup/my_serverN.desktop".  Each of these server link
files
"smb://my_workgroup/my_serverI.desktop" will link to "smb://my_serverI".

In short: * workgroup links live at smb:///workgroup.desktop
          * server links live at
              * smb:///server.desktop
              * smb://workgroup/server.desktop
          * workgroups live at smb://workgroup
          * servers live at smb://server
          * shares live at smb://server/share
          * files live at smb://server/share/...

Note that this means that

* smb://foo may either refer to a workgroup or to a server,
  depending on whether we have a workgroup named "foo".

* smb://foo/bar.desktop may either refer to a server link (linking to
smb://bar/)
  or to a file on a server, depending on whether we have a workgroup
named "foo".

* smb:/// files are constructed on the fly.

    * Any request do_get_file_info() for a toplevel file named
smb:///foo.desktop
      will be satisfied and will tell you it's a desktop file.

    * In do_read(), we'll figure out whether it is a link to smb://foo/.
Whether it
      is a link to a workgroup or to a server (which will just modify
its icon) is
      figured out by looking up the workgrop cache.

* This mechanism ensures that we always satisfy requests to any server
and to its corresponding server link.



-- 
Christian Neumair <chris gnome-de org>
Index: modules/smb-method.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/smb-method.c,v
retrieving revision 1.41
diff -u -p -r1.41 smb-method.c
--- modules/smb-method.c	18 Dec 2006 17:34:06 -0000	1.41
+++ modules/smb-method.c	25 Dec 2006 12:28:28 -0000
@@ -56,6 +56,15 @@ int smbc_remove_unused_server(SMBCCTX * 
 
 typedef enum {
 	SMB_URI_ERROR,
+	/* will be returned when people operate on
+ 	 * smb:/// URIs that don't end in ".desktop",
+ 	 *
+ 	 * or when they operate on
+ 	 *
+ 	 * smb://foo/bar/ URIs where foo is a valid workgroup name,
+ 	 * that don't end in ".desktop"
+ 	 */
+	SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME,
 	SMB_URI_WHOLE_NETWORK,
 	SMB_URI_WORKGROUP_LINK,
 	SMB_URI_WORKGROUP,
@@ -571,7 +580,7 @@ smb_uri_type (GnomeVFSURI *uri)
 	toplevel = (GnomeVFSToplevelURI *)uri;
 
 	if (toplevel->host_name == NULL || toplevel->host_name[0] == 0) {
-		/* smb:/// or smb:///foo */
+		/* smb:/// or smb:///foo.desktop (workgroup link), otherwise not found */
 		if (uri->text == NULL ||
 		    uri->text[0] == 0 ||
 		    strcmp (uri->text, "/") == 0) {
@@ -580,12 +589,17 @@ smb_uri_type (GnomeVFSURI *uri)
 		if (strchr (uri->text + 1, '/')) {
 			return SMB_URI_ERROR;
 		}
+
+		if (!g_str_has_suffix (uri->text, ".desktop")) {
+			return SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME;
+		}
+
 		return SMB_URI_WORKGROUP_LINK;
 	}
 	if (uri->text == NULL ||
 	    uri->text[0] == 0 ||
 	    strcmp (uri->text, "/") == 0) {
-		/* smb://foo/ */
+		/* smb://foo/ (workgroup or server) */
 		update_workgroup_cache ();
 		if (!g_ascii_strcasecmp(toplevel->host_name,
 					DEFAULT_WORKGROUP_NAME) ||
@@ -595,20 +609,30 @@ smb_uri_type (GnomeVFSURI *uri)
 			return SMB_URI_SERVER;
 		}
 	}
+	update_workgroup_cache ();
+
 	first_slash = strchr (uri->text + 1, '/');
-	if (first_slash == NULL) {
-		/* smb://foo/bar */
-		update_workgroup_cache ();
-		if (!g_ascii_strcasecmp(toplevel->host_name,
-					DEFAULT_WORKGROUP_NAME) ||
-		    g_hash_table_lookup (workgroups, toplevel->host_name)) {
-			return SMB_URI_SERVER_LINK;
-		} else {
-			return SMB_URI_SHARE;
+	if (!g_ascii_strcasecmp(toplevel->host_name,
+				DEFAULT_WORKGROUP_NAME) ||
+	    g_hash_table_lookup (workgroups, toplevel->host_name)) {
+		/* smb://foo/bar.desktop (server link), otherwise not found */
+		if (first_slash != NULL) {
+			return SMB_URI_ERROR;
+		}
+
+		if (!g_str_has_suffix (uri->text, ".desktop")) {
+			return SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME;
 		}
+
+		return SMB_URI_SERVER_LINK;
+	}
+
+	/* smb://foo/bar (share on server), otherwise smb://foo/bar/... (file on server) */
+	if (first_slash == NULL) {
+		return SMB_URI_SHARE;
+	} else {
+		return SMB_URI_SHARE_FILE;
 	}
-	
-	return SMB_URI_SHARE_FILE;
 }
 
 
@@ -1453,6 +1477,12 @@ typedef struct {
 	GnomeVFSFileOffset file_size;
 } FileHandle;
 
+
+#define TRUNCATE_DESKTOP_FILE_EXTENSION(str) \
+	if (g_str_has_suffix (str, ".desktop")) { \
+		*(str + strlen(str) - strlen(".desktop")) = '\0'; \
+	}
+
 static GnomeVFSResult
 do_open (GnomeVFSMethod *method,
 	 GnomeVFSMethodHandle **method_handle,
@@ -1472,6 +1502,10 @@ do_open (GnomeVFSMethod *method,
 
 	type = smb_uri_type (uri);
 
+	if (type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
+		return GNOME_VFS_ERROR_NOT_FOUND;
+	}
+
 	if (type == SMB_URI_ERROR) {
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
@@ -1491,7 +1525,9 @@ do_open (GnomeVFSMethod *method,
 		handle->is_data = TRUE;
 		handle->offset = 0;
 		unescaped_name = get_base_from_uri (uri);
+		TRUNCATE_DESKTOP_FILE_EXTENSION (unescaped_name);
 		name = gnome_vfs_uri_extract_short_path_name (uri);
+		TRUNCATE_DESKTOP_FILE_EXTENSION (name);
 		handle->file_data = get_workgroup_data (unescaped_name, name);
 		handle->file_size = strlen (handle->file_data);
 		g_free (unescaped_name);
@@ -1510,7 +1546,9 @@ do_open (GnomeVFSMethod *method,
 		handle->is_data = TRUE;
 		handle->offset = 0;
 		unescaped_name = get_base_from_uri (uri);
+		TRUNCATE_DESKTOP_FILE_EXTENSION (unescaped_name);
 		name = gnome_vfs_uri_extract_short_path_name (uri);
+		TRUNCATE_DESKTOP_FILE_EXTENSION (name);
 		handle->file_data = get_computer_data (unescaped_name, name);
 		handle->file_size = strlen (handle->file_data);
 		g_free (unescaped_name);
@@ -1707,6 +1745,10 @@ do_create (GnomeVFSMethod *method,
 	
 	type = smb_uri_type (uri);
 
+	if (type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
+		return GNOME_VFS_ERROR_NOT_FOUND;
+	}
+
 	if (type == SMB_URI_ERROR)
 		return GNOME_VFS_ERROR_INVALID_URI;
 
@@ -1779,6 +1821,10 @@ do_get_file_info (GnomeVFSMethod *method
 
 	type = smb_uri_type (uri);
 
+	if (type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
+		return GNOME_VFS_ERROR_NOT_FOUND;
+	}
+
 	if (type == SMB_URI_ERROR) {
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
@@ -1955,6 +2001,10 @@ do_open_directory (GnomeVFSMethod *metho
 
 	type = smb_uri_type (uri);
 
+	if (type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
+		return GNOME_VFS_ERROR_NOT_FOUND;
+	}
+
 	if (type == SMB_URI_WHOLE_NETWORK) {
 		update_workgroup_cache ();
 		
@@ -2083,7 +2133,8 @@ do_read_directory (GnomeVFSMethod *metho
 			/* workgroup link */
 			l = dh->workgroups;
 			dh->workgroups = g_list_remove_link (dh->workgroups, l);
-			file_info->name = l->data;
+			file_info->name = g_strconcat (l->data, ".desktop", NULL);
+			g_free (l->data);
 			g_list_free_1 (l);
 			
 			file_info->valid_fields =
@@ -2145,13 +2196,26 @@ do_read_directory (GnomeVFSMethod *metho
 		file_info->mime_type = g_strdup ("x-directory/smb-share");
 		break;
 	case SMBC_WORKGROUP:
-	case SMBC_SERVER:
+	case SMBC_SERVER: {
+		/* construct "foo.desktop" file name, we're listing a workgroup
+		 * smb://valid_workgroup/.
+		 *
+ 		 * I couldn't spot when SMBC_WORKGROUP is relevant, we construct
+ 		 * smb:///valid_workgroup.desktop in do_open_directory().
+ 		 */
+		char *file_name;
+
+		file_name = g_strconcat (file_info->name, ".desktop", NULL);
+		g_free (file_info->name);
+		file_info->name = file_name;
+
 		file_info->valid_fields = file_info->valid_fields
 			| GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE
 			| GNOME_VFS_FILE_INFO_FIELDS_TYPE;
 		file_info->type = GNOME_VFS_FILE_TYPE_REGULAR;
 		file_info->mime_type = g_strdup ("application/x-desktop");
 		break;
+	}
 	case SMBC_PRINTER_SHARE:
 		/* Ignored above for now */
 		file_info->valid_fields = file_info->valid_fields
@@ -2328,6 +2392,10 @@ do_unlink (GnomeVFSMethod *method,
 
 	type = smb_uri_type (uri);
 
+	if (type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
+		return GNOME_VFS_ERROR_NOT_FOUND;
+	}
+
 	if (type == SMB_URI_ERROR) {
 		return GNOME_VFS_ERROR_INVALID_URI;
 	}
@@ -2444,6 +2512,16 @@ do_move (GnomeVFSMethod *method,
 	old_type = smb_uri_type (old_uri);
 	new_type = smb_uri_type (new_uri);
 
+	if (old_type == SMB_URI_ERROR ||
+	    new_type == SMB_URI_ERROR) {
+		return GNOME_VFS_ERROR_INVALID_URI;
+	}
+
+	if (old_type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME ||
+	    new_type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
+		return GNOME_VFS_ERROR_NOT_FOUND;
+	}
+
 	if (old_type != SMB_URI_SHARE_FILE ||
 	    new_type != SMB_URI_SHARE_FILE) {
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
@@ -2530,7 +2608,8 @@ do_make_directory (GnomeVFSMethod *metho
 	    type == SMB_URI_SERVER ||
 	    type == SMB_URI_SHARE ||
 	    type == SMB_URI_WORKGROUP_LINK ||
-	    type == SMB_URI_SERVER_LINK) {
+	    type == SMB_URI_SERVER_LINK ||
+	    type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
 	}
 
@@ -2573,7 +2652,8 @@ do_remove_directory (GnomeVFSMethod *met
 	    type == SMB_URI_SERVER ||
 	    type == SMB_URI_SHARE ||
 	    type == SMB_URI_WORKGROUP_LINK ||
-	    type == SMB_URI_SERVER_LINK) {
+	    type == SMB_URI_SERVER_LINK ||
+	    type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
 		return GNOME_VFS_ERROR_NOT_PERMITTED;
 	}
 
@@ -2608,6 +2688,10 @@ do_set_file_info (GnomeVFSMethod *method
 	DEBUG_SMB (("do_set_file_info: mask %x\n", mask));
 
 	type = smb_uri_type (uri);
+
+	if (type == SMB_URI_ERROR_INVALID_DESKTOP_FILE_NAME) {
+		return GNOME_VFS_ERROR_NOT_FOUND;
+	}
 
 	if (type == SMB_URI_ERROR) {
 		return GNOME_VFS_ERROR_INVALID_URI;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]