Re: [PATCH] "Fixup" smb:/// entries
- From: Christian Neumair <chris gnome-de org>
- To: "gnome-vfs-list gnome org" <gnome-vfs-list gnome org>
- Subject: Re: [PATCH] "Fixup" smb:/// entries
- Date: Mon, 25 Dec 2006 13:35:35 +0100
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]