Added shell expansion for download paths.
authorDaniel Carl <danielcarl@gmx.de>
Sat, 8 Mar 2014 23:19:46 +0000 (00:19 +0100)
committerDaniel Carl <danielcarl@gmx.de>
Sat, 8 Mar 2014 23:19:46 +0000 (00:19 +0100)
doc/vimb.1
src/main.c
src/setting.c
src/util.c
src/util.h

index bfce546..28e3876 100644 (file)
@@ -519,9 +519,8 @@ Example: :sh! echo "`date` %" >> myhistory.txt
 .TP
 .BI ":s[ave] [" PATH "]"
 Download current opened page into configured download directory. If \fIPATH\fP
-is given, download under this file name or path. Possible value for PATH are
-`page.html', `subdir/img1.png', `~/downlod.html' or absolute paths
-`/tmp/file.html'.
+is given, download under this file name or path. \fIPATH\fP is expanded via
+shell and can therefor contain '~/', '${ENV}' and '~user' pattern.
 .B :q[uit]
 Close the browser.
 .TP
@@ -700,7 +699,8 @@ cookies)}.
 Cookie timeout in seconds.
 .TP
 .B download-path (string)
-Path to the default download directory.
+Path to the default download directory. Note that the set path is expanded via
+shell, so you can use '~/path' or '$HOME/foo'.
 .TP
 .B editor-command (string)
 Command with placeholder '%s' called if form filed is opened with editor to
index 56bf382..5f26aff 100644 (file)
@@ -936,17 +936,26 @@ static gboolean mimetype_decision_cb(WebKitWebView *webview,
 gboolean vb_download(WebKitWebView *view, WebKitDownload *download, const char *path)
 {
     WebKitDownloadStatus status;
-    char *uri, *file;
+    char *uri, *file, *dir;
 
-    /* prepare the path to save the donwload */
+    /* prepare the path to save the download */
     if (path) {
         file = util_build_path(path, vb.config.download_dir);
+
+        /* 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, PROJECT "-download", NULL);
+            g_free(dir);
+        }
     } else {
+        /* if there was no path given where to download the file, used
+         * suggested file name or a static one */
         path = webkit_download_get_suggested_filename(download);
         if (!path || *path == '\0') {
-            path = PROJECT "-donwload";
+            path = PROJECT "-download";
         }
-        file = util_build_path(path, vb.config.download_dir);
+        file = g_build_filename(vb.config.download_dir, path, NULL);
     }
 
     /* build the file uri from file path */
index 8d267cf..0e727e6 100644 (file)
@@ -663,6 +663,7 @@ static SettingStatus home_page(const Setting *s, const SettingType type)
 
 static SettingStatus download_path(const Setting *s, const SettingType type)
 {
+    char *path;
     if (type == SETTING_GET) {
         print_value(s, vb.config.download_dir);
     } else {
@@ -670,11 +671,13 @@ static SettingStatus download_path(const Setting *s, const SettingType type)
             g_free(vb.config.download_dir);
             vb.config.download_dir = NULL;
         }
+        path = util_shell_expand(s->arg.s);
         /* if path is not absolute create it in the home directory */
-        if (s->arg.s[0] != '/') {
-            vb.config.download_dir = g_build_filename(util_get_home_dir(), s->arg.s, NULL);
+        if (*path != G_DIR_SEPARATOR) {
+            vb.config.download_dir = g_build_filename(util_get_home_dir(), path, NULL);
+            g_free(path);
         } else {
-            vb.config.download_dir = g_strdup(s->arg.s);
+            vb.config.download_dir = path;
         }
         /* create the path if it does not exist */
         util_create_dir_if_not_exists(vb.config.download_dir);
index c368991..9456de7 100644 (file)
@@ -292,35 +292,71 @@ gboolean util_create_tmp_file(const char *content, char **file)
 
 /**
  * Build the absolute file path of given path and possible given directory.
- * If the path is already absolute or uses ~/ for the home directory, the
- * directory is ignored.
  *
  * Returned path must be freed.
  */
 char *util_build_path(const char *path, const char *dir)
 {
-    char *fullPath, *p;
-
-    /* creating directory */
-    if (path[0] == '/') {
-        fullPath = g_strdup(path);
-    } else if (path[0] == '~') {
-        if (path[1] == '/') {
-            fullPath = g_strconcat(g_get_home_dir(), &path[1], NULL);
-        } else {
-            fullPath = g_strconcat(g_get_home_dir(), "/", &path[1], NULL);
+    char *fullPath = NULL, *fexp, *dexp, *p;
+
+    /* if the path could be expanded */
+    if ((fexp = util_shell_expand(path))) {
+        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) {
+            /* try to expand also the dir given - this may be ~/path */
+            if ((dexp = util_shell_expand(dir))) {
+                /* use expanded dir and append expanded path */
+                fullPath = g_build_filename(dexp, fexp, NULL);
+                g_free(dexp);
+            }
+            g_free(fexp);
         }
-    } else if (dir) {
-        fullPath = g_strconcat(dir, "/", path, NULL);
-    } else {
-        fullPath = g_strconcat(g_get_current_dir(), "/", path, NULL);
     }
 
-    if ((p = strrchr(fullPath, '/'))) {
+    /* if full path not found use current dir */
+    if (!fullPath) {
+        fullPath = g_build_filename(g_get_current_dir(), path, NULL);
+    }
+
+    if ((p = strrchr(fullPath, G_DIR_SEPARATOR))) {
         *p = '\0';
-        g_mkdir_with_parents(fullPath, 0700);
+        util_create_dir_if_not_exists(fullPath);
         *p = '/';
     }
 
     return fullPath;
 }
+
+/**
+ * Run the shell to expand given string 'echo -n str'.
+ *
+ * Returned path must be g_freed.
+ */
+char *util_shell_expand(const char *str)
+{
+    GError *error = NULL;
+    char *shellcmd, *cmd, *out = NULL;
+
+    /* first check if the string may contain expandable chars */
+    if (*str == '~' || strchr(str, '$')) {
+        cmd      = g_strconcat("echo -n ", str, NULL);
+        shellcmd = g_strdup_printf(SHELL_CMD, cmd);
+        if (!g_spawn_command_line_sync(shellcmd, &out, NULL, NULL, &error)) {
+            g_warning("Could not run shell expansion: %s", error->message);
+            g_clear_error(&error);
+        }
+        g_free(shellcmd);
+        g_free(cmd);
+    }
+
+    /* if string needn't to be expanded or expansion fialed use it like it is */
+    if (!out) {
+        out = g_strdup(str);
+    }
+
+    return out;
+}
index f85faa8..657f741 100644 (file)
@@ -40,5 +40,6 @@ char* util_strcasestr(const char* haystack, const char* needle);
 char *util_str_replace(const char* search, const char* replace, const char* string);
 gboolean util_create_tmp_file(const char *content, char **file);
 char *util_build_path(const char *path, const char *dir);
+char *util_shell_expand(const char *str);
 
 #endif /* end of include guard: _UTIL_H */