mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
Added URL-like path parser
Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
parent
39462b9b76
commit
2ec4cc59ab
@ -109,6 +109,39 @@ END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
START_TEST (set_up_current_dir_url)
|
||||
{
|
||||
static struct vfs_s_subclass test_subclass;
|
||||
static struct vfs_class vfs_test_ops;
|
||||
char buffer[MC_MAXPATHLEN];
|
||||
|
||||
test_subclass.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops, &test_subclass);
|
||||
|
||||
vfs_test_ops.name = "testfs";
|
||||
vfs_test_ops.flags = VFSF_NOLINKS;
|
||||
vfs_test_ops.prefix = "test:";
|
||||
vfs_test_ops.chdir = test_chdir;
|
||||
|
||||
vfs_register_class (&vfs_test_ops);
|
||||
|
||||
cd_and_check ("/dev/some.file/test://bla-bla", "/dev/some.file/#test:bla-bla");
|
||||
|
||||
cd_and_check ("..", "/dev");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
cd_and_check ("..", "/");
|
||||
|
||||
test_subclass.flags &= ~VFS_S_REMOTE;
|
||||
|
||||
cd_and_check ("/dev/some.file/test://bla-bla", "/dev/some.file/#test/bla-bla");
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -122,6 +155,7 @@ main (void)
|
||||
|
||||
/* Add new tests here: *************** */
|
||||
tcase_add_test (tc_core, set_up_current_dir);
|
||||
tcase_add_test (tc_core, set_up_current_dir_url);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
|
@ -52,7 +52,6 @@ setup (void)
|
||||
vfs_setup_work_dir ();
|
||||
|
||||
|
||||
test_subclass1.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops1, &test_subclass1);
|
||||
|
||||
vfs_test_ops1.name = "testfs1";
|
||||
@ -60,6 +59,7 @@ setup (void)
|
||||
vfs_test_ops1.prefix = "test1";
|
||||
vfs_register_class (&vfs_test_ops1);
|
||||
|
||||
test_subclass2.flags = VFS_S_REMOTE;
|
||||
vfs_s_init_class (&vfs_test_ops2, &test_subclass2);
|
||||
vfs_test_ops2.name = "testfs2";
|
||||
vfs_test_ops2.prefix = "test2";
|
||||
@ -281,6 +281,29 @@ START_TEST (test_vfs_path_encoding_at_end)
|
||||
END_TEST
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
#undef ETALON_PATH_STR
|
||||
#define ETALON_PATH_STR "/#test1/bla-bla/some/path/#test2:user:passwd@some.host:1234/bla-bla/some/path/#test3/111/22/33"
|
||||
#define INPUT_PATH_STR "/test1://bla-bla/some/path/test2://user:passwd@some.host:1234/bla-bla/some/path/test3://111/22/33"
|
||||
START_TEST (test_vfs_path_from_to_string_uri)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
size_t vpath_len;
|
||||
char *result;
|
||||
vpath = vfs_path_from_str (INPUT_PATH_STR);
|
||||
|
||||
vpath_len = vfs_path_elements_count(vpath);
|
||||
fail_unless(vpath_len == 4, "vpath length should be 4 (actial: %d)",vpath_len);
|
||||
|
||||
result = vfs_path_to_str(vpath);
|
||||
fail_unless(strcmp(ETALON_PATH_STR, result) == 0, "\nexpected(%s)\ndoesn't equal to actual(%s)", ETALON_PATH_STR, result);
|
||||
g_free(result);
|
||||
|
||||
vfs_path_free(vpath);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -298,6 +321,7 @@ main (void)
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_partial_string_by_class);
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_string_encoding);
|
||||
tcase_add_test (tc_core, test_vfs_path_encoding_at_end);
|
||||
tcase_add_test (tc_core, test_vfs_path_from_to_string_uri);
|
||||
/* *********************************** */
|
||||
|
||||
suite_add_tcase (s, tc_core);
|
||||
|
206
lib/vfs/path.c
206
lib/vfs/path.c
@ -39,6 +39,7 @@
|
||||
|
||||
#include "vfs.h"
|
||||
#include "utilvfs.h"
|
||||
#include "xdirentry.h"
|
||||
#include "path.h"
|
||||
|
||||
extern GPtrArray *vfs__classes_list;
|
||||
@ -47,6 +48,8 @@ extern GPtrArray *vfs__classes_list;
|
||||
|
||||
/*** file scope macro definitions ****************************************************************/
|
||||
|
||||
#define URL_DELIMITER "://"
|
||||
|
||||
/*** file scope type declarations ****************************************************************/
|
||||
|
||||
/*** file scope variables ************************************************************************/
|
||||
@ -369,6 +372,161 @@ vfs_get_class_by_name (const char *class_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/**
|
||||
* Check if path string contain URL-like elements
|
||||
*
|
||||
* @param path_str path
|
||||
*
|
||||
* @return TRUE if path is deprecated or FALSE otherwise
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
vfs_path_is_str_path_deprecated (const char *path_str)
|
||||
{
|
||||
return strstr (path_str, URL_DELIMITER) == NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/** Split path string to path elements by deprecated algorithm.
|
||||
*
|
||||
* @param path_str VFS-path
|
||||
*
|
||||
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
||||
*/
|
||||
|
||||
static vfs_path_t *
|
||||
vfs_path_from_str_deprecated_parser (char *path)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *element;
|
||||
struct vfs_class *class;
|
||||
const char *local, *op;
|
||||
|
||||
vpath = vfs_path_new ();
|
||||
|
||||
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 = class;
|
||||
if (local == NULL)
|
||||
local = "";
|
||||
element->path = vfs_translate_path_n (local);
|
||||
|
||||
element->encoding = vfs_get_encoding (local);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
|
||||
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')
|
||||
{
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = g_ptr_array_index (vfs__classes_list, 0);
|
||||
element->path = vfs_translate_path_n (path);
|
||||
|
||||
element->encoding = vfs_get_encoding (path);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
}
|
||||
|
||||
return vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/** Split path string to path elements by URL algorithm.
|
||||
*
|
||||
* @param path_str VFS-path
|
||||
*
|
||||
* @return pointer to newly created vfs_path_t object with filled path elements array.
|
||||
*/
|
||||
|
||||
static vfs_path_t *
|
||||
vfs_path_from_str_uri_parser (char *path)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *element;
|
||||
|
||||
char *url_delimiter;
|
||||
|
||||
vpath = vfs_path_new ();
|
||||
|
||||
while ((url_delimiter = g_strrstr (path, URL_DELIMITER)) != NULL)
|
||||
{
|
||||
char *vfs_prefix_start;
|
||||
char *real_vfs_prefix_start = url_delimiter;
|
||||
char *slash_pointer;
|
||||
struct vfs_s_subclass *sub;
|
||||
|
||||
while (real_vfs_prefix_start > path && *(real_vfs_prefix_start) != PATH_SEP)
|
||||
real_vfs_prefix_start--;
|
||||
vfs_prefix_start = real_vfs_prefix_start;
|
||||
|
||||
if (*(vfs_prefix_start) == PATH_SEP)
|
||||
vfs_prefix_start += 1;
|
||||
*(url_delimiter + 1) = '\0';
|
||||
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = vfs_prefix_to_class (vfs_prefix_start);
|
||||
*url_delimiter = '\0';
|
||||
element->vfs_prefix = g_strdup (vfs_prefix_start);
|
||||
|
||||
element->dir.converter = INVALID_CONV;
|
||||
|
||||
url_delimiter += 3;
|
||||
sub = VFSDATA (element);
|
||||
if (sub->flags & VFS_S_REMOTE)
|
||||
{
|
||||
slash_pointer = strchr (url_delimiter, PATH_SEP);
|
||||
if (slash_pointer == NULL)
|
||||
{
|
||||
element->path = g_strdup ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
element->path = vfs_translate_path_n (slash_pointer + 1);
|
||||
element->encoding = vfs_get_encoding (slash_pointer);
|
||||
*slash_pointer = '\0';
|
||||
}
|
||||
vfs_path_url_split (element, url_delimiter);
|
||||
}
|
||||
else
|
||||
{
|
||||
element->path = vfs_translate_path_n (url_delimiter);
|
||||
element->encoding = vfs_get_encoding (url_delimiter);
|
||||
}
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
|
||||
if (real_vfs_prefix_start > path && *(real_vfs_prefix_start) != PATH_SEP)
|
||||
*real_vfs_prefix_start = '\0';
|
||||
else
|
||||
*(real_vfs_prefix_start + 1) = '\0';
|
||||
}
|
||||
|
||||
if (path[0] != '\0')
|
||||
{
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = g_ptr_array_index (vfs__classes_list, 0);
|
||||
element->path = vfs_translate_path_n (path);
|
||||
element->encoding = vfs_get_encoding (path);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
}
|
||||
|
||||
return vpath;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
/*** public functions ****************************************************************************/
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
@ -456,57 +614,20 @@ vfs_path_t *
|
||||
vfs_path_from_str (const char *path_str)
|
||||
{
|
||||
vfs_path_t *vpath;
|
||||
vfs_path_element_t *element;
|
||||
struct vfs_class *class;
|
||||
const char *local, *op;
|
||||
char *path;
|
||||
|
||||
if (path_str == NULL)
|
||||
return NULL;
|
||||
|
||||
vpath = vfs_path_new ();
|
||||
path = vfs_canon (path_str);
|
||||
if (path == NULL)
|
||||
{
|
||||
vfs_path_free (vpath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 = class;
|
||||
if (local == NULL)
|
||||
local = "";
|
||||
element->path = vfs_translate_path_n (local);
|
||||
if (vfs_path_is_str_path_deprecated (path))
|
||||
vpath = vfs_path_from_str_deprecated_parser (path);
|
||||
else
|
||||
vpath = vfs_path_from_str_uri_parser (path);
|
||||
|
||||
element->encoding = vfs_get_encoding (local);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
|
||||
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')
|
||||
{
|
||||
element = g_new0 (vfs_path_element_t, 1);
|
||||
element->class = g_ptr_array_index (vfs__classes_list, 0);
|
||||
element->path = vfs_translate_path_n (path);
|
||||
|
||||
element->encoding = vfs_get_encoding (path);
|
||||
element->dir.converter = INVALID_CONV;
|
||||
vpath->path = g_list_prepend (vpath->path, element);
|
||||
}
|
||||
g_free (path);
|
||||
|
||||
return vpath;
|
||||
@ -696,8 +817,8 @@ vfs_path_remove_element_by_index (vfs_path_t * vpath, int element_index)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/** Return VFS class for the given prefix */
|
||||
|
||||
struct vfs_class *
|
||||
vfs_prefix_to_class (const char *prefix)
|
||||
{
|
||||
@ -722,7 +843,6 @@ vfs_prefix_to_class (const char *prefix)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Check if need cleanup charset converter for vfs_path_element_t
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user