From d6d6ac86aa3a3a89a0ed1c28f6f64308a1eca182 Mon Sep 17 00:00:00 2001 From: Daniel Carl Date: Sun, 9 Mar 2014 00:19:46 +0100 Subject: [PATCH] Added shell expansion for download paths. --- doc/vimb.1 | 8 +++--- src/main.c | 17 +++++++++--- src/setting.c | 9 ++++--- src/util.c | 72 ++++++++++++++++++++++++++++++++++++++------------- src/util.h | 1 + 5 files changed, 78 insertions(+), 29 deletions(-) diff --git a/doc/vimb.1 b/doc/vimb.1 index bfce546..28e3876 100644 --- a/doc/vimb.1 +++ b/doc/vimb.1 @@ -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 diff --git a/src/main.c b/src/main.c index 56bf382..5f26aff 100644 --- a/src/main.c +++ b/src/main.c @@ -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 */ diff --git a/src/setting.c b/src/setting.c index 8d267cf..0e727e6 100644 --- a/src/setting.c +++ b/src/setting.c @@ -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); diff --git a/src/util.c b/src/util.c index c368991..9456de7 100644 --- a/src/util.c +++ b/src/util.c @@ -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; +} diff --git a/src/util.h b/src/util.h index f85faa8..657f741 100644 --- a/src/util.h +++ b/src/util.h @@ -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 */ -- 2.20.1