Skip to content

Commit

Permalink
lib: add rb_uri_is_descendant
Browse files Browse the repository at this point in the history
This checks if one canonical URI is a descendant of another, that is,
if removing some number of path components from the first URI would
result in the second.
  • Loading branch information
Jonathan Matthew committed Mar 26, 2021
1 parent ecef9cc commit bb6fba6
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
42 changes: 42 additions & 0 deletions lib/rb-file-helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,48 @@ rb_file_find_extant_parent (GFile *file)
return file;
}

/**
* rb_uri_is_descendant:
* @uri: URI to check
* @ancestor: a URI to check against
*
* Checks if @uri refers to a path beneath @ancestor, such that removing some number
* of path segments of @uri would result in @ancestor.
* It doesn't do any filesystem operations, it just looks at the URIs as strings.
* The URI strings should be built by looking at a filesystem rather than user input,
* and must not have path segments that are empty (multiple slashes) or '.' or '..'.
*
* Given this input, checking if one URI is a descendant of another is pretty simple.
* A descendant URI must have the ancestor as a prefix, and if the ancestor ends with
* a slash, there must be at least one character after that, otherwise the following
* character must be a slash with at least one character after it.
*
* Return value: %TRUE if @uri is a descendant of @ancestor
*/
gboolean
rb_uri_is_descendant (const char *uri, const char *ancestor)
{
int len;

if (g_str_has_prefix (uri, ancestor) == FALSE)
return FALSE;

len = strlen(ancestor);
if (ancestor[len - 1] == '/') {
/*
* following character in uri must be a new path segment, not
* the end of the uri. not considering multiple slashes here.
*/
return (uri[len] != '\0');
} else {
/*
* following character in uri must be a separator, with something after it.
* not considering multiple slashes here.
*/
return ((uri[len] == '/') && strlen(uri) > (len + 1));
}
}

/**
* rb_uri_get_filesystem_type:
* @uri: URI to get filesystem type for
Expand Down
1 change: 1 addition & 0 deletions lib/rb-file-helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ gboolean rb_uri_is_writable (const char *uri);
gboolean rb_uri_is_local (const char *uri);
gboolean rb_uri_is_hidden (const char *uri);
gboolean rb_uri_could_be_podcast (const char *uri, gboolean *is_opml);
gboolean rb_uri_is_descendant (const char *uri, const char *ancestor);
char * rb_uri_make_hidden (const char *uri);
char * rb_uri_get_dir_name (const char *uri);
char * rb_uri_get_short_path_name (const char *uri);
Expand Down
17 changes: 17 additions & 0 deletions tests/test-file-helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,22 @@ START_TEST (test_rb_check_dir_has_space)
}
END_TEST

START_TEST (test_rb_uri_is_descendant)
{
ck_assert (rb_uri_is_descendant ("file:///tmp", "file:///"));
ck_assert (rb_uri_is_descendant ("file:///tmp/2", "file:///"));
ck_assert (rb_uri_is_descendant ("file:///tmp/2", "file:///tmp"));
ck_assert (rb_uri_is_descendant ("file:///tmp/2", "file:///tmp/"));
ck_assert (rb_uri_is_descendant ("file:///tmp/", "file:///tmp") == FALSE);
ck_assert (rb_uri_is_descendant ("file:///tmp", "file:///tmp/") == FALSE);
ck_assert (rb_uri_is_descendant ("file:///tmp/", "file:///tmp/") == FALSE);
ck_assert (rb_uri_is_descendant ("file:///tmp", "file:///tmp") == FALSE);
ck_assert (rb_uri_is_descendant ("file:///tmp2", "file:///tmp") == FALSE);
ck_assert (rb_uri_is_descendant ("file:///tmp/2", "file:///tmp2") == FALSE);
ck_assert (rb_uri_is_descendant ("file:///tmp/22", "file:///tmp/2") == FALSE);
}
END_TEST

static Suite *
rb_file_helpers_suite ()
{
Expand All @@ -110,6 +126,7 @@ rb_file_helpers_suite ()

tcase_add_test (tc_chain, test_rb_uri_get_short_path_name);
tcase_add_test (tc_chain, test_rb_check_dir_has_space);
tcase_add_test (tc_chain, test_rb_uri_is_descendant);

return s;
}
Expand Down

0 comments on commit bb6fba6

Please sign in to comment.