From e9ed6a41cf0bd8024f9b914fa64a5853a0f9c119 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Mon, 13 Jun 2011 13:19:47 +0300 Subject: [PATCH] Added function vfs_path_url_split() for parse VFS parameters Signed-off-by: Slava Zanko --- lib/tests/vfs/path_serialize.c | 32 +++++++-- lib/vfs/path.c | 121 ++++++++++++++++++++++++++++++++- lib/vfs/path.h | 1 + 3 files changed, 147 insertions(+), 7 deletions(-) diff --git a/lib/tests/vfs/path_serialize.c b/lib/tests/vfs/path_serialize.c index 0d846736f..107dfd811 100644 --- a/lib/tests/vfs/path_serialize.c +++ b/lib/tests/vfs/path_serialize.c @@ -86,10 +86,32 @@ teardown (void) /* --------------------------------------------------------------------------------------------- */ #define ETALON_PATH_STR "/local/path/#test1:user:pass@some.host:12345/bla-bla/some/path/#test2:/#enc:KOI8-R/bla-bla/some/path#test3:/111/22/33" -#define ETALON_SERIALIZED_PATH "g14:path-element-0p4:pathv12:/local/path/p10:class-namev7:localfsp4:portv1:0" \ - "g14:path-element-1p4:pathv18:bla-bla/some/path/p10:class-namev7:testfs1p11:raw_url_strv31:test1:user:pass@some.host:12345p4:portv1:0" \ - "g14:path-element-2p4:pathv17:bla-bla/some/pathp10:class-namev7:testfs2p8:encodingv6:KOI8-Rp11:raw_url_strv6:test2:p4:portv1:0" \ - "g14:path-element-3p4:pathv9:111/22/33p10:class-namev7:testfs3p11:raw_url_strv6:test3:p4:portv1:0" +#define ETALON_SERIALIZED_PATH \ + "g14:path-element-0" \ + "p4:pathv12:/local/path/" \ + "p10:class-namev7:localfs" \ + "g14:path-element-1" \ + "p4:pathv18:bla-bla/some/path/" \ + "p10:class-namev7:testfs1" \ + "p11:raw_url_strv31:test1:user:pass@some.host:12345" \ + "p10:vfs_prefixv5:test1" \ + "p4:userv4:user" \ + "p8:passwordv4:pass" \ + "p4:hostv9:some.host" \ + "p4:portv5:12345" \ + "g14:path-element-2" \ + "p4:pathv17:bla-bla/some/path" \ + "p10:class-namev7:testfs2" \ + "p8:encodingv6:KOI8-R" \ + "p11:raw_url_strv6:test2:" \ + "p10:vfs_prefixv5:test2" \ + "p4:hostv0:" \ + "g14:path-element-3" \ + "p4:pathv9:111/22/33" \ + "p10:class-namev7:testfs3" \ + "p11:raw_url_strv6:test3:" \ + "p10:vfs_prefixv5:test3" \ + "p4:hostv0:" START_TEST (test_path_serialize_deserialize) { @@ -110,7 +132,7 @@ START_TEST (test_path_serialize_deserialize) fail_unless ( strcmp (serialized_vpath, ETALON_SERIALIZED_PATH ) == 0, - "serialized_vpath (%s) doesn't equal to etalon (%s)", serialized_vpath, ETALON_SERIALIZED_PATH + "\nserialized_vpath (%s)\nnot equal to etalon (%s)", serialized_vpath, ETALON_SERIALIZED_PATH ); vpath = vfs_path_deserialize (serialized_vpath, &error); diff --git a/lib/vfs/path.c b/lib/vfs/path.c index 9cc283367..dd9581b5d 100644 --- a/lib/vfs/path.c +++ b/lib/vfs/path.c @@ -161,7 +161,6 @@ vfs_canon (const char *path) } /* --------------------------------------------------------------------------------------------- */ - /** get encoding after last #enc: or NULL, if part does not contain #enc: * * @param path string @@ -199,6 +198,106 @@ vfs_get_encoding (const char *path) } } +/* --------------------------------------------------------------------------------------------- */ +/** Extract the hostname and username from the path + * + * Format of the path is [user@]hostname:port/remote-dir, e.g.: + * + * ftp://sunsite.unc.edu/pub/linux + * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc + * ftp://tsx-11.mit.edu:8192/ + * ftp://joe@foo.edu:11321/private + * ftp://joe:password@foo.se + * + * @param path_element is an input string to be parsed + * @param path is an input string to be parsed + * + * @return g_malloc()ed url info. + * If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS + * is not set, then the current login name is supplied. + * Return value is a g_malloc()ed structure with the pathname relative to the + * host. + */ + +static void +vfs_path_url_split (vfs_path_element_t * path_element, const char *path) +{ + char *pcopy; + const char *pend; + char *dir, *colon, *inner_colon, *at, *rest; + + path_element->port = 0; + + pcopy = g_strdup (path); + pend = pcopy + strlen (pcopy); + dir = pcopy; + + /* search for any possible user */ + at = strrchr (pcopy, '@'); + + /* We have a username */ + if (at == NULL) + rest = pcopy; + else + { + *at = '\0'; + inner_colon = strchr (pcopy, ':'); + if (inner_colon != NULL) + { + *inner_colon = '\0'; + inner_colon++; + path_element->password = g_strdup (inner_colon); + } + + if (*pcopy != '\0') + path_element->user = g_strdup (pcopy); + + if (pend == at + 1) + rest = at; + else + rest = at + 1; + } + + /* Check if the host comes with a port spec, if so, chop it */ + if (*rest != '[') + colon = strchr (rest, ':'); + else + { + colon = strchr (++rest, ']'); + if (colon != NULL) + { + colon[0] = '\0'; + colon[1] = '\0'; + colon++; + } + } + + if (colon != NULL) + { + *colon = '\0'; + if (sscanf (colon + 1, "%d", &path_element->port) == 1) + { + if (path_element->port <= 0 || path_element->port >= 65536) + path_element->port = 0; + } + else + while (*(++colon) != '\0') + { + switch (*colon) + { + case 'C': + path_element->port = 1; + break; + case 'r': + path_element->port = 2; + break; + } + } + } + path_element->host = g_strdup (rest); + g_free (pcopy); +} + /* --------------------------------------------------------------------------------------------- */ /** * get VFS class for the given name @@ -321,6 +420,7 @@ vfs_path_from_str (const char *path_str) while ((class = _vfs_split_with_semi_skip_count (path, &local, &op, 0)) != NULL) { + char *url_params; element = g_new0 (vfs_path_element_t, 1); element->class = vfs_prefix_to_class (op); if (local == NULL) @@ -331,6 +431,18 @@ vfs_path_from_str (const char *path_str) element->dir.converter = INVALID_CONV; element->raw_url_str = g_strdup (op); + + url_params = strchr (op, ':'); /* skip VFS prefix */ + if (url_params != NULL) + { + *url_params = '\0'; + url_params++; + vfs_path_url_split (element, url_params); + } + + if (*op != '\0') + element->vfs_prefix = g_strdup (op); + vpath->path = g_list_prepend (vpath->path, element); } if (path[0] != '\0') @@ -425,6 +537,7 @@ vfs_path_element_clone (const vfs_path_element_t * element) new_element->host = g_strdup (element->host); new_element->path = g_strdup (element->path); new_element->encoding = g_strdup (element->encoding); + new_element->vfs_prefix = g_strdup (element->vfs_prefix); return new_element; } @@ -448,6 +561,7 @@ vfs_path_element_free (vfs_path_element_t * element) g_free (element->host); g_free (element->path); g_free (element->encoding); + g_free (element->vfs_prefix); if (vfs_path_element_need_cleanup_converter (element)) { @@ -607,11 +721,13 @@ vfs_path_serialize (const vfs_path_t * vpath, GError ** error) mc_config_set_string_raw (cpath, groupname, "encoding", element->encoding); mc_config_set_string_raw (cpath, groupname, "raw_url_str", element->raw_url_str); + mc_config_set_string_raw (cpath, groupname, "vfs_prefix", element->vfs_prefix); mc_config_set_string_raw (cpath, groupname, "user", element->user); mc_config_set_string_raw (cpath, groupname, "password", element->password); mc_config_set_string_raw (cpath, groupname, "host", element->host); - mc_config_set_int (cpath, groupname, "port", element->port); + if (element->port != 0) + mc_config_set_int (cpath, groupname, "port", element->port); g_free (groupname); } @@ -676,6 +792,7 @@ vfs_path_deserialize (const char *data, GError ** error) element->encoding = mc_config_get_string_raw (cpath, groupname, "encoding", NULL); element->raw_url_str = mc_config_get_string_raw (cpath, groupname, "raw_url_str", NULL); + element->vfs_prefix = mc_config_get_string_raw (cpath, groupname, "vfs_prefix", NULL); element->user = mc_config_get_string_raw (cpath, groupname, "user", NULL); element->password = mc_config_get_string_raw (cpath, groupname, "password", NULL); diff --git a/lib/vfs/path.h b/lib/vfs/path.h index 4e52a39a7..f99738c6e 100644 --- a/lib/vfs/path.h +++ b/lib/vfs/path.h @@ -24,6 +24,7 @@ typedef struct char *path; struct vfs_class *class; char *encoding; + char *vfs_prefix; struct {