## [Unreleased]
### Added
+* `:cleardata [timeSpan] [listOfDataTypes]` command to clear various types of
+ stored website data modified in the last _timeSpan_.
### Changed
### Fixed
### Removed
+* `:clearcache` was removed in favor of more advanced `:cleardata` command.
+ The previous behaviour of `:clearcache` could be replaces by
+ `:cleardata - memory-cache,disk-cache`.
## [3.5.0] - 2019-07-29
### Added
.EE
.SS Misc
.TP
-.B :cl[earcache]
-Clears all resources currently cached by webkit.
+.BI ":cl[eardata] [" timespan "] [" dataTypes "]"
+Asynchronously clears the website data of the given list of\fIdataTypes\fP
+modified in the past \fItimespan\fP.
+If \fItimespan\fP is 0, all website data will be removed.
Note that this effects all running instances of vimb.
+.RS
+.PP
+.PD 0
+The \fItimespan\fP is given as sequence of '[multiplier]\fIunit\fP' tupels.
+with following units.
+.TP
+.B y
+year (365 days)
+.TP
+.B w
+week (7 days)
+.TP
+.B d
+day
+.TP
+.B h
+hour
+.TP
+.B m
+minute
+.TP
+.B s
+second
+.TP
+.B -
+can be used to clear data without timespan restriction
+.PD
+.RE
+.RS
+.PP
+.PD 0
+The \fIdataTypes\fP is a comma separated list of following types.
+.TP
+.B memory-cache
+Memory cache.
+.TP
+.B disk-cache
+HTTP disk cache.
+.TP
+.B offline-cache
+Offline web application cache.
+.TP
+.B session-storage
+Session storage data.
+.TP
+.B local-storage
+Local storage data.
+.TP
+.B indexeddb-databases
+IndexedDB databases.
+.TP
+.B plugin-data
+Plugin data.
+.TP
+.B cookies
+Cookies. Note that the cookies are not cleared in case a \fItimespan\fP is
+given.
+.TP
+.B hsts-cache
+HTTP Strict Transport Security cache.
+.sp
+.PP
+.I Example:
+.PD 0
+.IP ":cleardata"
+to clear all known website data types without any timespan restriction.
+.IP ":cleardata - local-storage,session-storage,cookies"
+to completely clear the cookies, local- and session-storage without time
+restrictions.
+.IP ":cleardata 2d4h disk-cache"
+to clear the disk cache that was modified in the past two days and four hours.
+.PD
+.RE
+.TP
+.BI ":sh[ellcmd]! " cmd
+Like :sh[ellcmd] but asynchronous.
+.sp
+Example:
+.EX
+:sh! /bin/sh -c 'echo "`date` $VIMB_URI" >> myhistory.txt'
+.EE
+.TP
.TP
.BI ":sh[ellcmd] " cmd
Runs the given shell \fIcmd\fP syncron and print the output into inputbox.
#include "util.h"
#include "ext-proxy.h"
#include "autocmd.h"
+#include "util.h"
typedef enum {
#ifdef FEATURE_AUTOCMD
EX_BMR,
EX_EVAL,
EX_HARDCOPY,
- EX_CLEARCACHE,
+ EX_CLEARDATA,
EX_CMAP,
EX_CNOREMAP,
EX_HANDADD,
static VbCmdResult ex_bookmark(Client *c, const ExArg *arg);
static VbCmdResult ex_eval(Client *c, const ExArg *arg);
static void on_eval_script_finished(GDBusProxy *proxy, GAsyncResult *result, Client *c);
-static VbCmdResult ex_clearcache(Client *c, const ExArg *arg);
+static VbCmdResult ex_cleardata(Client *c, const ExArg *arg);
static VbCmdResult ex_hardcopy(Client *c, const ExArg *arg);
static void print_failed_cb(WebKitPrintOperation* op, GError *err, Client *c);
static VbCmdResult ex_map(Client *c, const ExArg *arg);
{"cmap", EX_CMAP, ex_map, EX_FLAG_LHS|EX_FLAG_CMD},
{"cnoremap", EX_CNOREMAP, ex_map, EX_FLAG_LHS|EX_FLAG_CMD},
{"cunmap", EX_CUNMAP, ex_unmap, EX_FLAG_LHS},
- {"clearcache", EX_CLEARCACHE, ex_clearcache, EX_FLAG_NONE},
+ {"cleardata", EX_CLEARDATA, ex_cleardata, EX_FLAG_LHS|EX_FLAG_RHS},
{"hardcopy", EX_HARDCOPY, ex_hardcopy, EX_FLAG_NONE},
{"handler-add", EX_HANDADD, ex_handlers, EX_FLAG_RHS},
{"handler-remove", EX_HANDREM, ex_handlers, EX_FLAG_RHS},
}
}
-static VbCmdResult ex_clearcache(Client *c, const ExArg *arg)
+/**
+ * Clear website data by ':cleardata {time} {dataTypeList}'.
+ */
+static VbCmdResult ex_cleardata(Client *c, const ExArg *arg)
{
- webkit_web_context_clear_cache(webkit_web_context_get_default());
- return CMD_SUCCESS;
+ unsigned int data_types = 0;
+ WebKitWebsiteDataManager *manager;
+ VbCmdResult result = CMD_SUCCESS;
+ GTimeSpan timespan = 0;
+
+ if (arg->lhs->len) {
+ timespan = util_string_to_timespan(arg->lhs->str);
+ }
+ if (!arg->rhs->len) {
+ /* No special type given - clear all known types. */
+ data_types = WEBKIT_WEBSITE_DATA_ALL;
+ } else {
+ GString *str;
+ char **types;
+ char *value;
+ unsigned int len, i, t;
+ gboolean found;
+ static const Arg type_map[] = {
+ {WEBKIT_WEBSITE_DATA_MEMORY_CACHE, "memory-cache"},
+ {WEBKIT_WEBSITE_DATA_DISK_CACHE, "disk-cache"},
+ {WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE, "offline-cache"},
+ {WEBKIT_WEBSITE_DATA_SESSION_STORAGE, "session-storage"},
+ {WEBKIT_WEBSITE_DATA_LOCAL_STORAGE, "local-storage"},
+ {WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES, "indexeddb-databases"},
+ {WEBKIT_WEBSITE_DATA_PLUGIN_DATA, "plugin-data"},
+ {WEBKIT_WEBSITE_DATA_COOKIES, "cookies"},
+#if WEBKIT_CHECK_VERSION(2, 26, 0)
+ {WEBKIT_WEBSITE_DATA_HSTS_CACHE, "hsts-cache"},
+#endif
+ {0, ""},
+ };
+
+ /* Walk through list of data types given as rhs. */
+ types = g_strsplit(arg->rhs->str, ",", -1);
+ len = g_strv_length(types);
+ str = g_string_new(NULL);
+
+ /* Loop over given types and collect the type values into bitmap. */
+ for (i = 0; i < len; i++) {
+ value = types[i];
+ found = FALSE;
+ for (t = 0; type_map[t].i; t++) {
+ if (!strcmp(value, type_map[t].s)) {
+ data_types |= type_map[t].i;
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* collect unknown types to be shown in error message. */
+ g_string_append_printf(str, "%s ", value);
+ }
+ }
+ if (*str->str) {
+ vb_echo(c, MSG_ERROR, TRUE, "unknown data type(s): %s", str->str);
+ result = CMD_ERROR|CMD_KEEPINPUT;
+ }
+ g_string_free(str, TRUE);
+ g_strfreev(types);
+ }
+ manager = webkit_web_context_get_website_data_manager(webkit_web_view_get_context(c->webview));
+ webkit_website_data_manager_clear(manager, data_types, timespan, NULL, NULL, NULL);
+
+ return result;
}
/**
}
}
+/**
+ * Get the time span to given string like '1y5dh' (one year and five days and
+ * one hour).
+ */
+GTimeSpan util_string_to_timespan(const char *input)
+{
+ unsigned int multiplier = 0;
+ GTimeSpan sum = 0;
+ gboolean hasmultiplier = FALSE;
+
+ while (*input) {
+ if (VB_IS_DIGIT(*input)) {
+ multiplier = multiplier * 10 + (*input - '0');
+ /* Use separate variable to differentiate between no multiplier
+ * set (is same as 1) or ultiplier of '0'. */
+ hasmultiplier = TRUE;
+ } else {
+ GTimeSpan s = 0;
+ switch (*input) {
+ case 'y': s = 365 * G_TIME_SPAN_DAY; break;
+ case 'w': s = 7 * G_TIME_SPAN_DAY; break;
+ case 'd': s = G_TIME_SPAN_DAY; break;
+ case 'h': s = G_TIME_SPAN_HOUR; break;
+ case 'm': s = G_TIME_SPAN_MINUTE; break;
+ case 's': s = G_TIME_SPAN_SECOND; break;
+ }
+ sum += s * (hasmultiplier ? multiplier : 1);
+ /* Unset multiplier for th epossible next multiplier in input */
+ multiplier = 0;
+ hasmultiplier = FALSE;
+ }
+ input++;
+ }
+
+ return sum;
+}
char *util_str_replace(const char* search, const char* replace, const char* string);
char *util_strescape(const char *source, const char *exceptions);
gboolean util_wildmatch(const char *pattern, const char *subject);
+GTimeSpan util_string_to_timespan(const char *input);
#endif /* end of include guard: _UTIL_H */
}
}
+static void test_string_to_timespan(void)
+{
+ g_assert_cmpuint(util_string_to_timespan("d"), ==, G_TIME_SPAN_DAY);
+ g_assert_cmpuint(util_string_to_timespan("h"), ==, G_TIME_SPAN_HOUR);
+ g_assert_cmpuint(util_string_to_timespan("m"), ==, G_TIME_SPAN_MINUTE);
+ g_assert_cmpuint(util_string_to_timespan("s"), ==, G_TIME_SPAN_SECOND);
+
+ g_assert_cmpuint(util_string_to_timespan("y"), ==, G_TIME_SPAN_DAY * 365);
+ g_assert_cmpuint(util_string_to_timespan("w"), ==, G_TIME_SPAN_DAY * 7);
+
+ /* use counters */
+ g_assert_cmpuint(util_string_to_timespan("1s"), ==, G_TIME_SPAN_SECOND);
+ g_assert_cmpuint(util_string_to_timespan("2s"), ==, 2 * G_TIME_SPAN_SECOND);
+ g_assert_cmpuint(util_string_to_timespan("34s"), ==, 34 * G_TIME_SPAN_SECOND);
+ g_assert_cmpuint(util_string_to_timespan("0s"), ==, 0);
+
+ /* combine counters and different units */
+ g_assert_cmpuint(util_string_to_timespan("ds"), ==, G_TIME_SPAN_DAY + G_TIME_SPAN_SECOND);
+ g_assert_cmpuint(util_string_to_timespan("2dh0s"), ==, (2 * G_TIME_SPAN_DAY) + G_TIME_SPAN_HOUR);
+
+ /* unparsabel values */
+ g_assert_cmpuint(util_string_to_timespan(""), ==, 0);
+ g_assert_cmpuint(util_string_to_timespan("-"), ==, 0);
+ g_assert_cmpuint(util_string_to_timespan("5-"), ==, 0);
+}
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/test-util/wildmatch-complete", test_wildmatch_complete);
g_test_add_func("/test-util/wildmatch-multi", test_wildmatch_multi);
g_test_add_func("/test-util/strescape", test_strescape);
+ g_test_add_func("/test-util/string_to_timespan", test_string_to_timespan);
return g_test_run();
}