Skip to content

Commit

Permalink
open-uri: add temporary keyfile deserialization
Browse files Browse the repository at this point in the history
This adds support for deserializing URI handlers from `.desktop`
overrides in the user data directory, with the format:

```
[URI Handler example.com]
Scheme=https;
Host=example.com;*.example.com;
Port=443;
Path=/resource/*
```
  • Loading branch information
andyholmes committed Apr 29, 2024
1 parent d29b327 commit 1833e6f
Showing 1 changed file with 108 additions and 1 deletion.
109 changes: 108 additions & 1 deletion src/open-uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,113 @@ uri_handler_free (UriHandler *handler)
g_free (handler);
}

/*
* Temporary deserialization
*/
static UriHandler *
uri_handler_deserialize (GKeyFile *keyfile,
const char *group)
{
UriHandler *ret = NULL;
g_auto (GStrv) ports = NULL;

g_assert (keyfile != NULL);
g_assert (group != NULL && *group != '\0');

ret = g_new0 (UriHandler, 1);
ret->schemes = g_key_file_get_string_list (keyfile, group, "Scheme", NULL, NULL);
ret->hosts = g_key_file_get_string_list (keyfile, group, "Host", NULL, NULL);
ret->paths = g_key_file_get_string_list (keyfile, group, "Path", NULL, NULL);

ports = g_key_file_get_string_list (keyfile, group, "Port", NULL, NULL);
if (ports != NULL)
{
unsigned int n_ports = g_strv_length (ports);

ret->ports = g_array_new (TRUE, TRUE, sizeof (uint16_t));
for (unsigned int i = 0; i < n_ports; i++)
{
guint64 port = g_ascii_strtoull (ports[i], NULL, 10);

if (port > 0 && port < UINT16_MAX)
g_array_append_vals (ret->ports, (uint16_t *)&port, 1);
}
}

return ret;
}

static GHashTable *
uri_handler_load_keyfiles (void)
{
GHashTable *ret = NULL;
g_autoptr (GFile) search_path = NULL;
g_autoptr (GFileEnumerator) search_dir = NULL;

ret = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify)g_ptr_array_unref);

search_path = g_file_new_build_filename (g_get_user_data_dir (),
"applications",
NULL);
search_dir = g_file_enumerate_children (search_path,
G_FILE_ATTRIBUTE_STANDARD_NAME,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL,
NULL);

while (TRUE)
{
GFile *file;
g_autoptr (GPtrArray) handlers = NULL;
g_autoptr (GKeyFile) keyfile = NULL;
g_auto (GStrv) groups = NULL;
g_autofree char *filepath = NULL;

if (!g_file_enumerator_iterate (search_dir, NULL, &file, NULL, NULL))
break;

if (file == NULL)
break;

filepath = g_file_get_path (file);
keyfile = g_key_file_new ();
if (!g_key_file_load_from_file (keyfile, filepath, G_KEY_FILE_NONE, NULL))
continue;

handlers = g_ptr_array_new_with_free_func ((GDestroyNotify)uri_handler_free);
groups = g_key_file_get_groups (keyfile, NULL);
for (size_t i = 0; groups[i] != NULL; i++)
{
UriHandler *handler = NULL;

if (!g_str_has_prefix (groups[i], "URI Handler"))
continue;

handler = uri_handler_deserialize (keyfile, groups[i]);
g_ptr_array_add (handlers, handler);
}

if (handlers->len > 0)
{
g_autofree char *basename = NULL;
g_autofree char *app_id = NULL;

basename = g_file_get_basename (file);
app_id = g_strndup (basename, strlen (basename) - strlen (".desktop"));

g_debug ("Found %u handlers for %s", handlers->len, app_id);
g_hash_table_replace (ret,
g_steal_pointer (&app_id),
g_steal_pointer (&handlers));
}
}

return ret;
}

static gboolean
uri_handler_match (UriHandler *handler,
GUri *uri)
Expand Down Expand Up @@ -654,7 +761,7 @@ find_patterned_choices (XdpAppInfo *app,
return;
}

candidates = g_hash_table_new (g_str_hash, g_str_equal);
candidates = uri_handler_load_keyfiles ();
builder = g_strv_builder_new ();

g_hash_table_iter_init (&iter, candidates);
Expand Down

0 comments on commit 1833e6f

Please sign in to comment.