about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorIsaacM88 <izack23@gmail.com>2023-03-09 13:16:42 -0700
committerIsaacM88 <izack23@gmail.com>2023-03-09 15:02:26 -0700
commitd043d53948284ab7d1f3ae92c891703033cc98b1 (patch)
tree498b87e4012f5ae1f1a4b7ea1f5770ef26f889c2
parent4887d21a119ed67756a1544ec953aa010257bcb1 (diff)
downloadprofani-tty-d043d53948284ab7d1f3ae92c891703033cc98b1.tar.gz
Fix duplicate download IDs.
Fixes https://github.com/profanity-im/profanity/issues/1794

Explanation
The problem is the download's identifier. Downloads are given an ID so they can be referenced later when their progress changes. Currently, the download's ID is the download's URL. When you download the same file twice, you have two downloads with the same ID. Download progress updates are shown on the first of both downloads with the same ID.

Solution
Change the download's ID from its URL to a random number. A random ID is generated when get_random_string() is called from cmd_funcs.c. Several other functions are updated to cope with the new ID format.
-rw-r--r--src/command/cmd_funcs.c18
-rw-r--r--src/tools/aesgcm_download.c14
-rw-r--r--src/tools/aesgcm_download.h1
-rw-r--r--src/tools/http_common.c8
-rw-r--r--src/tools/http_common.h4
-rw-r--r--src/tools/http_download.c15
-rw-r--r--src/tools/http_download.h1
-rw-r--r--src/ui/window.c4
-rw-r--r--src/ui/window.h2
-rw-r--r--tests/unittests/tools/stub_aesgcm_download.c1
-rw-r--r--tests/unittests/tools/stub_http_download.c1
-rw-r--r--tests/unittests/ui/stub_ui.c2
12 files changed, 43 insertions, 28 deletions
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c
index 56a18bdb..dc471b90 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -9399,12 +9399,13 @@ cmd_slashguard(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)
+_url_aesgcm_method(ProfWin* window, const char* cmd_template, const char* url, const char* filename, const char* id)
 {
     AESGCMDownload* download = malloc(sizeof(AESGCMDownload));
     download->window = window;
     download->url = strdup(url);
     download->filename = strdup(filename);
+    download->id = strdup(id);
     if (cmd_template != NULL) {
         download->cmd_template = strdup(cmd_template);
     } else {
@@ -9417,13 +9418,14 @@ _url_aesgcm_method(ProfWin* window, const char* cmd_template, const char* url, c
 #endif
 
 void
-_url_http_method(ProfWin* window, const char* cmd_template, const char* url, const char* filename)
+_url_http_method(ProfWin* window, const char* cmd_template, const char* url, const char* filename, const char* id)
 {
 
     HTTPDownload* download = malloc(sizeof(HTTPDownload));
     download->window = window;
     download->url = strdup(url);
     download->filename = strdup(filename);
+    download->id = strdup(id);
     if (cmd_template != NULL) {
         download->cmd_template = strdup(cmd_template);
     } else {
@@ -9499,7 +9501,9 @@ cmd_url_open(ProfWin* window, const char* const command, gchar** args)
 
         // Download, decrypt and open the cleartext version of the AESGCM
         // encrypted file.
-        _url_aesgcm_method(window, cmd_template, url, filename);
+        gchar* id = get_random_string(4);
+        _url_aesgcm_method(window, cmd_template, url, filename, id);
+        g_free(id);
         goto out;
     }
 #endif
@@ -9553,10 +9557,14 @@ cmd_url_save(ProfWin* window, const char* const command, gchar** args)
 
     cmd_template = prefs_get_string(PREF_URL_SAVE_CMD);
     if (cmd_template == NULL && (g_strcmp0(scheme, "http") == 0 || g_strcmp0(scheme, "https") == 0)) {
-        _url_http_method(window, cmd_template, url, filename);
+        gchar* id = get_random_string(4);
+        _url_http_method(window, cmd_template, url, filename, id);
+        g_free(id);
 #ifdef HAVE_OMEMO
     } else if (g_strcmp0(scheme, "aesgcm") == 0) {
-        _url_aesgcm_method(window, cmd_template, url, filename);
+        gchar* id = get_random_string(4);
+        _url_aesgcm_method(window, cmd_template, url, filename, id);
+        g_free(id);
 #endif
     } else if (cmd_template != NULL) {
         _url_external_method(cmd_template, url, filename);
diff --git a/src/tools/aesgcm_download.c b/src/tools/aesgcm_download.c
index e7b5b42c..da935156 100644
--- a/src/tools/aesgcm_download.c
+++ b/src/tools/aesgcm_download.c
@@ -71,7 +71,7 @@ aesgcm_file_get(void* userdata)
     // and tag stored in the URL fragment.
     if (omemo_parse_aesgcm_url(aesgcm_dl->url, &https_url, &fragment) != 0) {
         cons_show_error("Download failed: Cannot parse URL '%s'.", aesgcm_dl->url);
-        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->url,
+        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id,
                                    "Download failed: Cannot parse URL '%s'.",
                                    aesgcm_dl->url);
         return NULL;
@@ -82,7 +82,7 @@ aesgcm_file_get(void* userdata)
     gchar* tmpname = NULL;
     gint tmpfd;
     if ((tmpfd = g_file_open_tmp("profanity.XXXXXX", &tmpname, NULL)) == -1) {
-        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->url,
+        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id,
                                    "Downloading '%s' failed: Unable to create "
                                    "temporary ciphertext file for writing "
                                    "(%s).",
@@ -93,7 +93,7 @@ aesgcm_file_get(void* userdata)
     // Open the target file for storing the cleartext.
     FILE* outfh = fopen(aesgcm_dl->filename, "wb");
     if (outfh == NULL) {
-        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->url,
+        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id,
                                    "Downloading '%s' failed: Unable to open "
                                    "output file at '%s' for writing (%s).",
                                    https_url, aesgcm_dl->filename,
@@ -106,6 +106,7 @@ aesgcm_file_get(void* userdata)
     HTTPDownload* http_dl = malloc(sizeof(HTTPDownload));
     http_dl->window = aesgcm_dl->window;
     http_dl->worker = aesgcm_dl->worker;
+    http_dl->id = strdup(aesgcm_dl->id);
     http_dl->url = strdup(https_url);
     http_dl->filename = strdup(tmpname);
     http_dl->cmd_template = NULL;
@@ -115,7 +116,7 @@ aesgcm_file_get(void* userdata)
 
     FILE* tmpfh = fopen(tmpname, "rb");
     if (tmpfh == NULL) {
-        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->url,
+        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id,
                                    "Downloading '%s' failed: Unable to open "
                                    "temporary file at '%s' for reading (%s).",
                                    aesgcm_dl->url, tmpname,
@@ -136,7 +137,7 @@ aesgcm_file_get(void* userdata)
     g_free(tmpname);
 
     if (crypt_res != GPG_ERR_NO_ERROR) {
-        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->url,
+        http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id,
                                    "Downloading '%s' failed: Failed to decrypt "
                                    "file (%s).",
                                    https_url, gcry_strerror(crypt_res));
@@ -156,7 +157,7 @@ aesgcm_file_get(void* userdata)
 
         // TODO: Log the error.
         if (!call_external(argv)) {
-            http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->url,
+            http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id,
                                        "Downloading '%s' failed: Unable to call "
                                        "command '%s' with file at '%s' (%s).",
                                        aesgcm_dl->url,
@@ -169,6 +170,7 @@ aesgcm_file_get(void* userdata)
         free(aesgcm_dl->cmd_template);
     }
 
+    free(aesgcm_dl->id);
     free(aesgcm_dl->filename);
     free(aesgcm_dl->url);
     free(aesgcm_dl);
diff --git a/src/tools/aesgcm_download.h b/src/tools/aesgcm_download.h
index c0096f1d..796b9389 100644
--- a/src/tools/aesgcm_download.h
+++ b/src/tools/aesgcm_download.h
@@ -50,6 +50,7 @@
 
 typedef struct aesgcm_download_t
 {
+    char* id;
     char* url;
     char* filename;
     char* cmd_template;
diff --git a/src/tools/http_common.c b/src/tools/http_common.c
index faad257f..4192a6ca 100644
--- a/src/tools/http_common.c
+++ b/src/tools/http_common.c
@@ -45,7 +45,7 @@
 #define FALLBACK_MSG ""
 
 void
-http_print_transfer_update(ProfWin* window, char* url, const char* fmt, ...)
+http_print_transfer_update(ProfWin* window, char* id, const char* fmt, ...)
 {
     va_list args;
 
@@ -54,13 +54,13 @@ http_print_transfer_update(ProfWin* window, char* url, const char* fmt, ...)
     g_string_vprintf(msg, fmt, args);
     va_end(args);
 
-    win_update_entry_message(window, url, msg->str);
+    win_update_entry_message(window, id, msg->str);
 
     g_string_free(msg, TRUE);
 }
 
 void
-http_print_transfer(ProfWin* window, char* url, const char* fmt, ...)
+http_print_transfer(ProfWin* window, char* id, const char* fmt, ...)
 {
     va_list args;
 
@@ -69,7 +69,7 @@ http_print_transfer(ProfWin* window, char* url, const char* fmt, ...)
     g_string_vprintf(msg, fmt, args);
     va_end(args);
 
-    win_print_http_transfer(window, msg->str, url);
+    win_print_http_transfer(window, msg->str, id);
 
     g_string_free(msg, TRUE);
 }
diff --git a/src/tools/http_common.h b/src/tools/http_common.h
index ac51b5a8..733d4d17 100644
--- a/src/tools/http_common.h
+++ b/src/tools/http_common.h
@@ -38,7 +38,7 @@
 
 #include "ui/window.h"
 
-void http_print_transfer(ProfWin* window, char* url, const char* fmt, ...);
-void http_print_transfer_update(ProfWin* window, char* url, const char* fmt, ...);
+void http_print_transfer(ProfWin* window, char* id, const char* fmt, ...);
+void http_print_transfer_update(ProfWin* window, char* id, const char* fmt, ...);
 
 #endif
diff --git a/src/tools/http_download.c b/src/tools/http_download.c
index 5a5b8ef8..71c9a1e1 100644
--- a/src/tools/http_download.c
+++ b/src/tools/http_download.c
@@ -112,12 +112,12 @@ http_file_get(void* userdata)
     download->bytes_received = 0;
 
     pthread_mutex_lock(&lock);
-    http_print_transfer(download->window, download->url,
+    http_print_transfer(download->window, download->id,
                         "Downloading '%s': 0%%", download->url);
 
     FILE* outfh = fopen(download->filename, "wb");
     if (outfh == NULL) {
-        http_print_transfer_update(download->window, download->url,
+        http_print_transfer_update(download->window, download->id,
                                    "Downloading '%s' failed: Unable to open "
                                    "output file at '%s' for writing (%s).",
                                    download->url, download->filename,
@@ -177,22 +177,22 @@ http_file_get(void* userdata)
     g_free(cert_path);
     if (err) {
         if (download->cancel) {
-            http_print_transfer_update(download->window, download->url,
+            http_print_transfer_update(download->window, download->id,
                                        "Downloading '%s' failed: "
                                        "Download was canceled",
                                        download->url);
         } else {
-            http_print_transfer_update(download->window, download->url,
+            http_print_transfer_update(download->window, download->id,
                                        "Downloading '%s' failed: %s",
                                        download->url, err);
         }
         free(err);
     } else {
         if (!download->cancel) {
-            http_print_transfer_update(download->window, download->url,
+            http_print_transfer_update(download->window, download->id,
                                        "Downloading '%s': done\nSaved to '%s'",
                                        download->url, download->filename);
-            win_mark_received(download->window, download->url);
+            win_mark_received(download->window, download->id);
         }
     }
 
@@ -203,7 +203,7 @@ http_file_get(void* userdata)
 
         // TODO: Log the error.
         if (!call_external(argv)) {
-            http_print_transfer_update(download->window, download->url,
+            http_print_transfer_update(download->window, download->id,
                                        "Downloading '%s' failed: Unable to call "
                                        "command '%s' with file at '%s' (%s).",
                                        download->url,
@@ -221,6 +221,7 @@ out:
     download_processes = g_slist_remove(download_processes, download);
     pthread_mutex_unlock(&lock);
 
+    free(download->id);
     free(download->url);
     free(download->filename);
     free(download);
diff --git a/src/tools/http_download.h b/src/tools/http_download.h
index 23344f6c..2c8d8a3d 100644
--- a/src/tools/http_download.h
+++ b/src/tools/http_download.h
@@ -49,6 +49,7 @@
 
 typedef struct http_download_t
 {
+    char* id;
     char* url;
     char* filename;
     char* cmd_template;
diff --git a/src/ui/window.c b/src/ui/window.c
index 4bbec7a4..064069c7 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1680,9 +1680,9 @@ win_appendln_highlight(ProfWin* window, theme_item_t theme_item, const char* con
 }
 
 void
-win_print_http_transfer(ProfWin* window, const char* const message, char* url)
+win_print_http_transfer(ProfWin* window, const char* const message, char* id)
 {
-    win_print_outgoing_with_receipt(window, "!", NULL, message, url, NULL);
+    win_print_outgoing_with_receipt(window, "!", NULL, message, id, NULL);
 }
 
 void
diff --git a/src/ui/window.h b/src/ui/window.h
index 3b78dc58..1c0a9007 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -74,7 +74,7 @@ void win_print_outgoing_muc_msg(ProfWin* window, char* show_char, const char* co
 void win_print_history(ProfWin* window, const ProfMessage* const message);
 void win_print_old_history(ProfWin* window, const ProfMessage* const message);
 
-void win_print_http_transfer(ProfWin* window, const char* const message, char* url);
+void win_print_http_transfer(ProfWin* window, const char* const message, char* id);
 
 void win_newline(ProfWin* window);
 void win_redraw(ProfWin* window);
diff --git a/tests/unittests/tools/stub_aesgcm_download.c b/tests/unittests/tools/stub_aesgcm_download.c
index 6f4cc0ce..07f411ca 100644
--- a/tests/unittests/tools/stub_aesgcm_download.c
+++ b/tests/unittests/tools/stub_aesgcm_download.c
@@ -8,6 +8,7 @@ typedef struct http_download_t HTTPDownload;
 
 typedef struct aesgcm_download_t
 {
+    char* id;
     char* url;
     char* filename;
     ProfWin* window;
diff --git a/tests/unittests/tools/stub_http_download.c b/tests/unittests/tools/stub_http_download.c
index cc7bddc5..f530b384 100644
--- a/tests/unittests/tools/stub_http_download.c
+++ b/tests/unittests/tools/stub_http_download.c
@@ -8,6 +8,7 @@ typedef struct prof_win_t ProfWin;
 
 typedef struct http_download_t
 {
+    char* id;
     char* url;
     char* filename;
     char* directory;
diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c
index d8272aab..edd8c336 100644
--- a/tests/unittests/ui/stub_ui.c
+++ b/tests/unittests/ui/stub_ui.c
@@ -490,7 +490,7 @@ mucwin_unset_message_char(ProfMucWin* mucwin)
 
 void win_update_entry_message(ProfWin* window, const char* const id, const char* const message){};
 void win_mark_received(ProfWin* window, const char* const id){};
-void win_print_http_transfer(ProfWin* window, const char* const message, char* url){};
+void win_print_http_transfer(ProfWin* window, const char* const message, char* id){};
 void win_print_loading_history(ProfWin* window){};
 
 void