about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/command/cmd_funcs.c7
-rw-r--r--src/tools/http_download.c223
-rw-r--r--src/tools/http_download.h63
-rw-r--r--src/tools/http_upload.c2
-rw-r--r--src/ui/window.c2
-rw-r--r--src/ui/window.h2
6 files changed, 293 insertions, 6 deletions
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 <boothj5@gmail.com>
+ * Copyright (C) 2020 William Wennerström <william@wstrm.dev>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <curl/curl.h>
+#include <gio/gio.h>
+#include <pthread.h>
+#include <assert.h>
+
+#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 <boothj5@gmail.com>
+ * Copyright (C) 2020 William Wennerström <william@wstrm.dev>
+ *
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ * 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 <sys/select.h>
+#include <curl/curl.h>
+
+#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);