about summary refs log tree commit diff stats
path: root/src/command
diff options
context:
space:
mode:
authorWilliam Wennerström <william@wstrm.dev>2020-12-03 16:43:07 +0100
committerWilliam Wennerström <william@wstrm.dev>2020-12-03 16:54:06 +0100
commit3a6597ee2967f91f49a1b4e17cf0595f37064587 (patch)
tree82d021e0c76b6980d908952edd4402272f14dcab /src/command
parent1bb6cecee69d5167220a18cc4c125c215784de66 (diff)
downloadprofani-tty-3a6597ee2967f91f49a1b4e17cf0595f37064587.tar.gz
Refactor for threaded external executable for built-in download methods
Diffstat (limited to 'src/command')
-rw-r--r--src/command/cmd_funcs.c289
1 files changed, 118 insertions, 171 deletions
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c
index c6557159..88461f1d 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -60,6 +60,7 @@
 #include "command/cmd_funcs.h"
 #include "command/cmd_defs.h"
 #include "command/cmd_ac.h"
+#include "config/files.h"
 #include "config/accounts.h"
 #include "config/account.h"
 #include "config/preferences.h"
@@ -1089,7 +1090,7 @@ _writecsv(int fd, const char* const str)
     size_t len = strlen(str);
     char* s = malloc(2 * len * sizeof(char));
     char* c = s;
