Added :save command.
authorDaniel Carl <danielcarl@gmx.de>
Thu, 20 Apr 2017 20:45:31 +0000 (22:45 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Thu, 20 Apr 2017 20:45:31 +0000 (22:45 +0200)
src/command.c
src/main.c
src/main.h
src/util.c
src/util.h

index 7fbc878..4913ddc 100644 (file)
@@ -143,8 +143,8 @@ gboolean command_yank(Client *c, const Arg *arg, char buf)
 
 gboolean command_save(Client *c, const Arg *arg)
 {
-#if 0
     const char *uri, *path = NULL;
+    WebKitDownload *download;
 
     if (arg->i == COMMAND_SAVE_CURRENT) {
         uri = c->state.uri;
@@ -159,10 +159,11 @@ gboolean command_save(Client *c, const Arg *arg)
     if (!uri || !*uri) {
         return FALSE;
     }
-#endif
 
-    /* TODO start the download to given path here */
-    return TRUE;
+    /* Start the download to given path. */
+    download = webkit_web_view_download_uri(c->webview, uri);
+
+    return vb_download_set_destination(c, download, NULL, path);
 }
 
 #ifdef FEATURE_QUEUE
index 67e3486..7b0f4ba 100644 (file)
@@ -97,6 +97,86 @@ static void on_script_message_focus(WebKitUserContentManager *manager,
 
 struct Vimb vb;
 
+/**
+ * Set the destination for a download according to suggested file name and
+ * possible given path.
+ */
+gboolean vb_download_set_destination(Client *c, WebKitDownload *download,
+    char *suggested_filename, const char *path)
+{
+    char *download_path, *dir, *file, *uri;
+    download_path = GET_CHAR(c, "download-path");
+
+    /* For unnamed downloads set default filename. */
+    if (!suggested_filename || !*suggested_filename) {
+        suggested_filename = "vimb-download";
+    }
+
+    /* Prepare the path to save the download. */
+    if (path && *path) {
+        file = util_build_path(c, path, download_path);
+
+        /* if file is an directory append a file name */
+        if (g_file_test(file, (G_FILE_TEST_IS_DIR))) {
+            dir  = file;
+            file = g_build_filename(dir, suggested_filename, NULL);
+            g_free(dir);
+        }
+    } else {
+        file = util_build_path(c, suggested_filename, download_path);
+    }
+
+    /* If the filepath exists already insert numerical suffix before file
+     * extension. */
+    if (g_file_test(file, G_FILE_TEST_EXISTS)) {
+        const char *dot_pos;
+        char *num = NULL;
+        GString *tmp;
+        gssize suffix;
+        int i = 1;
+        suffix = 2;
+
+        /* position on .tar. (special case, extension with two dots),
+         * position on last dot (if any) otherwise */
+        if (!(dot_pos = strstr(file, ".tar."))) {
+            dot_pos = strrchr(file, '.');
+        }
+
+        /* the position to insert the suffix at */
+        if (dot_pos) {
+            suffix = dot_pos - file;
+        } else {
+            suffix = strlen(file);
+        }
+
+        tmp = g_string_new(NULL);
+        num = g_strdup_printf("%d", i++);
+
+        /* Construct a new complete odwnload filepath with suffic before the
+         * file extension. */
+        do {
+            num = g_strdup_printf("%d", i++);
+            g_string_assign(tmp, file);
+            g_string_insert(tmp, suffix, num);
+            g_free(num);
+        } while (g_file_test(tmp->str, G_FILE_TEST_EXISTS));
+
+        file = g_strdup(tmp->str);
+        g_string_free(tmp, TRUE);
+    }
+
+    /* Build URI from filepath. */
+    uri = g_filename_to_uri(file, NULL, NULL);
+    g_free(file);
+
+    /* configure download */
+    g_assert(uri);
+    webkit_download_set_allow_overwrite(download, FALSE);
+    webkit_download_set_destination(download, uri);
+    g_free(uri);
+
+    return TRUE;
+}
 
 /**
  * Write text to the inpubox if this isn't focused.
@@ -822,75 +902,11 @@ static void on_webctx_init_web_extension(WebKitWebContext *webctx, gpointer data
 static gboolean on_webdownload_decide_destination(WebKitDownload *download,
         gchar *suggested_filename, Client *c)
 {
-    g_assert(download);
-    g_assert(suggested_filename);
-    g_assert(c);
-
-    char *path, *filename, *uri;
-    GString *expanded, *filepath;
-    const char *extension_dot;
-    int suffix;
-    gssize suffix_pos;
-
-    /* get the download path from settings */
-    path = GET_CHAR(c, "download-path");
-    g_assert(path);
-
-    /* expand any ~ or $VAR patterns in download path */
-    expanded = g_string_new(NULL);
-    util_parse_expansion(c, (const char**)&path, expanded, UTIL_EXP_TILDE|UTIL_EXP_DOLLAR, "");
-    g_string_append(expanded, path + 1);
-
-    /* for unnamed downloads set default filename */
-    filename = strlen(suggested_filename) ? suggested_filename : "vimb-download";
-
-    /* construct complete download filepath */
-    filepath = g_string_new(NULL);
-    g_string_printf(filepath, "%s%c%s", expanded->str, G_DIR_SEPARATOR, filename);
-
-    /* if the filepath exists already
-     * insert numerical suffix before file extension */
-    if (g_file_test(filepath->str, G_FILE_TEST_EXISTS)) {
-        suffix = 2;
-
-        /* position on .tar. (special case, extension with two dots),
-         * position on last dot (if any) otherwise */
-        if (!(extension_dot = strstr(filename, ".tar."))) {
-            extension_dot = strrchr(filename, '.');
-        }
-
-        /* the position to insert the suffix at */
-        if (extension_dot) {
-            suffix_pos = extension_dot - filename;
-        } else {
-            suffix_pos = strlen(filename);
-        }
-
-        /* construct a new complete download filepath and add the suffix before
-         * the filename extension, keep incrementing the suffix value as long
-         * as the filepath exists, stop on first unused filename. */
-        do {
-            g_string_printf(filepath, "%s%c%.*s_%i%s",
-                    expanded->str, G_DIR_SEPARATOR,
-                    (int)suffix_pos, filename,
-                    suffix++, filename + suffix_pos);
-        } while (g_file_test(filepath->str, G_FILE_TEST_EXISTS));
+    if (webkit_download_get_destination(download)) {
+        return TRUE;
     }
 
-    /* build URI from filepath */
-    uri = g_filename_to_uri(filepath->str, NULL, NULL);
-    g_assert(uri);
-
-    /* configure download */
-    webkit_download_set_allow_overwrite(download, FALSE);
-    webkit_download_set_destination(download, uri);
-
-    /* cleanup */
-    g_string_free(expanded, TRUE);
-    g_string_free(filepath, TRUE);
-    g_free(uri);
-
-    return TRUE;
+    return vb_download_set_destination(c, download, suggested_filename, NULL);
 }
 
 /**
index 9d016a5..e4b969d 100644 (file)
@@ -263,7 +263,8 @@ struct Vimb {
     GtkCssProvider *style_provider;
 };
 
-
+gboolean vb_download_set_destination(Client *c, WebKitDownload *download,
+    char *suggested_filename, const char *path);
 void vb_echo(Client *c, MessageType type, gboolean hide, const char *error, ...);
 void vb_echo_force(Client *c, MessageType type, gboolean hide, const char *error, ...);
 void vb_enter(Client *c, char id);
index 3430a58..b392876 100644 (file)
@@ -36,6 +36,48 @@ static struct {
 
 static void create_dir_if_not_exists(const char *dirpath);
 
+/**
+ * Build the absolute file path of given path and possible given directory.
+ *
+ * Returned path must be freed.
+ */
+char *util_build_path(Client *c, const char *path, const char *dir)
+{
+    char *fullPath = NULL, *fexp, *dexp, *p;
+    int expflags   = UTIL_EXP_TILDE|UTIL_EXP_DOLLAR;
+
+    /* if the path could be expanded */
+    if ((fexp = util_expand(c, path, expflags))) {
+        if (*fexp == '/') {
+            /* path is already absolute, no need to use given dir - there is
+             * no need to free fexp, bacuse this should be done by the caller
+             * on fullPath later */
+            fullPath = fexp;
+        } else if (dir && *dir) {
+            /* try to expand also the dir given - this may be ~/path */
+            if ((dexp = util_expand(c, dir, expflags))) {
+                /* use expanded dir and append expanded path */
+                fullPath = g_build_filename(dexp, fexp, NULL);
+                g_free(dexp);
+            }
+            g_free(fexp);
+        }
+    }
+
+    /* if full path not found use current dir */
+    if (!fullPath) {
+        fullPath = g_build_filename(g_get_current_dir(), path, NULL);
+    }
+
+    /* Create the directory part of the path if it does not exists. */
+    if ((p = strrchr(fullPath, '/'))) {
+        *p = '\0';
+        util_create_dir_if_not_exists(fullPath);
+        *p = '/';
+    }
+
+    return fullPath;
+}
 
 /**
  * Free memory for allocated path strings.
@@ -47,6 +89,13 @@ void util_cleanup(void)
     }
 }
 
+void util_create_dir_if_not_exists(const char *dirpath)
+{
+    if (!g_file_test(dirpath, G_FILE_TEST_IS_DIR)) {
+        g_mkdir_with_parents(dirpath, 0755);
+    }
+}
+
 /**
  * Expand ~user, ~/, $ENV and ${ENV} for given string into new allocated
  * string.
index a9fd042..63f5046 100644 (file)
@@ -30,7 +30,9 @@ enum {
 };
 typedef void *(*Util_Content_Func)(const char*, const char*);
 
+char *util_build_path(Client *c, const char *path, const char *dir);
 void util_cleanup(void);
+void util_create_dir_if_not_exists(const char *dirpath);
 char *util_expand(Client *c, const char *src, int expflags);
 gboolean util_file_append(const char *file, const char *format, ...);
 gboolean util_file_prepend(const char *file, const char *format, ...);