From: Daniel Carl Date: Thu, 20 Apr 2017 20:45:31 +0000 (+0200) Subject: Added :save command. X-Git-Url: https://git.owens.tech/assets/favicon.png/assets/favicon.png/git?a=commitdiff_plain;h=597a0acfd9e35f6516a6c5069fdf651416e9f11c;p=vimb.git Added :save command. --- diff --git a/src/command.c b/src/command.c index 7fbc878..4913ddc 100644 --- a/src/command.c +++ b/src/command.c @@ -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 diff --git a/src/main.c b/src/main.c index 67e3486..7b0f4ba 100644 --- a/src/main.c +++ b/src/main.c @@ -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); } /** diff --git a/src/main.h b/src/main.h index 9d016a5..e4b969d 100644 --- a/src/main.h +++ b/src/main.h @@ -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); diff --git a/src/util.c b/src/util.c index 3430a58..b392876 100644 --- a/src/util.c +++ b/src/util.c @@ -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. diff --git a/src/util.h b/src/util.h index a9fd042..63f5046 100644 --- a/src/util.h +++ b/src/util.h @@ -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, ...);