Applications/Internet/Cyberia: Initial support for cookies

This commit is contained in:
Alec Murphy
2025-10-10 11:40:00 -04:00
parent f9e9f46081
commit 6253fe8004

View File

@@ -469,6 +469,116 @@ U0 @cyberia_msgbox_error_wrapper(U8* msg)
} }
} }
U0 @cyberia_get_key_value(U8* s, U64* key_ptr, U64* value_ptr)
{
I64 i;
I64 len = StrLen(s);
for (i = 0; i < len; i++) {
if (!(*key_ptr)) {
switch (s[i]) {
case ' ':
case '\t':
case '\r':
case '\n':
break;
default:
*key_ptr = s + i;
break;
}
} else {
switch (s[i]) {
case '=':
s[i] = NULL;
*value_ptr = s + i + 1;
return;
default:
break;
}
}
}
}
U0 @cyberia_set_cookie_baked(U8* domain, U8* key, U8* value)
{
if (!cyberia->o("cookies")->@(domain)) {
cyberia->o("cookies")->set(domain, Json.CreateObject(erythros_mem_task), JSON_OBJECT);
}
cyberia->o("cookies")->o(domain)->set(key, value, JSON_STRING);
}
U0 @cyberia_set_cookie_raw(@browser* browser, U8* s)
{
// - Parse key=value pairs from value
// by default, Set-Cookie or Clear-Site-Data effects domain.tld as well as ...*.*.*.*.domain.tld
if (!browser || !s || !StrLen(s)) {
return;
}
U8* domain = browser->renderer->current_url->host;
// A user agent MUST use an algorithm equivalent to the following algorithm to parse a set-cookie-string:
// If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F character (CTL characters excluding HTAB):
// Abort this algorithm and ignore the set-cookie-string entirely.
I64 i;
I64 len = StrLen(s);
for (i = 0; i < len; i++) {
switch (s[i]) {
case 0x00...0x08:
case 0x0a...0x1f:
case 0x7f:
return;
default:
break;
}
}
// FIXME: For now, we are going to ignore unparsed-attributes, and match against domain.tld
U8* t = StrFind(";", s);
if (t) {
*t = NULL;
}
U64 key = NULL;
U64 value = NULL;
@cyberia_get_key_value(s, &key, &value);
if (domain && key && value) {
@cyberia_set_cookie_baked(domain, key, value);
}
}
U0 @cyberia_set_cookies(@browser* browser, @http_response* resp)
{
if (!browser || !resp || !browser->renderer || !resp->headers) {
return;
}
I64 i = 0;
U8* value = NULL;
JsonArray* a = NULL;
JsonKey* keys = resp->headers->keys;
while (keys) {
if (!StrICmp(keys->name, "set-cookie")) {
switch (keys->type) {
case JSON_ARRAY:
a = keys->value;
for (i = 0; i < a->length; i++) {
@cyberia_set_cookie_raw(browser, a->@(i));
}
break;
default:
@cyberia_set_cookie_raw(browser, keys->value);
break;
}
}
keys = keys->next;
}
}
U0 @cyberia_navigate(Bool refresh = FALSE) U0 @cyberia_navigate(Bool refresh = FALSE)
{ {
win->focused_widget = NULL; win->focused_widget = NULL;
@@ -546,6 +656,10 @@ U0 @cyberia_navigate(Bool refresh = FALSE)
MemSet(buffer, 0, HTTP_FETCH_BUFFER_SIZE); MemSet(buffer, 0, HTTP_FETCH_BUFFER_SIZE);
@http_response* resp = NULL; @http_response* resp = NULL;
JsonObject* headers = NULL;
U8* domain = renderer->current_url->host;
JsonKey* cookie_keys = NULL;
U8 cookie_buf[2048];
if (!StrCmp(&addressbar1->text, "about:newtab")) { if (!StrCmp(&addressbar1->text, "about:newtab")) {
resp = CAlloc(sizeof(@http_response)); resp = CAlloc(sizeof(@http_response));
@@ -556,7 +670,26 @@ U0 @cyberia_navigate(Bool refresh = FALSE)
StrCpy(&addressbar1->text, ""); StrCpy(&addressbar1->text, "");
win->focused_widget = addressbar1; win->focused_widget = addressbar1;
} else { } else {
resp = Http.Get(renderer->current_url, buffer); if (cyberia->o("cookies")->@(domain)) {
headers = Json.CreateObject(browser_task);
cookie_keys = cyberia->o("cookies")->o(domain)->keys;
StrCpy(cookie_buf, "");
while (cookie_keys) {
StrPrint(cookie_buf + StrLen(cookie_buf), "%s=%s", cookie_keys->name, cookie_keys->value);
if (cookie_keys->next) {
StrCpy(cookie_buf + StrLen(cookie_buf), "; ");
}
cookie_keys = cookie_keys->next;
}
headers->set("Cookie", cookie_buf, JSON_STRING);
}
if (renderer->form_data_str) {
resp = Http.Post(renderer->current_url, buffer, renderer->form_data_str, headers);
// FIXME: form_data_str should be freed
renderer->form_data_str = NULL;
} else {
resp = Http.Get(renderer->current_url, buffer, NULL, headers);
}
} }
while (resp->state != HTTP_STATE_DONE) { while (resp->state != HTTP_STATE_DONE) {