diff --git a/src/cookies/cookies.c b/src/cookies/cookies.c index 3b29cd355..993437d1f 100644 --- a/src/cookies/cookies.c +++ b/src/cookies/cookies.c @@ -454,13 +454,14 @@ set_cookie(struct uri *uri, unsigned char *str) cookie->secure = (parse_header_param(str, "secure", NULL, 0) == HEADER_PARAM_FOUND); - + cookie->httponly = (parse_header_param(str, "httponly", NULL, 0) + == HEADER_PARAM_FOUND); #ifdef DEBUG_COOKIES { DBG("Got cookie %s = %s from %s, domain %s, " - "expires at %"TIME_PRINT_FORMAT", secure %d", cookie->name, + "expires at %"TIME_PRINT_FORMAT", secure %d, httponly %d", cookie->name, cookie->value, cookie->server->host, cookie->domain, - (time_print_T) cookie->expires, cookie->secure); + (time_print_T) cookie->expires, cookie->secure, cookie->httponly); } #endif @@ -618,8 +619,8 @@ is_path_prefix(unsigned char *d, unsigned char *s) } -struct string * -send_cookies(struct uri *uri) +static struct string * +send_cookies_common(struct uri *uri, unsigned int httponly) { struct c_domain *cd; struct cookie *c, *next; @@ -661,6 +662,9 @@ send_cookies(struct uri *uri) if (c->secure && uri->protocol != PROTOCOL_HTTPS) continue; + if (c->httponly && httponly) + continue; + if (header.length) add_to_string(&header, "; "); @@ -682,6 +686,18 @@ send_cookies(struct uri *uri) return &header; } +struct string * +send_cookies(struct uri *uri) +{ + return send_cookies_common(uri, 0); +} + +struct string * +send_cookies_js(struct uri *uri) +{ + return send_cookies_common(uri, 1); +} + static void done_cookies(struct module *module); @@ -719,7 +735,7 @@ load_cookies(void) { while (fgets(in_buffer, 6 * MAX_STR_LEN, fp)) { struct cookie *cookie; unsigned char *p, *q = in_buffer; - enum { NAME = 0, VALUE, SERVER, PATH, DOMAIN, EXPIRES, SECURE, MEMBERS }; + enum { NAME = 0, VALUE, SERVER, PATH, DOMAIN, EXPIRES, SECURE, HTTPONLY, MEMBERS }; int member; struct { unsigned char *pos; @@ -740,7 +756,7 @@ load_cookies(void) { members[member].len = p - q; } - if (member != MEMBERS) continue; /* Invalid line. */ + if ((member != HTTPONLY) && (member != MEMBERS)) continue; /* Invalid line. */ /* Skip expired cookies if any. */ expires = str_to_time_t(members[EXPIRES].pos); @@ -768,6 +784,7 @@ load_cookies(void) { cookie->expires = expires; cookie->secure = !!atoi(members[SECURE].pos); + cookie->httponly = (member == MEMBERS) && !!atoi(members[HTTPONLY].pos); accept_cookie(cookie); } @@ -857,12 +874,12 @@ save_cookies(struct terminal *term) { now = time(NULL); foreach (c, cookies) { if (!c->expires || c->expires <= now) continue; - if (secure_fprintf(ssi, "%s\t%s\t%s\t%s\t%s\t%"TIME_PRINT_FORMAT"\t%d\n", + if (secure_fprintf(ssi, "%s\t%s\t%s\t%s\t%s\t%"TIME_PRINT_FORMAT"\t%d\t%d\n", c->name, c->value, c->server->host, empty_string_or_(c->path), empty_string_or_(c->domain), - (time_print_T) c->expires, c->secure) < 0) + (time_print_T) c->expires, c->secure, c->httponly) < 0) break; } diff --git a/src/cookies/cookies.h b/src/cookies/cookies.h index a2f6695ea..c8b8e38c6 100644 --- a/src/cookies/cookies.h +++ b/src/cookies/cookies.h @@ -40,7 +40,8 @@ struct cookie { struct cookie_server *server; /* The host the cookie originated from */ time_t expires; /* Expiration time. Zero means undefined */ - int secure; /* Did it have 'secure' attribute */ + unsigned int secure:1; /* Did it have 'secure' attribute */ + unsigned int httponly:1; /* Did it have 'httponly' attribute */ struct listbox_item *box_item; }; @@ -61,6 +62,7 @@ void set_cookies_dirty(void); * string will be overwritten at the next call time. The string source * itself is dynamically allocated, though. */ struct string *send_cookies(struct uri *uri); +struct string *send_cookies_js(struct uri *uri); extern struct module cookies_module; diff --git a/src/cookies/dialogs.c b/src/cookies/dialogs.c index 597e9fbc2..4de71ca71 100644 --- a/src/cookies/dialogs.c +++ b/src/cookies/dialogs.c @@ -48,6 +48,8 @@ add_cookie_info_to_string(struct string *string, struct cookie *cookie, add_format_to_string(string, "\n%s: %s", _("Secure", term), _(cookie->secure ? N_("yes") : N_("no"), term)); + add_format_to_string(string, "\n%s: %s", _("HttpOnly", term), + _(cookie->httponly ? N_("yes") : N_("no"), term)); } static void @@ -321,13 +323,33 @@ set_cookie_secure(struct dialog_data *dlg_data, struct widget_data *widget_data) return EVENT_PROCESSED; } +static widget_handler_status_T +set_cookie_httponly(struct dialog_data *dlg_data, struct widget_data *widget_data) +{ + struct cookie *cookie = dlg_data->dlg->udata; + unsigned char *value = widget_data->cdata; + unsigned char *end; + long number; + + if (!value || !cookie) return EVENT_NOT_PROCESSED; + + errno = 0; + number = strtol(value, (char **) &end, 10); + if (errno || *end) return EVENT_NOT_PROCESSED; + + cookie->httponly = (number != 0); + set_cookies_dirty(); + return EVENT_PROCESSED; +} + + static void build_edit_dialog(struct terminal *term, struct cookie *cookie) { -#define EDIT_WIDGETS_COUNT 8 +#define EDIT_WIDGETS_COUNT 9 /* [gettext_accelerator_context(.build_edit_dialog)] */ struct dialog *dlg; - unsigned char *name, *value, *domain, *expires, *secure; + unsigned char *name, *value, *domain, *expires, *secure, *httponly; unsigned char *dlg_server; int length = 0; @@ -344,6 +366,7 @@ build_edit_dialog(struct terminal *term, struct cookie *cookie) domain = value + MAX_STR_LEN; expires = domain + MAX_STR_LEN; secure = expires + MAX_STR_LEN; + httponly = secure + MAX_STR_LEN; safe_strncpy(name, cookie->name, MAX_STR_LEN); safe_strncpy(value, cookie->value, MAX_STR_LEN); @@ -352,6 +375,8 @@ build_edit_dialog(struct terminal *term, struct cookie *cookie) ulongcat(expires, &length, cookie->expires, MAX_STR_LEN, 0); length = 0; ulongcat(secure, &length, cookie->secure, MAX_STR_LEN, 0); + length = 0; + ulongcat(httponly, &length, cookie->httponly, MAX_STR_LEN, 0); dlg_server = cookie->server->host; dlg_server = straconcat(_("Server", term), ": ", dlg_server, "\n", @@ -368,6 +393,7 @@ build_edit_dialog(struct terminal *term, struct cookie *cookie) add_dlg_field_float(dlg, _("Domain", term), 0, 0, set_cookie_domain, MAX_STR_LEN, domain, NULL); add_dlg_field_float(dlg, _("Expires", term), 0, 0, set_cookie_expires, MAX_STR_LEN, expires, NULL); add_dlg_field_float(dlg, _("Secure", term), 0, 0, set_cookie_secure, MAX_STR_LEN, secure, NULL); + add_dlg_field_float(dlg, _("HttpOnly", term), 0, 0, set_cookie_httponly, MAX_STR_LEN, httponly, NULL); add_dlg_button(dlg, _("~OK", term), B_ENTER, ok_dialog, NULL); add_dlg_button(dlg, _("~Cancel", term), B_ESC, cancel_dialog, NULL); diff --git a/src/ecmascript/spidermonkey/document.c b/src/ecmascript/spidermonkey/document.c index e82d264b1..b26c284ea 100644 --- a/src/ecmascript/spidermonkey/document.c +++ b/src/ecmascript/spidermonkey/document.c @@ -110,7 +110,7 @@ document_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp) #ifdef CONFIG_COOKIES if (!strcmp(string, "cookie")) { - struct string *cookies = send_cookies(vs->uri); + struct string *cookies = send_cookies_js(vs->uri); if (cookies) { static unsigned char cookiestr[1024];