about summary refs log tree commit diff stats
path: root/src/tools
diff options
context:
space:
mode:
authorWilliam Wennerström <william@wstrm.dev>2020-07-02 22:04:21 +0200
committerWilliam Wennerström <william@wstrm.dev>2020-11-16 21:58:09 +0100
commit9499df65859abd1404d3f9e96b8af859d3315bff (patch)
tree3af8a29c089cd79df9e8581e18c4f94a91a07975 /src/tools
parent362c6973de1182554d33936403794d9aa5efe093 (diff)
downloadprofani-tty-9499df65859abd1404d3f9e96b8af859d3315bff.tar.gz
Add http_download tool
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/http_download.c223
-rw-r--r--src/tools/http_download.h63
-rw-r--r--src/tools/http_upload.c2
3 files changed, 287 insertions, 1 deletions
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);