From a9ef000328b0f6ac8a9980e3bf9d26dad5ffc911 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Tue, 24 Mar 2026 21:20:24 +0000 Subject: [PATCH] fix: Improve status reporting and filename handling for /url save Use the original aesgcm:// URL when downloading OMEMO downloads. Then in the final message use the decrypted file destination instead of the internal temporary path. Use the unique download ID instead of the URL for message updates to have proper progress reporting. Unify the final transfer status to "done" across both downloads and uploads. Fixes: https://github.com/profanity-im/profanity/issues/1939 Signed-off-by: Michael Vetter --- src/command/cmd_funcs.c | 28 ++++++++++++++++++++-------- src/tools/aesgcm_download.c | 8 ++++++-- src/tools/http_download.c | 31 +++++++++++++++++++------------ src/tools/http_download.h | 2 ++ src/tools/http_upload.c | 10 ++++++++-- 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index dbf92d21..68d6188a 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9209,18 +9209,30 @@ _prepare_filename(ProfWin* window, gchar* url, gchar* path) break; } - // Ensure that the downloads directory exists for saving cleartexts. - auto_gchar gchar* downloads_dir = path ? get_expanded_path(path) : files_get_download_path(jid); - if (g_mkdir_with_parents(downloads_dir, S_IRWXU) != 0) { - cons_show_error("Failed to create download directory " - "at '%s' with error '%s'", - downloads_dir, strerror(errno)); - return NULL; + auto_gchar gchar* expanded_path = path ? get_expanded_path(path) : files_get_download_path(jid); + + // If path is provided and doesn't look like a directory, create its parent. + // Otherwise, create the directory itself. + if (path && !g_str_has_suffix(expanded_path, G_DIR_SEPARATOR_S) && !g_file_test(expanded_path, G_FILE_TEST_IS_DIR)) { + auto_gchar gchar* dirname = g_path_get_dirname(expanded_path); + if (g_mkdir_with_parents(dirname, S_IRWXU) != 0) { + cons_show_error("Failed to create download directory " + "at '%s' with error '%s'", + dirname, strerror(errno)); + return NULL; + } + } else { + if (g_mkdir_with_parents(expanded_path, S_IRWXU) != 0) { + cons_show_error("Failed to create download directory " + "at '%s' with error '%s'", + expanded_path, strerror(errno)); + return NULL; + } } // Generate an unique filename from the URL that should be stored in the // downloads directory. - return unique_filename_from_url(url, downloads_dir); + return unique_filename_from_url(url, expanded_path); } #ifdef HAVE_OMEMO diff --git a/src/tools/aesgcm_download.c b/src/tools/aesgcm_download.c index 1c34074e..e6daae71 100644 --- a/src/tools/aesgcm_download.c +++ b/src/tools/aesgcm_download.c @@ -80,9 +80,11 @@ aesgcm_file_get(void* userdata) http_dl->worker = aesgcm_dl->worker; http_dl->id = strdup(aesgcm_dl->id); http_dl->url = strdup(https_url); + http_dl->display_url = strdup(aesgcm_dl->url); http_dl->filename = strdup(tmpname); http_dl->cmd_template = NULL; http_dl->silent = FALSE; + http_dl->silent_done = TRUE; http_dl->return_bytes_received = TRUE; aesgcm_dl->http_dl = http_dl; @@ -113,10 +115,12 @@ aesgcm_file_get(void* userdata) http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, "Downloading '%s' failed: Failed to decrypt " "file (%s).", - https_url, gcry_strerror(crypt_res)); + aesgcm_dl->url, gcry_strerror(crypt_res)); } else { http_print_transfer_update(aesgcm_dl->window, aesgcm_dl->id, - "Decrypted file saved to '%s'", aesgcm_dl->filename); + "Downloading '%s': done\nSaved to '%s'", + aesgcm_dl->url, aesgcm_dl->filename); + win_mark_received(aesgcm_dl->window, aesgcm_dl->id); } if (aesgcm_dl->cmd_template != NULL) { diff --git a/src/tools/http_download.c b/src/tools/http_download.c index 720cc40c..8e14fa66 100644 --- a/src/tools/http_download.c +++ b/src/tools/http_download.c @@ -32,7 +32,6 @@ #include "common.h" GSList* download_processes = NULL; -gboolean silent = FALSE; static int _xferinfo(void* userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) @@ -58,9 +57,16 @@ _xferinfo(void* userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultot dlperc = (100 * dlnow) / dltotal; } - if (!silent) - http_print_transfer_update(download->window, download->url, - "Downloading '%s': %d%%", download->url, dlperc); + if (!download->silent) { + const char* url = download->display_url ? download->display_url : download->url; + if (dlnow == dltotal && dltotal > 0) { + http_print_transfer_update(download->window, download->id, + "Downloading '%s': done", url); + } else { + http_print_transfer_update(download->window, download->id, + "Downloading '%s': %d%%", url, dlperc); + } + } pthread_mutex_unlock(&lock); @@ -85,15 +91,15 @@ http_file_get(void* userdata) CURL* curl; CURLcode res; - silent = download->silent; download->cancel = 0; download->bytes_received = 0; pthread_mutex_lock(&lock); - if (!silent) { + const char* display_url = download->display_url ? download->display_url : download->url; + if (!download->silent) { http_print_transfer(download->window, download->id, - "Downloading '%s': 0%%", download->url); + "Downloading '%s': 0%%", display_url); } FILE* outfh = fopen(download->filename, "wb"); @@ -172,18 +178,18 @@ http_file_get(void* userdata) http_print_transfer_update(download->window, download->id, "Downloading '%s' failed: " "Download was canceled", - download->url); + display_url); } else { http_print_transfer_update(download->window, download->id, "Downloading '%s' failed: %s", - download->url, err); + display_url, err); } free(err); } else { - if (!download->cancel && !silent) { + if (!download->cancel && !download->silent && !download->silent_done) { http_print_transfer_update(download->window, download->id, "Downloading '%s': done\nSaved to '%s'", - download->url, download->filename); + display_url, download->filename); win_mark_received(download->window, download->id); if (download->return_bytes_received) { ret = malloc(sizeof(*ret)); @@ -204,7 +210,7 @@ http_file_get(void* userdata) http_print_transfer_update(download->window, download->id, "Downloading '%s' failed: Unable to call " "command '%s' with file at '%s' (%s).", - download->url, + display_url, download->cmd_template, download->filename, "TODO: Log the error"); @@ -221,6 +227,7 @@ out: free(download->filename); free(download->url); + free(download->display_url); free(download->id); free(download); diff --git a/src/tools/http_download.h b/src/tools/http_download.h index 4b7a40e7..c020e864 100644 --- a/src/tools/http_download.h +++ b/src/tools/http_download.h @@ -25,6 +25,7 @@ typedef struct http_download_t { char* id; char* url; + char* display_url; char* filename; char* cmd_template; curl_off_t bytes_received; @@ -32,6 +33,7 @@ typedef struct http_download_t pthread_t worker; int cancel; gboolean silent; + gboolean silent_done; gboolean return_bytes_received; } HTTPDownload; diff --git a/src/tools/http_upload.c b/src/tools/http_upload.c index 6162034f..919c7d87 100644 --- a/src/tools/http_upload.c +++ b/src/tools/http_upload.c @@ -65,7 +65,13 @@ _xferinfo(void* userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultot ulperc = (100 * ulnow) / ultotal; } - gchar* msg = g_strdup_printf("Uploading '%s': %d%%", upload->filename, ulperc); + gchar* msg = NULL; + if (ulnow == ultotal && ultotal > 0) { + msg = g_strdup_printf("Uploading '%s': done", upload->filename); + } else { + msg = g_strdup_printf("Uploading '%s': %d%%", upload->filename, ulperc); + } + if (!msg) { msg = g_strdup(FALLBACK_MSG); } @@ -288,7 +294,7 @@ http_file_put(void* userdata) cons_show_error(err_msg); } else { if (!upload->cancel) { - auto_gchar gchar* status_msg = g_strdup_printf("Uploading '%s': 100%%", upload->filename); + auto_gchar gchar* status_msg = g_strdup_printf("Uploading '%s': done", upload->filename); if (!status_msg) { status_msg = g_strdup(FALLBACK_MSG); }