[rhythmbox/uri-is-descendant: 1/2] lib: add rb_uri_is_descendant
- From: Jonathan Matthew <jmatthew src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rhythmbox/uri-is-descendant: 1/2] lib: add rb_uri_is_descendant
- Date: Fri, 26 Mar 2021 03:55:46 +0000 (UTC)
commit bb6fba636f870c4a820abc6614582e045d6e9195
Author: Jonathan Matthew <jonathan d14n org>
Date: Tue Mar 23 23:02:36 2021 +1000
lib: add rb_uri_is_descendant
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.
lib/rb-file-helpers.c | 42 ++++++++++++++++++++++++++++++++++++++++++
lib/rb-file-helpers.h | 1 +
tests/test-file-helpers.c | 17 +++++++++++++++++
3 files changed, 60 insertions(+)
---
diff --git a/lib/rb-file-helpers.c b/lib/rb-file-helpers.c
index bc8e49ddf..4e5b2a53b 100644
--- a/lib/rb-file-helpers.c
+++ b/lib/rb-file-helpers.c
@@ -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
diff --git a/lib/rb-file-helpers.h b/lib/rb-file-helpers.h
index 606eeb31e..8196f63fb 100644
--- a/lib/rb-file-helpers.h
+++ b/lib/rb-file-helpers.h
@@ -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);
diff --git a/tests/test-file-helpers.c b/tests/test-file-helpers.c
index 855b15fc0..f20d85e99 100644
--- a/tests/test-file-helpers.c
+++ b/tests/test-file-helpers.c
@@ -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 ()
{
@@ -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;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]