Add external download command (#65).
authorDaniel Carl <danielcarl@gmx.de>
Sun, 22 Jun 2014 14:50:38 +0000 (16:50 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Sun, 22 Jun 2014 14:50:38 +0000 (16:50 +0200)
src/main.c
src/main.h
src/setting.c

index 76847e8..9b23a14 100644 (file)
@@ -86,6 +86,9 @@ static void title_changed_cb(WebKitWebView *webview, WebKitWebFrame *frame, cons
 static gboolean mimetype_decision_cb(WebKitWebView *webview,
     WebKitWebFrame *frame, WebKitNetworkRequest *request, char*
     mime_type, WebKitWebPolicyDecision *decision);
+gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *path);
+void vb_download_internal(WebKitWebView *view, WebKitDownload *download, const char *file);
+void vb_download_external(WebKitWebView *view, WebKitDownload *download, const char *file);
 static void download_progress_cp(WebKitDownload *download, GParamSpec *pspec);
 
 /* functions */
@@ -1185,8 +1188,7 @@ static gboolean mimetype_decision_cb(WebKitWebView *webview,
 
 gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *path)
 {
-    WebKitDownloadStatus status;
-    char *uri, *file, *dir;
+    char *file, *dir;
 
     /* prepare the path to save the download */
     if (path) {
@@ -1208,17 +1210,38 @@ gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *
         file = util_build_path(path, vb.config.download_dir);
     }
 
+    if (vb.config.download_use_external && *vb.config.download_command) {
+        /* run download with external programm */
+        vb_download_external(view, download, file);
+        g_free(file);
+
+        /* signalize that we handle the download ourself */
+        return false;
+    } else {
+        /* use webkit download helpr to download the uri */
+        vb_download_internal(view, download, file);
+        g_free(file);
+
+        return true;
+    }
+}
+
+void vb_download_internal(WebKitWebView *view, WebKitDownload *download, const char *file)
+{
+    char *uri;
+    guint64 size;
+    WebKitDownloadStatus status;
+
     /* build the file uri from file path */
     uri = g_filename_to_uri(file, NULL, NULL);
     webkit_download_set_destination_uri(download, uri);
-    g_free(file);
     g_free(uri);
 
-    guint64 size = webkit_download_get_total_size(download);
+    size = webkit_download_get_total_size(download);
     if (size > 0) {
-        vb_echo(VB_MSG_NORMAL, false, "Download %s [~%uB] started ...", path, size);
+        vb_echo(VB_MSG_NORMAL, false, "Download %s [%uB] started ...", file, size);
     } else {
-        vb_echo(VB_MSG_NORMAL, false, "Download %s started ...", path);
+        vb_echo(VB_MSG_NORMAL, false, "Download %s started ...", file);
     }
 
     status = webkit_download_get_status(download);
@@ -1234,8 +1257,73 @@ gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *
     g_signal_connect(download, "notify::progress", G_CALLBACK(webview_download_progress_cb), NULL);
 
     vb_update_statusbar();
+}
 
-    return true;
+void vb_download_external(WebKitWebView *view, WebKitDownload *download, const char *file)
+{
+    const char *user_agent = NULL, *mimetype = NULL;
+    char **argv, **envp;
+    char *cmd;
+    int argc;
+    guint64 size;
+    SoupMessage *msg;
+    WebKitNetworkRequest *request;
+    GError *error = NULL;
+
+    request = webkit_download_get_network_request(download);
+    msg     = webkit_network_request_get_message(request);
+    /* if the download is started by the :save command or hinting we get no
+     * message here */
+    if (msg) {
+        user_agent = soup_message_headers_get_one(msg->request_headers, "User-Agent");
+        mimetype   = soup_message_headers_get_one(msg->request_headers, "Content-Type");
+    }
+
+    /* set the required download information as environment */
+    envp = g_get_environ();
+    envp = g_environ_setenv(envp, "VIMB_FILE", file, true);
+#ifdef FEATURE_COOKIE
+    envp = g_environ_setenv(envp, "VIMB_COOKIES", vb.files[FILES_COOKIE], true);
+#endif
+    if (mimetype) {
+        envp = g_environ_setenv(envp, "VIMB_MIME_TYPE", mimetype, true);
+    }
+
+    if (!user_agent) {
+        WebKitWebSettings *setting = webkit_web_view_get_settings(view);
+        g_object_get(G_OBJECT(setting), "user-agent", &user_agent, NULL);
+    }
+    envp = g_environ_setenv(envp, "VIMB_USER_AGENT", user_agent, true);
+
+    cmd  = g_strdup_printf(vb.config.download_command, webkit_download_get_uri(download));
+
+    if (!g_shell_parse_argv(cmd, &argc, &argv, &error)) {
+        g_warning(
+            "Could not parse download-command '%s': %s",
+            vb.config.download_command,
+            error->message
+        );
+        g_error_free(error);
+        g_free(cmd);
+
+        return;
+    }
+    g_free(cmd);
+
+    if (g_spawn_async(NULL, argv, envp, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error)) {
+        size = webkit_download_get_total_size(download);
+        if (size > 0) {
+            vb_echo(VB_MSG_NORMAL, true, "Download of %uB started", size);
+        } else {
+            vb_echo(VB_MSG_NORMAL, true, "Download started");
+        }
+    } else {
+        g_warning("%s", error->message);
+        g_clear_error(&error);
+        vb_echo(VB_MSG_ERROR, true, "Could not start download");
+    }
+    g_strfreev(argv);
+    g_strfreev(envp);
 }
 
 static void download_progress_cp(WebKitDownload *download, GParamSpec *pspec)
index 1107d16..9e0600e 100644 (file)
@@ -301,6 +301,8 @@ typedef struct {
     char         *download_dir;
     guint        history_max;
     char         *editor_command;
+    char         *download_command;
+    gboolean     download_use_external;
     guint        timeoutlen;      /* timeout for ambiguous mappings */
     gboolean     strict_focus;
     GHashTable   *headers;        /* holds user defined header appended to requests */
index 38c6643..b435786 100644 (file)
@@ -54,6 +54,8 @@ static SettingStatus proxy(const Setting *s, const SettingType type);
 static SettingStatus user_style(const Setting *s, const SettingType type);
 static SettingStatus history_max_items(const Setting *s, const SettingType type);
 static SettingStatus editor_command(const Setting *s, const SettingType type);
+static SettingStatus download_command(const Setting *s, const SettingType type);
+static SettingStatus download_use_external(const Setting *s, const SettingType type);
 static SettingStatus timeoutlen(const Setting *s, const SettingType type);
 static SettingStatus headers(const Setting *s, const SettingType type);
 static SettingStatus nextpattern(const Setting *s, const SettingType type);
@@ -130,6 +132,8 @@ static Setting default_settings[] = {
     {NULL, "download-path", TYPE_CHAR, download_path, {.s = ""}},
     {NULL, "history-max-items", TYPE_INTEGER, history_max_items, {.i = 2000}},
     {NULL, "editor-command", TYPE_CHAR, editor_command, {.s = "x-terminal-emulator -e vi %s"}},
+    {NULL, "download-command", TYPE_CHAR, download_command, {.s = "/bin/sh -c \"curl -sLJOC - -A '$VIMB_USER_AGENT' -e '$VIMB_URI' -b '$VIMB_COOKIES' %s\""}},
+    {NULL, "download-use-external", TYPE_BOOLEAN, download_use_external, {.i = 0}},
     {NULL, "header", TYPE_CHAR, headers, {.s = ""}},
     {NULL, "nextpattern", TYPE_CHAR, nextpattern, {.s = "/\\bnext\\b/i,/^(>\\|>>\\|»)$/,/^(>\\|>>\\|»)/,/(>\\|>>\\|»)$/,/\\bmore\\b/i"}},
     {NULL, "previouspattern", TYPE_CHAR, nextpattern, {.s = "/\\bprev\\|previous\\b/i,/^(<\\|<<\\|«)$/,/^(<\\|<<\\|«)/,/(<\\|<<\\|«)$/"}},
@@ -823,6 +827,35 @@ static SettingStatus editor_command(const Setting *s, const SettingType type)
     return SETTING_OK;
 }
 
+static SettingStatus download_command(const Setting *s, const SettingType type)
+{
+    if (type == SETTING_GET) {
+        print_value(s, vb.config.download_command);
+
+        return SETTING_OK;
+    }
+
+    OVERWRITE_STRING(vb.config.download_command, s->arg.s);
+
+    return SETTING_OK;
+}
+
+static SettingStatus download_use_external(const Setting *s, const SettingType type)
+{
+    if (type != SETTING_SET) {
+        if (type == SETTING_TOGGLE) {
+            vb.config.download_use_external = !vb.config.download_use_external;
+        }
+        print_value(s, &vb.config.download_use_external);
+
+        return SETTING_OK;
+    }
+
+    vb.config.download_use_external = s->arg.i ? true : false;
+
+    return SETTING_OK;
+}
+
 static SettingStatus timeoutlen(const Setting *s, const SettingType type)
 {
     if (type == SETTING_GET) {