Applications/Internet/Cyberia.app: Initial support for FORM method=get

Now we can search with simple engines like Wiby and FrogFind.
This commit is contained in:
Alec Murphy 2025-04-16 15:03:59 -04:00
parent 4ef542cf32
commit ebfaa0254c

View file

@ -37,17 +37,81 @@ class @browser
U8* search_query; U8* search_query;
}; };
@browser* browser = CAlloc(sizeof(@browser)); @browser* browser = CAlloc(sizeof(@browser), Fs);
I64 @cyberia_is_alphanum(I64 c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
}
U8* @cyberia_urlencode_str(U8* str, I64* output_len)
{
if (str == NULL) {
return NULL;
}
I64 len = StrLen(str);
U8* encoded_str = NULL;
U8* dest;
I64 encoded_len = 0;
U8* p;
I64 c;
Bool contains_plus = FALSE;
// First pass: calculate the exact required length
p = str;
while (*p) {
c = *p;
// Check if the character should NOT be encoded
if (@cyberia_is_alphanum(c) || c == '-' || c == '_' || c == '.') {
encoded_len++;
} else if (c == ' ') {
encoded_len++; // Will be replaced by '+'
contains_plus = TRUE;
} else {
encoded_len += 3; // Will be replaced by %XX
}
++p;
}
*output_len = encoded_len;
if (encoded_len == StrLen(str) && !contains_plus)
return str;
// Allocate memory for the encoded string + null terminator
encoded_str = CAlloc(encoded_len + 1, browser->task);
if (!encoded_str)
return NULL;
// Second pass: build the encoded string
dest = encoded_str;
p = str;
while (*p) {
c = *p;
if (@cyberia_is_alphanum(c) || c == '-' || c == '_' || c == '.') {
*dest++ = c;
} else if (c == ' ') {
*dest++ = '+';
} else {
StrPrint(dest, "%%%02X", c);
dest += 3;
}
++p;
}
*dest = '\0';
return encoded_str;
}
browser->history = Json.CreateArray(Fs); browser->history = Json.CreateArray(Fs);
browser->history_index = -1; browser->history_index = -1;
browser->renderer = NULL; browser->renderer = NULL;
browser->task = Fs; browser->task = Fs;
browser->fetch_buffer = CAlloc(HTTP_FETCH_BUFFER_SIZE); browser->fetch_buffer = CAlloc(HTTP_FETCH_BUFFER_SIZE, browser->task);
browser->go_to_url_string = NULL; browser->go_to_url_string = NULL;
browser->javascript_link_handlers = Json.CreateObject(Fs); browser->javascript_link_handlers = Json.CreateObject(Fs);
browser->lazyload_buffer = CAlloc(HTTP_FETCH_BUFFER_SIZE); browser->lazyload_buffer = CAlloc(HTTP_FETCH_BUFFER_SIZE, browser->task);
browser->lazyload_timeout_buffer = CAlloc(HTTP_FETCH_BUFFER_SIZE); browser->lazyload_timeout_buffer = CAlloc(HTTP_FETCH_BUFFER_SIZE, browser->task);
U0 @cyberia_win_close(Window* win) U0 @cyberia_win_close(Window* win)
{ {
@ -96,6 +160,96 @@ U0 @cyberia_link_clicked(Widget* widget)
Spawn(&@cyberia_navigate); Spawn(&@cyberia_navigate);
} }
U0 @cyberia_collect_form_nodes(JsonArray* array, @html_dom_node* node)
{
if (!array || !node)
return;
if (!StrICmp(node->tagName, "input") || !StrICmp(node->tagName, "textarea")) {
if (node->attributes->@("name")) {
array->append(node, JSON_NUMBER);
}
}
I64 i;
if (node->children->length) {
for (i = 0; i < node->children->length; i++)
@cyberia_collect_form_nodes(array, node->children->@(i));
}
}
U0 @cyberia_form_submit_clicked(Widget* widget)
{
if (!widget || !widget->data)
return;
@html_dom_node* form_node = @self_or_ancestor_matches_tag_name(widget->data, "form");
if (!form_node)
return;
if (!form_node->attributes->@("method"))
form_node->attributes->set("method", "get", JSON_STRING);
if (!form_node->attributes->@("action"))
form_node->attributes->set("action", "#", JSON_STRING);
I64 i;
U8* method = form_node->attributes->@("method");
U8* action = @resolve_href(browser->renderer, form_node->attributes->@("action"));
@html_dom_node* element_node;
"method: \"%s\", action: \"%s\"\n", method, action;
JsonArray* form_elements = Json.CreateArray(browser->renderer->task);
@cyberia_collect_form_nodes(form_elements, form_node);
"form element count: %d\n", form_elements->length;
U8 get_request_str[1024];
if (!StrICmp(method, "get")) {
StrPrint(get_request_str, "%s?", action);
for (i = 0; i < form_elements->length; i++) {
element_node = form_elements->@(i);
U8* name = element_node->attributes->@("name");
U8* raw_value = "";
U8* encoded_value = NULL;
I64 encoded_value_length = 0;
Widget* element_gui_widget = element_node->attributes->@("cyberiaGuiWidget");
switch (element_gui_widget->type) {
case WIDGET_TYPE_CHECKBOX:
if (element_gui_widget(CheckBoxWidget*)->checked) {
raw_value = @t(element_node->attributes->@("value"), element_node->attributes->@("value"), "on");
} else {
raw_value = NULL;
}
break;
case WIDGET_TYPE_INPUT:
raw_value = &element_gui_widget(TextInputWidget*)->text;
break;
default:
break;
}
encoded_value = @cyberia_urlencode_str(raw_value, &encoded_value_length);
if (encoded_value) {
String.Append(get_request_str, "%s=%s", name, encoded_value);
if (i < form_elements->length - 1)
String.Append(get_request_str, "&");
if (encoded_value_length != StrLen(raw_value)) {
Free(encoded_value);
}
}
}
StrCpy(&addressbar1->text, &get_request_str);
"get_request_str: %s\n", get_request_str;
}
Free(action);
Spawn(&@cyberia_navigate);
}
U0 @cyberia_refresh_clicked() U0 @cyberia_refresh_clicked()
{ {
if (refreshbtn1->disabled) if (refreshbtn1->disabled)
@ -203,6 +357,7 @@ U0 @cyberia_navigate(Bool refresh = FALSE)
renderer->images = NULL; renderer->images = NULL;
renderer->link_pointer = Compositor.theme.pointer.link; renderer->link_pointer = Compositor.theme.pointer.link;
renderer->link_callback = &@cyberia_link_clicked; renderer->link_callback = &@cyberia_link_clicked;
renderer->form_submit_callback = &@cyberia_form_submit_clicked;
renderer->widgets_base = widgets_base->next; renderer->widgets_base = widgets_base->next;
renderer->status_widget = status1; renderer->status_widget = status1;
renderer->background_widget = background1; renderer->background_widget = background1;
@ -280,7 +435,7 @@ U0 @cyberia_navigate(Bool refresh = FALSE)
return; return;
StrCpy(&addressbar1->text, resolved_location); StrCpy(&addressbar1->text, resolved_location);
Free(resolved_location); Free(resolved_location);
@cyberia_navigate; @cyberia_navigate(1);
return; return;
} }
@ -301,31 +456,31 @@ U0 @cyberia_navigate(Bool refresh = FALSE)
while (append->next) { while (append->next) {
append = append->next; append = append->next;
} }
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = controlsbackdrop1; append->next->widget = controlsbackdrop1;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = backbtn1; append->next->widget = backbtn1;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = fwdbtn1; append->next->widget = fwdbtn1;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = refreshbtn1; append->next->widget = refreshbtn1;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = addressbar1; append->next->widget = addressbar1;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = statusbackdrop1; append->next->widget = statusbackdrop1;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = status1; append->next->widget = status1;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = status2; append->next->widget = status2;
append = append->next; append = append->next;
append->next = CAlloc(sizeof(@window_widgets_list)); append->next = CAlloc(sizeof(@window_widgets_list), browser->task);
append->next->widget = vscroll1; append->next->widget = vscroll1;
vscroll1->scroll = 0; vscroll1->scroll = 0;