diff options
author | Michael Vetter <jubalh@iodoru.org> | 2020-07-02 11:26:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-02 11:26:18 +0200 |
commit | 9774b0c5509193027d4f68df9dcb862455699cfc (patch) | |
tree | 1ade86abc718ae2cc06199c12c5d6a4f0cb49df0 /src/command | |
parent | 3af5f33489d1e065c9da03b0bb99eddff57816a4 (diff) | |
parent | 86cd33405e7f67647ce2c171e19bab4120201140 (diff) | |
download | profani-tty-9774b0c5509193027d4f68df9dcb862455699cfc.tar.gz |
Merge pull request #1374 from profanity-im/revampUrlopen
Rework /url and /executable for filetypes
Diffstat (limited to 'src/command')
-rw-r--r-- | src/command/cmd_ac.c | 26 | ||||
-rw-r--r-- | src/command/cmd_defs.c | 50 | ||||
-rw-r--r-- | src/command/cmd_funcs.c | 231 | ||||
-rw-r--r-- | src/command/cmd_funcs.h | 3 |
4 files changed, 270 insertions, 40 deletions
diff --git a/src/command/cmd_ac.c b/src/command/cmd_ac.c index eefca0cc..0d9d4cc5 100644 --- a/src/command/cmd_ac.c +++ b/src/command/cmd_ac.c @@ -124,7 +124,7 @@ static char* _avatar_autocomplete(ProfWin *window, const char *const input, gboo static char* _correction_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _correct_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _software_autocomplete(ProfWin *window, const char *const input, gboolean previous); -static char* _urlopen_autocomplete(ProfWin *window, const char *const input, gboolean previous); +static char* _url_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _executable_autocomplete(ProfWin *window, const char *const input, gboolean previous); static char* _script_autocomplete_func(const char *const prefix, gboolean previous, void *context); @@ -263,6 +263,7 @@ static Autocomplete logging_group_ac; static Autocomplete color_ac; static Autocomplete correction_ac; static Autocomplete avatar_ac; +static Autocomplete url_ac; static Autocomplete executable_ac; /*! @@ -1041,9 +1042,14 @@ cmd_ac_init(void) autocomplete_add(avatar_ac, "get"); autocomplete_add(avatar_ac, "open"); + url_ac = autocomplete_new(); + autocomplete_add(url_ac, "open"); + autocomplete_add(url_ac, "save"); + executable_ac = autocomplete_new(); autocomplete_add(executable_ac, "avatar"); autocomplete_add(executable_ac, "urlopen"); + autocomplete_add(executable_ac, "urlsave"); } void @@ -1362,6 +1368,7 @@ cmd_ac_reset(ProfWin *window) autocomplete_reset(color_ac); autocomplete_reset(correction_ac); autocomplete_reset(avatar_ac); + autocomplete_reset(url_ac); autocomplete_reset(executable_ac); autocomplete_reset(script_ac); @@ -1523,6 +1530,7 @@ cmd_ac_uninit(void) autocomplete_free(color_ac); autocomplete_free(correction_ac); autocomplete_free(avatar_ac); + autocomplete_free(url_ac); autocomplete_free(executable_ac); } @@ -1784,7 +1792,7 @@ _cmd_ac_complete_params(ProfWin *window, const char *const input, gboolean previ g_hash_table_insert(ac_funcs, "/correction", _correction_autocomplete); g_hash_table_insert(ac_funcs, "/correct", _correct_autocomplete); g_hash_table_insert(ac_funcs, "/software", _software_autocomplete); - g_hash_table_insert(ac_funcs, "/urlopen", _urlopen_autocomplete); + g_hash_table_insert(ac_funcs, "/url", _url_autocomplete); g_hash_table_insert(ac_funcs, "/executable", _executable_autocomplete); int len = strlen(input); @@ -4133,14 +4141,24 @@ _software_autocomplete(ProfWin *window, const char *const input, gboolean previo } static char* -_urlopen_autocomplete(ProfWin *window, const char *const input, gboolean previous) +_url_autocomplete(ProfWin *window, const char *const input, gboolean previous) { char *result = NULL; + result = autocomplete_param_with_ac(input, "/url", url_ac, TRUE, previous); + if (result) { + return result; + } + if (window->type == WIN_CHAT || window->type == WIN_MUC || window->type == WIN_PRIVATE) { - result = autocomplete_param_with_func(input, "/urlopen", wins_get_url, previous, window); + result = autocomplete_param_with_func(input, "/url open", wins_get_url, previous, window); + if (result) { + return result; + } + + result = autocomplete_param_with_func(input, "/url save", wins_get_url, previous, window); } return result; diff --git a/src/command/cmd_defs.c b/src/command/cmd_defs.c index 815fe9d8..0e91f803 100644 --- a/src/command/cmd_defs.c +++ b/src/command/cmd_defs.c @@ -2506,40 +2506,50 @@ static struct cmd_t command_defs[] = "/software xmpp.vanaheimr.edda") }, - { "/urlopen", - parse_args, 1, -1, NULL, - CMD_NOSUBFUNCS - CMD_MAINFUNC(cmd_urlopen) - CMD_TAGS( - CMD_TAG_CHAT, - CMD_TAG_GROUPCHAT) - CMD_SYN( - "/urlopen <url>") - CMD_DESC( - "Open the URL") - CMD_ARGS( - { "<url>", "URL to open."}) - CMD_NOEXAMPLES - }, - { "/executable", - parse_args, 2, 2, &cons_executable_setting, + parse_args, 2, 4, &cons_executable_setting, CMD_NOSUBFUNCS CMD_MAINFUNC(cmd_executable) CMD_TAGS( CMD_TAG_DISCOVERY) CMD_SYN( "/executable avatar <cmd>", - "/executable urlopen <cmd>") + "/executable urlopen (<fileType>|DEF <require_save> <cmd>", + "/executable urlsave (<protocol>|DEF) <cmd>") CMD_DESC( "Configure executable that should be called upon a certain command." "Default is xdg-open.") CMD_ARGS( { "avatar", "Set executable that is run in /avatar open. Use your favourite image viewer." }, - { "urlopen", "Set executable that is run in /urlopen. Use your favourite browser." }) + { "urlopen", "Set executable that is run in /url open for a given file type. It may be your favorite browser or a specific viewer. Use DEF to set default command for undefined file type." }, + { "urlsave", "Set executable that is run in /url save for a given protocol. Use your favourite downloader. Use DEF to set default command for undefined protocol."}) CMD_EXAMPLES( "/executable avatar xdg-open", - "/executable urlopen firefox") + "/executable urlopen DEF false \"xdg-open %u\"", + "/executable urlopen html false \"firefox %u\"", + "/executable urlsave aesgcm \"omut -d %u %p\"") + }, + + { "/url", + parse_args, 2, 3, NULL, + CMD_SUBFUNCS( + { "open", cmd_url_open}, + { "save", cmd_url_save }) + CMD_NOMAINFUNC + CMD_TAGS( + CMD_TAG_CHAT, + CMD_TAG_GROUPCHAT) + CMD_SYN( + "/url open <url>", + "/url save <url> [<path>]") + CMD_DESC( + "Deal with URLs") + CMD_ARGS( + { "open", "Open URL with predefined executable." }, + { "save", "Save URL to optional path, default path is current directory"}) + CMD_EXAMPLES( + "/url open https://profanity-im.github.io", + "/url save https://profanity-im.github.io/guide/latest/userguide.html /home/user/Download/") }, }; diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index bd4dc95f..b60c9667 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -44,6 +44,8 @@ #include <errno.h> #include <assert.h> #include <glib.h> +#include <glib/gstdio.h> +#include <gio/gio.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> @@ -9071,29 +9073,210 @@ cmd_slashguard(ProfWin *window, const char *const command, gchar **args) } gboolean -cmd_urlopen(ProfWin *window, const char *const command, gchar **args) +cmd_url_open(ProfWin *window, const char *const command, gchar **args) { - if (window->type == WIN_CHAT || - window->type == WIN_MUC || - window->type == WIN_PRIVATE) { + if (window->type != WIN_CHAT && + window->type != WIN_MUC && + window->type != WIN_PRIVATE) { + cons_show("url open not supported in this window"); + return TRUE; + } - if (args[0] == NULL) { - cons_bad_cmd_usage(command); - return TRUE; + if (args[1] == NULL) { + cons_bad_cmd_usage(command); + return TRUE; + } + + gboolean require_save = false; + + gchar *fileStart = g_strrstr(args[1], "/"); + if (fileStart == NULL) { + cons_show("URL '%s' is not valid.", args[1]); + return TRUE; + } + + fileStart++; + if (((char*)(fileStart - 2))[0] == '/' && + ((char*)(fileStart - 3))[0] == ':' + ){ + // If the '/' is last character of the '://' string, there will be no suffix + // Therefore, it is considered that there is no file name in the URL and + // fileStart is set to the end of the URL. + fileStart = args[1] + strlen(args[1]); + } + + gchar *suffix = NULL; + gchar *suffixStart = g_strrstr(fileStart, "."); + if (suffixStart != NULL) { + suffixStart++; + gchar *suffixEnd = g_strrstr(suffixStart, "#"); + if(suffixEnd == NULL) { + suffix = g_strdup(suffixStart); + } else { + suffix = g_strndup(suffixStart, suffixEnd - suffixStart); } + } + + gchar **suffix_cmd_pref = prefs_get_string_list_with_option(PREF_URL_OPEN_CMD, NULL); + if (suffix != NULL) { + gchar *lowercase_suffix = g_ascii_strdown(suffix, -1); + g_strfreev(suffix_cmd_pref); + suffix_cmd_pref = prefs_get_string_list_with_option(PREF_URL_OPEN_CMD, lowercase_suffix); + g_free(lowercase_suffix); + g_free(suffix); + } + + if (0 == g_strcmp0(suffix_cmd_pref[0], "true")) { + require_save = true; + } - gchar* cmd = prefs_get_string(PREF_URL_OPEN_CMD); - gchar *argv[] = {cmd, args[0], NULL}; + gchar *suffix_cmd = g_strdup(suffix_cmd_pref[1]); + g_strfreev(suffix_cmd_pref); - if (!call_external(argv, NULL, NULL)) { - cons_show_error("Unable to open url: check the logs for more information."); + gchar *scheme = g_uri_parse_scheme(args[1]); + if( 0 == g_strcmp0(scheme, "aesgcm")) { + require_save = true; + } + g_free(scheme); + + if (require_save) { + gchar *save_args[] = { "open", args[1], "/tmp/profanity.tmp", NULL}; + cmd_url_save(window, command, save_args); + } + + gchar **argv = g_strsplit(suffix_cmd, " ", 0); + guint num_args = 0; + while (argv[num_args]) { + if (0 == g_strcmp0(argv[num_args], "%u")) { + g_free(argv[num_args]); + if (require_save) { + argv[num_args] = g_strdup("/tmp/profanity.tmp"); + } else { + argv[num_args] = g_strdup(args[1]); + } + break; } + num_args++; + } + + if (!call_external(argv, NULL, NULL)) { + cons_show_error("Unable to open url: check the logs for more information."); + } - g_free(cmd); + if (require_save) { + g_unlink("/tmp/profanity.tmp"); + } + + g_strfreev(argv); + g_free(suffix_cmd); + + return TRUE; +} + +gboolean +cmd_url_save(ProfWin *window, const char *const command, gchar **args) +{ + if (window->type != WIN_CHAT && + window->type != WIN_MUC && + window->type != WIN_PRIVATE) { + cons_show("url save not supported in this window"); + return TRUE; + } + + if (args[1] == NULL) { + cons_bad_cmd_usage(command); + return TRUE; + } + + gchar *uri = args[1]; + gchar *target_path = g_strdup(args[2]); + + GFile *file = g_file_new_for_uri(uri); + + gchar *target_dir = NULL; + gchar *base_name = NULL; + + if (target_path == NULL) { + target_dir = g_strdup("./"); + base_name = g_file_get_basename(file); + if (0 == g_strcmp0(base_name, ".")) { + g_free(base_name); + base_name = g_strdup("saved_url_content.html"); + } + target_path = g_strconcat(target_dir, base_name, NULL); + } + + if (g_file_test(target_path, G_FILE_TEST_EXISTS) && + g_file_test(target_path, G_FILE_TEST_IS_DIR) + ) { + target_dir = g_strdup(target_path); + base_name = g_file_get_basename(file); + g_free(target_path); + target_path = g_strconcat(target_dir, "/", base_name, NULL); + } + + g_object_unref(file); + file = NULL; + + if (base_name == NULL) { + base_name = g_path_get_basename(target_path); + target_dir = g_path_get_dirname(target_path); + } + + if (!g_file_test(target_dir, G_FILE_TEST_EXISTS) || + !g_file_test(target_dir, G_FILE_TEST_IS_DIR)) { + cons_show("%s does not exist or is not a directory.", target_dir); + g_free(target_path); + g_free(target_dir); + g_free(base_name); + return TRUE; + } + + gchar *scheme = g_uri_parse_scheme(uri); + if (scheme == NULL) { + cons_show("URL '%s' is not valid.", uri); + g_free(target_path); + g_free(target_dir); + g_free(base_name); + return TRUE; + } + + gchar *scheme_cmd = NULL; + + if (0 == g_strcmp0(scheme, "http") + || 0 == g_strcmp0(scheme, "https") + || 0 == g_strcmp0(scheme, "aesgcm") + ) { + scheme_cmd = prefs_get_string_with_option(PREF_URL_SAVE_CMD, scheme); + } + + g_free(scheme); + + gchar **argv = g_strsplit(scheme_cmd, " ", 0); + g_free(scheme_cmd); + + guint num_args = 0; + while (argv[num_args]) { + if (0 == g_strcmp0(argv[num_args], "%u")) { + g_free(argv[num_args]); + argv[num_args] = g_strdup(uri); + } else if (0 == g_strcmp0(argv[num_args], "%p")) { + g_free(argv[num_args]); + argv[num_args] = target_path; + } + num_args++; + } + + if (!call_external(argv, NULL, NULL)) { + cons_show_error("Unable to save url: check the logs for more information."); } else { - cons_show("urlopen not supported in this window"); + cons_show("URL '%s' has been saved into '%s'.", uri, target_path); } + g_free(target_dir); + g_free(base_name); + g_strfreev(argv); + return TRUE; } @@ -9104,8 +9287,26 @@ cmd_executable(ProfWin *window, const char *const command, gchar **args) prefs_set_string(PREF_AVATAR_CMD, args[1]); cons_show("Avatar command set to: %s", args[1]); } else if (g_strcmp0(args[0], "urlopen") == 0) { - prefs_set_string(PREF_URL_OPEN_CMD, args[1]); - cons_show("urlopen command set to: %s", args[1]); + if (g_strv_length(args) < 4) { + cons_bad_cmd_usage(command); + return TRUE; + } + + gchar *str = g_strjoinv(" ", &args[3]); + const gchar* const list[] = {args[2], str, NULL}; + prefs_set_string_list_with_option(PREF_URL_OPEN_CMD, args[1], list); + cons_show("`url open` command set to: %s for %s files", str, args[1]); + g_free(str); + } else if (g_strcmp0(args[0], "urlsave") == 0) { + if (g_strv_length(args) < 3) { + cons_bad_cmd_usage(command); + return TRUE; + } + + gchar *str = g_strjoinv(" ", &args[2]); + prefs_set_string_with_option(PREF_URL_SAVE_CMD, args[1], str); + cons_show("`url save` command set to: %s for scheme %s", str, args[1]); + g_free(str); } else { cons_bad_cmd_usage(command); } diff --git a/src/command/cmd_funcs.h b/src/command/cmd_funcs.h index b75755cb..955a2e39 100644 --- a/src/command/cmd_funcs.h +++ b/src/command/cmd_funcs.h @@ -236,7 +236,8 @@ gboolean cmd_correction(ProfWin *window, const char *const command, gchar **args gboolean cmd_correct(ProfWin *window, const char *const command, gchar **args); gboolean cmd_slashguard(ProfWin *window, const char *const command, gchar **args); gboolean cmd_serversoftware(ProfWin *window, const char *const command, gchar **args); -gboolean cmd_urlopen(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_url_open(ProfWin *window, const char *const command, gchar **args); +gboolean cmd_url_save(ProfWin *window, const char *const command, gchar **args); gboolean cmd_executable(ProfWin *window, const char *const command, gchar **args); #endif |