url-mode: store URL in UTF-8, not UTF-32

The only time the URL is actually in UTF-32 is when we’re collecting
it (auto-detecting it) from the grid, since cells store their
character(s) in UTF-32.

Everything *after* that prefers the URL in UTF-8. So, do the
conversion while collecting the URL.

This patch also changes the URL activation code to strip the
‘file://user@host/’ prefix from file URIs that refer to files
on the *local* computer.
This commit is contained in:
Daniel Eklöf 2021-02-13 12:28:53 +01:00
parent 0bda60aacc
commit 3339915d20
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 61 additions and 44 deletions

View file

@ -227,7 +227,7 @@ typedef tll(struct ptmx_buffer) ptmx_buffer_list_t;
enum url_action { URL_ACTION_COPY, URL_ACTION_LAUNCH };
struct url {
wchar_t *url;
char *url;
wchar_t *text;
wchar_t *key;
struct coord start;

View file

@ -11,6 +11,7 @@
#include "selection.h"
#include "spawn.h"
#include "terminal.h"
#include "uri.h"
#include "util.h"
#include "xmalloc.h"
@ -36,42 +37,55 @@ execute_binding(struct seat *seat, struct terminal *term,
static void
activate_url(struct seat *seat, struct terminal *term, const struct url *url)
{
size_t chars = wcstombs(NULL, url->url, 0);
char *url_string = NULL;
if (chars != (size_t)-1) {
char *url_utf8 = xmalloc(chars + 1);
wcstombs(url_utf8, url->url, chars + 1);
char *scheme, *host, *path;
if (uri_parse(url->url, strlen(url->url), &scheme, NULL, NULL,
&host, NULL, &path, NULL, NULL) &&
strcmp(scheme, "file") == 0 &&
hostname_is_localhost(host))
{
/*
* This is a file in *this* computer. Pass only the
* filename to the URL-launcher.
*
* I.e. strip the file://user@host/ prefix.
*/
url_string = path;
free(scheme);
free(host);
} else
url_string = xstrdup(url->url);
switch (url->action) {
case URL_ACTION_COPY:
if (text_to_clipboard(seat, term, url_utf8, seat->kbd.serial)) {
/* Now owned by our clipboard “manager” */
url_utf8 = NULL;
}
break;
case URL_ACTION_LAUNCH: {
size_t argc;
char **argv;
if (spawn_expand_template(
&term->conf->url_launch, 1,
(const char *[]){"url"},
(const char *[]){url_utf8},
&argc, &argv))
{
spawn(term->reaper, term->cwd, argv, -1, -1, -1);
for (size_t i = 0; i < argc; i++)
free(argv[i]);
free(argv);
}
break;
}
switch (url->action) {
case URL_ACTION_COPY:
if (text_to_clipboard(seat, term, url_string, seat->kbd.serial)) {
/* Now owned by our clipboard “manager” */
url_string = NULL;
}
break;
free(url_utf8);
case URL_ACTION_LAUNCH: {
size_t argc;
char **argv;
if (spawn_expand_template(
&term->conf->url_launch, 1,
(const char *[]){"url"},
(const char *[]){url_string},
&argc, &argv))
{
spawn(term->reaper, term->cwd, argv, -1, -1, -1);
for (size_t i = 0; i < argc; i++)
free(argv[i]);
free(argv);
}
break;
}
}
free(url_string);
}
void
@ -313,14 +327,20 @@ auto_detected(const struct terminal *term, enum url_action action, url_list_t *u
start.row += term->grid->view;
end.row += term->grid->view;
tll_push_back(
*urls,
((struct url){
.url = xwcsdup(url),
.text = xwcsdup(L""),
.start = start,
.end = end,
.action = action}));
size_t chars = wcstombs(NULL, url, 0);
if (chars != (size_t)-1) {
char *url_utf8 = xmalloc((chars + 1) * sizeof(wchar_t));
wcstombs(url_utf8, url, chars + 1);
tll_push_back(
*urls,
((struct url){
.url = url_utf8,
.text = xwcsdup(L""),
.start = start,
.end = end,
.action = action}));
}
state = STATE_PROTOCOL;
len = 0;
@ -425,13 +445,10 @@ urls_assign_key_combos(const struct config *conf, url_list_t *urls)
#if defined(_DEBUG) && LOG_ENABLE_DBG
tll_foreach(*urls, it) {
char url[1024];
wcstombs(url, it->item.url, sizeof(url) - 1);
char key[32];
wcstombs(key, it->item.key, sizeof(key) - 1);
LOG_DBG("URL: %s (%s)", url, key);
LOG_DBG("URL: %s (%s)", it->item.url, key);
}
#endif
}