-    for (int i =0; i < strlen(str); i++) {
+    for (int i = 0; i < strlen(str); i++) {
         if (str[i] != '"')
             *c++ = str[i];
         else {
@@ -9058,169 +9059,59 @@ cmd_slashguard(ProfWin* window, const char* const command, gchar** args)
     return TRUE;
 }
 
-gboolean
-cmd_url_open(ProfWin* window, const char* const command, gchar** args)
+#ifdef HAVE_OMEMO
+void
+_url_aesgcm_method(ProfWin* window, const char* cmd_template, const char* url, const char* filename)
 {
-    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[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* suffix_cmd = g_strdup(suffix_cmd_pref[1]);
-    g_strfreev(suffix_cmd_pref);
-
-    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.");
-    }
-
-    if (require_save) {
-        g_unlink("/tmp/profanity.tmp");
+    AESGCMDownload* download = malloc(sizeof(AESGCMDownload));
+    download->window = window;
+    download->url = strdup(url);
+    download->filename = strdup(filename);
+    if (cmd_template != NULL) {
+        download->cmd_template = strdup(cmd_template);
+    } else {
+        download->cmd_template = NULL;
     }
 
-    g_strfreev(argv);
-    g_free(suffix_cmd);
-
-    return TRUE;
-}
-
-void
-_url_open_fallback_method(ProfWin* window, const char* url, const char* filename)
-{
-    // TODO(wstrm): Use _url_save_fallback_method?.
-    // We probably want to do the cmd_url_open in a separate thread and wait for
-    // the transfer to be finished before calling call_external.
+    pthread_create(&(download->worker), NULL, &aesgcm_file_get, download);
+    aesgcm_download_add_download(download);
 }
+#endif
 
 void
-_url_save_fallback_method(ProfWin* window, const char* url, const char* filename)
+_url_http_method(ProfWin* window, const char* cmd_template, const char* url, const char* filename)
 {
-    gchar* scheme = g_uri_parse_scheme(url);
-
-#ifdef HAVE_OMEMO
-    if (g_strcmp0(scheme, "aesgcm") == 0) {
-        AESGCMDownload* download = malloc(sizeof(AESGCMDownload));
-        download->window = window;
-        download->url = strdup(url);
-        download->filename = strdup(filename);
-
-        pthread_create(&(download->worker), NULL, &aesgcm_file_get, download);
-        aesgcm_download_add_download(download);
-
-        free(scheme);
-
-        return;
-    }
-#endif
 
     HTTPDownload* download = malloc(sizeof(HTTPDownload));
     download->window = window;
     download->url = strdup(url);
     download->filename = strdup(filename);
+    if (cmd_template != NULL) {
+        download->cmd_template = strdup(cmd_template);
+    } else {
+        download->cmd_template = NULL;
+    }
 
     pthread_create(&(download->worker), NULL, &http_file_get, download);
     http_download_add_download(download);
-
-    free(scheme);
 }
 
 void
-_url_save_external_method(const char* scheme_cmd, const char* url, const char* filename)
+_url_external_method(const char* cmd_template, const char* url, const char* filename)
 {
-    gchar** argv = g_strsplit(scheme_cmd, " ", 0);
-
-    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(url);
-        } else if (0 == g_strcmp0(argv[num_args], "%p")) {
-            g_free(argv[num_args]);
-            argv[num_args] = strdup(filename);
-        }
-        num_args++;
-    }
+    gchar** argv = format_call_external_argv(cmd_template, url, filename);
 
     if (!call_external(argv, NULL, NULL)) {
-        cons_show_error("Unable to save url: check the logs for more information.");
+        cons_show_error("Unable to call external executable for url: check the logs for more information.");
     } else {
-        cons_show("URL '%s' has been saved to '%s'.", url, filename);
+        cons_show("URL '%s' has been called with '%s'.", cmd_template);
     }
+
+    g_strfreev(argv);
 }
 
 char*
-_make_unique_filename(const char* filename)
+_unique_filename(const char* filename)
 {
     char* unique = strdup(filename);
 
@@ -9242,29 +9133,9 @@ _make_unique_filename(const char* filename)
     return unique;
 }
 
-gboolean
-cmd_url_save(ProfWin* window, const char* const command, gchar** args)
+char*
+_unique_filename_from_url(char* url, char* path)
 {
-    if (window->type != WIN_CHAT && window->type != WIN_MUC && window->type != WIN_PRIVATE) {
-        cons_show_error("`/url save` is not supported in this window.");
-        return TRUE;
-    }
-
-    if (args[1] == NULL) {
-        cons_bad_cmd_usage(command);
-        return TRUE;
-    }
-
-    gchar* url = args[1];
-    gchar* path = g_strdup(args[2]);
-
-    gchar* scheme = g_uri_parse_scheme(url);
-    if (scheme == NULL) {
-        cons_show("URL '%s' is not valid.", url);
-        g_free(url);
-        return TRUE;
-    }
-
     gchar* directory = NULL;
     gchar* basename = NULL;
     if (path != NULL) {
@@ -9279,7 +9150,7 @@ cmd_url_save(ProfWin* window, const char* const command, gchar** args)
 
     if (!g_file_test(directory, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
         cons_show_error("Directory '%s' does not exist or is not a directory.", directory);
-        return TRUE;
+        return NULL;
     }
 
     if (!basename) {
@@ -9289,30 +9160,106 @@ cmd_url_save(ProfWin* window, const char* const command, gchar** args)
     char* filename = NULL;
     filename = g_build_filename(directory, basename, NULL);
 
-    char* unique_filename = _make_unique_filename(filename);
+    char* unique_filename = _unique_filename(filename);
     if (!unique_filename) {
         cons_show_error("Failed to generate an unique filename from '%s'.", filename);
         free(filename);
-        return TRUE;
+        return NULL;
     }
 
     free(filename);
-    filename = unique_filename;
+    return unique_filename;
+}
+
+gboolean
+cmd_url_open(ProfWin* window, const char* const command, gchar** args)
+{
+    if (window->type != WIN_CHAT && window->type != WIN_MUC && window->type != WIN_PRIVATE) {
+        cons_show("url open not supported in this window");
+        return TRUE;
+    }
+
+    gchar* url = args[1];
+    if (url == NULL) {
+        cons_bad_cmd_usage(command);
+        return TRUE;
+    }
+
+    gchar* scheme = g_uri_parse_scheme(url);
+    if (scheme == NULL) {
+        cons_show("URL '%s' is not valid.", args[1]);
+        return TRUE;
+    }
+
+    char* cmd_template = prefs_get_string_with_option(PREF_URL_OPEN_CMD, scheme);
+    if (cmd_template == NULL) {
+        cons_show("No default open command found in url open preferences");
+        return TRUE;
+    }
+
+#ifdef HAVE_OMEMO
+    // OMEMO URLs (aesgcm://) must be saved and decrypted before being opened.
+    if (0 == g_strcmp0(scheme, "aesgcm")) {
+        char* filename = _unique_filename_from_url(url, files_get_data_path(DIR_DOWNLOADS));
+        _url_aesgcm_method(window, cmd_template, url, filename);
 
-    gchar* scheme_cmd = prefs_get_string_with_option(PREF_URL_SAVE_CMD, scheme);
-    if (scheme_cmd == NULL) {
+        free(filename);
+        goto out;
+    }
+#endif
+
+    _url_external_method(cmd_template, url, NULL);
+
+#ifdef HAVE_OMEMO
+out:
+#endif
+    free(cmd_template);
+    free(scheme);
+
+    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_error("`/url save` is not supported in this window.");
+        return TRUE;
+    }
+
+    if (args[1] == NULL) {
+        cons_bad_cmd_usage(command);
+        return TRUE;
+    }
+
+    gchar* url = args[1];
+    gchar* path = g_strdup(args[2]);
+
+    gchar* scheme = g_uri_parse_scheme(url);
+    if (scheme == NULL) {
+        cons_show("URL '%s' is not valid.", args[1]);
+        return TRUE;
+    }
+
+    char* filename = _unique_filename_from_url(url, path);
+
+    char* cmd_template = prefs_get_string_with_option(PREF_URL_SAVE_CMD, scheme);
+    if (cmd_template == NULL) {
         if (g_strcmp0(scheme, "http") == 0
-            || g_strcmp0(scheme, "https") == 0
-            || g_strcmp0(scheme, "aesgcm") == 0) {
-            _url_save_fallback_method(window, url, filename);
+            || g_strcmp0(scheme, "https") == 0) {
+            _url_http_method(window, url, filename, cmd_template);
+#ifdef HAVE_OMEMO
+        } else if (g_strcmp0(scheme, "aesgcm") == 0) {
+            _url_aesgcm_method(window, url, filename, cmd_template);
+#endif
         } else {
             cons_show_error("No download method defined for the scheme '%s'.", scheme);
         }
     } else {
-        _url_save_external_method(scheme_cmd, url, filename);
+        _url_external_method(cmd_template, url, filename);
     }
 
-    g_free(scheme_cmd);
+    free(cmd_template);
 
     return TRUE;
 }