From 9499df65859abd1404d3f9e96b8af859d3315bff Mon Sep 17 00:00:00 2001 From: William Wennerström Date: Thu, 2 Jul 2020 22:04:21 +0200 Subject: Add http_download tool --- src/command/cmd_funcs.c | 7 +- src/tools/http_download.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++ src/tools/http_download.h | 63 +++++++++++++ src/tools/http_upload.c | 2 +- src/ui/window.c | 2 +- src/ui/window.h | 2 +- 6 files changed, 293 insertions(+), 6 deletions(-) create mode 100644 src/tools/http_download.c create mode 100644 src/tools/http_download.h diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 55bef3d1..7d921ea3 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -9114,8 +9114,8 @@ cmd_url_open(ProfWin* window, const char* const command, gchar** args) 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")) { + gchar *scheme = g_uri_parse_scheme(args[1]); + if( 0 == g_strcmp0(scheme, OMEMO_AESGCM_URL_SCHEME)) { require_save = true; } g_free(scheme); @@ -9221,7 +9221,8 @@ cmd_url_save(ProfWin* window, const char* const command, gchar** args) if (0 == g_strcmp0(scheme, "http") || 0 == g_strcmp0(scheme, "https") - || 0 == g_strcmp0(scheme, "aesgcm")) { + || 0 == g_strcmp0(scheme, OMEMO_AESGCM_URL_SCHEME) + ) { scheme_cmd = prefs_get_string_with_option(PREF_URL_SAVE_CMD, scheme); } diff --git a/src/tools/http_download.c b/src/tools/http_download.c new file mode 100644 index 00000000..80916385 --- /dev/null +++ b/src/tools/http_download.c @@ -0,0 +1,223 @@ +/* + * http_download.c + * vim: expandtab:ts=4:sts=4:sw=4 + * + * Copyright (C) 2012 - 2019 James Booth + * Copyright (C) 2020 William Wennerström + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see . + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#define _GNU_SOURCE 1 + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "profanity.h" +#include "event/client_events.h" +#include "tools/http_download.h" +#include "config/preferences.h" +#include "ui/ui.h" +#include "ui/window.h" +#include "common.h" + +#define FALLBACK_MSG "" + +GSList *download_processes = NULL; + +static int +_xferinfo(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + HTTPDownload *download = (HTTPDownload *)userdata; + + pthread_mutex_lock(&lock); + + if (download->cancel) { + pthread_mutex_unlock(&lock); + return 1; + } + + if (download->bytes_received == dlnow) { + pthread_mutex_unlock(&lock); + return 0; + } else { + download->bytes_received = dlnow; + } + + unsigned int dlperc = 0; + if (dltotal != 0) { + dlperc = (100 * dlnow) / dltotal; + } + + char *msg; + if (asprintf(&msg, "Downloading '%s': %d%%", download->url, dlperc) == -1) { + msg = strdup(FALLBACK_MSG); + } + win_update_entry_message(download->window, download->url, msg); + free(msg); + + pthread_mutex_unlock(&lock); + + return 0; +} + +#if LIBCURL_VERSION_NUM < 0x072000 +static int +_older_progress(void *p, double dltotal, double dlnow, double ultotal, double ulnow) +{ + return _xferinfo(p, (curl_off_t)dltotal, (curl_off_t)dlnow, (curl_off_t)ultotal, (curl_off_t)ulnow); +} +#endif + +void * +http_file_get(void *userdata) +{ + HTTPDownload *download = (HTTPDownload *)userdata; + + FILE *fh = NULL; + + char *err = NULL; + + CURL *curl; + CURLcode res; + + download->cancel = 0; + download->bytes_received = 0; + + pthread_mutex_lock(&lock); + char* msg; + if (asprintf(&msg, "Downloading '%s': 0%%", download->url) == -1) { + msg = strdup(FALLBACK_MSG); + } + win_print_http_transfer(download->window, msg, download->url); + free(msg); + + char *cert_path = prefs_get_string(PREF_TLS_CERTPATH); + pthread_mutex_unlock(&lock); + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + curl_easy_setopt(curl, CURLOPT_URL, download->url); + + #if LIBCURL_VERSION_NUM >= 0x072000 + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, _xferinfo); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, download); + #else + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, _older_progress); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, download); + #endif + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + + fh = download->filehandle; + + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&fh); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "profanity"); + + if (cert_path) { + curl_easy_setopt(curl, CURLOPT_CAPATH, cert_path); + } + + if ((res = curl_easy_perform(curl)) != CURLE_OK) { + err = strdup(curl_easy_strerror(res)); + } + + curl_easy_cleanup(curl); + curl_global_cleanup(); + + if (fh) { + fclose(fh); + } + + pthread_mutex_lock(&lock); + g_free(cert_path); + + if (err) { + char *msg; + if (download->cancel) { + if (asprintf(&msg, "Downloading '%s' failed: Download was canceled", download->url) == -1) { + msg = strdup(FALLBACK_MSG); + } + } else { + if (asprintf(&msg, "Downloading '%s' failed: %s", download->url, err) == -1) { + msg = strdup(FALLBACK_MSG); + } + win_update_entry_message(download->window, download->url, msg); + } + cons_show_error(msg); + free(msg); + free(err); + } else { + if (!download->cancel) { + if (asprintf(&msg, "Downloading '%s': 100%%", download->url) == -1) { + msg = strdup(FALLBACK_MSG); + } + win_update_entry_message(download->window, download->url, msg); + win_mark_received(download->window, download->put_url); + free(msg); + } + } + + download_processes = g_slist_remove(download_processes, download); + pthread_mutex_unlock(&lock); + + free(download->url); + free(download); + + return NULL; +} + +void +http_download_cancel_processes(ProfWin *window) +{ + GSList *download_process = download_processes; + while (download_process) { + HTTPDownload *download = download_process->data; + if (download->window == window) { + download->cancel = 1; + break; + } + download_process = g_slist_next(download_process); + } +} + +void +http_download_add_download(HTTPDownload *download) +{ + download_processes = g_slist_append(download_processes, download); +} diff --git a/src/tools/http_download.h b/src/tools/http_download.h new file mode 100644 index 00000000..7348b77c --- /dev/null +++ b/src/tools/http_download.h @@ -0,0 +1,63 @@ +/* + * http_download.h + * vim: expandtab:ts=4:sts=4:sw=4 + * + * Copyright (C) 2012 - 2019 James Booth + * Copyright (C) 2020 William Wennerström + * + * This file is part of Profanity. + * + * Profanity is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Profanity is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Profanity. If not, see . + * + * In addition, as a special exception, the copyright holders give permission to + * link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. + * + * You must obey the GNU General Public License in all respects for all of the + * code used other than OpenSSL. If you modify file(s) with this exception, you + * may extend this exception to your version of the file(s), but you are not + * obligated to do so. If you do not wish to do so, delete this exception + * statement from your version. If you delete this exception statement from all + * source files in the program, then also delete it here. + * + */ + +#ifndef TOOLS_HTTP_DOWNLOAD_H +#define TOOLS_HTTP_DOWNLOAD_H + +#ifdef PLATFORM_CYGWIN +#define SOCKET int +#endif + +#include +#include + +#include "ui/win_types.h" + +typedef struct http_download_t { + char *url; + FILE *filehandle; + curl_off_t bytes_received; + ProfWin *window; + pthread_t worker; + int cancel; +} HTTPDownload; + +void* http_file_get(void *userdata); + +void http_download_cancel_processes(ProfWin *window); +void http_download_add_download(HTTPDownload *download); + +#endif diff --git a/src/tools/http_upload.c b/src/tools/http_upload.c index 8d369f8a..2fb32062 100644 --- a/src/tools/http_upload.c +++ b/src/tools/http_upload.c @@ -176,7 +176,7 @@ http_file_put(void *userdata) if (asprintf(&msg, "Uploading '%s': 0%%", upload->filename) == -1) { msg = strdup(FALLBACK_MSG); } - win_print_http_upload(upload->window, msg, upload->put_url); + win_print_http_transfer(upload->window, msg, upload->put_url); free(msg); char* cert_path = prefs_get_string(PREF_TLS_CERTPATH); diff --git a/src/ui/window.c b/src/ui/window.c index 687af3b2..c03b3aab 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1390,7 +1390,7 @@ win_appendln_highlight(ProfWin* window, theme_item_t theme_item, const char* con } void -win_print_http_upload(ProfWin* window, const char* const message, char* url) +win_print_http_transfer(ProfWin *window, const char *const message, char *url) { win_print_outgoing_with_receipt(window, "!", NULL, message, url, NULL); } diff --git a/src/ui/window.h b/src/ui/window.h index c731d19b..86d1dbfd 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -72,7 +72,7 @@ void win_println_incoming_muc_msg(ProfWin* window, char* show_char, int flags, c void win_print_outgoing_muc_msg(ProfWin* window, char* show_char, const char* const me, const char* const id, const char* const replace_id, const char* const message); void win_print_history(ProfWin* window, const ProfMessage* const message); -void win_print_http_upload(ProfWin* window, const char* const message, char* url); +void win_print_http_transfer(ProfWin *window, const char *const message, char *url); void win_newline(ProfWin* window); void win_redraw(ProfWin* window); -- cgit 1.4.1-2-gfad0