From cc1094f0ac62db0d736b6e41e219fe628d22a69e Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Fri, 20 Feb 2009 11:39:25 +0000 Subject: Utilise hubbub's form association callback. Please can we dispense with the libxml binding? It's causing much #ifdef mess. Fix encoding of names -- previously were output as raw utf-8, rather than in the submission charset. Actually bother to destroy forms in a document, and the controls associated with them. We still leak non form-associated controls, but that's too much effort to fix right now. svn path=/trunk/netsurf/; revision=6573 --- render/box_construct.c | 197 +++++++++++++++++++++++++++++-------------------- 1 file changed, 118 insertions(+), 79 deletions(-) (limited to 'render/box_construct.c') diff --git a/render/box_construct.c b/render/box_construct.c index 94ca2ef57..4f9bdfd32 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -140,7 +140,9 @@ static bool box_a(BOX_SPECIAL_PARAMS); static bool box_body(BOX_SPECIAL_PARAMS); static bool box_br(BOX_SPECIAL_PARAMS); static bool box_image(BOX_SPECIAL_PARAMS); +#ifndef WITH_HUBBUB static bool box_form(BOX_SPECIAL_PARAMS); +#endif static bool box_textarea(BOX_SPECIAL_PARAMS); static bool box_select(BOX_SPECIAL_PARAMS); static bool box_input(BOX_SPECIAL_PARAMS); @@ -174,7 +176,9 @@ static const struct element_entry element_table[] = { {"br", box_br}, {"button", box_button}, {"embed", box_embed}, +#ifndef WITH_HUBBUB {"form", box_form}, +#endif {"frameset", box_frameset}, {"iframe", box_iframe}, {"image", box_image}, @@ -2158,13 +2162,14 @@ bool box_iframe(BOX_SPECIAL_PARAMS) } +#ifndef WITH_HUBBUB /** * Interactive form [17.3]. */ bool box_form(BOX_SPECIAL_PARAMS) { - char *xmlaction, *action, *faction, *method, *enctype, *charset, *target; + char *xmlaction, *action, *method, *enctype, *charset, *target; form_method fmethod; struct form *form; url_func_result result; @@ -2173,26 +2178,22 @@ bool box_form(BOX_SPECIAL_PARAMS) xmlGetProp(n, (const xmlChar *) "action"))) { /* the action attribute is required, but many forms fail to * specify it. In the case where it is _not_ specified, - * follow other browsers and make the form action the - * URI of the page the form is contained in. */ - action = strdup(""); + * follow other browsers and make the form action the URI of + * the page the form is contained in. */ + action = strdup(content->data.html.base_url); } else { - action = strdup(xmlaction); + result = url_join(xmlaction, content->data.html.base_url, + &action); + xmlFree(xmlaction); + + if (result != URL_FUNC_OK) + return false; } if (!action) return false; - result = url_join(action, content->data.html.base_url, &faction); - if (result != URL_FUNC_OK) { - free(action); - return false; - } - - /* No longer needed */ - free(action); - fmethod = method_GET; if ((method = (char *) xmlGetProp(n, (const xmlChar *) "method"))) { if (strcasecmp(method, "post") == 0) { @@ -2214,20 +2215,24 @@ bool box_form(BOX_SPECIAL_PARAMS) /* target for form data */ target = (char *) xmlGetProp(n, (const xmlChar *) "target"); - form = form_new(faction, target, fmethod, charset, - content->data.html.encoding); - if (!form) { - free(faction); - xmlFree(target); + form = form_new(n, action, target, fmethod, charset, + content->data.html.encoding); + + free(action); + if (charset) xmlFree(charset); + if (target) + xmlFree(target); + + if (!form) return false; - } + form->prev = content->data.html.forms; content->data.html.forms = form; return true; } - +#endif /** * Form control [17.4]. @@ -2241,25 +2246,36 @@ bool box_input(BOX_SPECIAL_PARAMS) type = (char *) xmlGetProp(n, (const xmlChar *) "type"); +#ifdef WITH_HUBBUB + gadget = binding_get_control_for_node(content->data.html.parser_binding, + n); + if (!gadget) + goto no_memory; + box->gadget = gadget; + gadget->box = box; +#endif + if (type && strcasecmp(type, "password") == 0) { if (!box_input_text(n, content, box, 0, markup_track, author, true)) goto no_memory; +#ifndef WITH_HUBBUB gadget = box->gadget; gadget->box = box; - +#endif } else if (type && strcasecmp(type, "file") == 0) { box->type = BOX_INLINE_BLOCK; - box->gadget = gadget = form_new_control(GADGET_FILE); +#ifndef WITH_HUBBUB + box->gadget = gadget = form_new_control(n, GADGET_FILE); if (!gadget) goto no_memory; gadget->box = box; - +#endif } else if (type && strcasecmp(type, "hidden") == 0) { /* no box for hidden inputs */ box->style->display = CSS_DISPLAY_NONE; - - gadget = form_new_control(GADGET_HIDDEN); +#ifndef WITH_HUBBUB + gadget = form_new_control(n, GADGET_HIDDEN); if (!gadget) goto no_memory; @@ -2270,11 +2286,12 @@ bool box_input(BOX_SPECIAL_PARAMS) goto no_memory; gadget->length = strlen(gadget->value); } - +#endif } else if (type && (strcasecmp(type, "checkbox") == 0 || strcasecmp(type, "radio") == 0)) { - box->gadget = gadget = form_new_control(type[0] == 'c' || - type[0] == 'C' ? GADGET_CHECKBOX : +#ifndef WITH_HUBBUB + box->gadget = gadget = form_new_control(n, type[0] == 'c' || + type[0] == 'C' ? GADGET_CHECKBOX : GADGET_RADIO); if (!gadget) goto no_memory; @@ -2289,9 +2306,10 @@ bool box_input(BOX_SPECIAL_PARAMS) goto no_memory; gadget->length = strlen(gadget->value); } - +#endif } else if (type && (strcasecmp(type, "submit") == 0 || - strcasecmp(type, "reset") == 0)) { + strcasecmp(type, "reset") == 0 || + strcasecmp(type, "button") == 0)) { struct box *inline_container, *inline_box; if (!box_button(n, content, box, 0, markup_track, author)) goto no_memory; @@ -2310,30 +2328,9 @@ bool box_input(BOX_SPECIAL_PARAMS) else if (box->gadget->type == GADGET_SUBMIT) inline_box->text = talloc_strdup(content, messages_get("Form_Submit")); - else + else if (box->gadget->type == GADGET_RESET) inline_box->text = talloc_strdup(content, messages_get("Form_Reset")); - if (!inline_box->text) - goto no_memory; - inline_box->length = strlen(inline_box->text); - box_add_child(inline_container, inline_box); - box_add_child(box, inline_container); - - } else if (type && strcasecmp(type, "button") == 0) { - struct box *inline_container, *inline_box; - if (!box_button(n, content, box, 0, markup_track, author)) - goto no_memory; - inline_container = box_create(0, 0, 0, 0, 0, content); - if (!inline_container) - goto no_memory; - inline_container->type = BOX_INLINE_CONTAINER; - inline_box = box_create(box->style, 0, 0, box->title, 0, - content); - if (!inline_box) - goto no_memory; - inline_box->type = BOX_TEXT; - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "value"))) - inline_box->text = talloc_strdup(content, s); else inline_box->text = talloc_strdup(content, "Button"); if (!inline_box->text) @@ -2341,12 +2338,13 @@ bool box_input(BOX_SPECIAL_PARAMS) inline_box->length = strlen(inline_box->text); box_add_child(inline_container, inline_box); box_add_child(box, inline_container); - } else if (type && strcasecmp(type, "image") == 0) { - box->gadget = gadget = form_new_control(GADGET_IMAGE); +#ifndef WITH_HUBBUB + box->gadget = gadget = form_new_control(n, GADGET_IMAGE); if (!gadget) goto no_memory; gadget->box = box; +#endif gadget->type = GADGET_IMAGE; if (box->style && box->style->display != CSS_DISPLAY_NONE) { @@ -2375,19 +2373,21 @@ bool box_input(BOX_SPECIAL_PARAMS) free(url); } } - } else { /* the default type is "text" */ if (!box_input_text(n, content, box, 0, markup_track, author, false)) goto no_memory; +#ifndef WITH_HUBBUB gadget = box->gadget; gadget->box = box; +#endif } if (type) xmlFree(type); +#ifndef WITH_HUBBUB if (gadget) { if (content->data.html.forms) form_add_control(content->data.html.forms, gadget); @@ -2399,6 +2399,7 @@ bool box_input(BOX_SPECIAL_PARAMS) goto no_memory; } } +#endif *convert_children = false; return true; @@ -2406,9 +2407,10 @@ bool box_input(BOX_SPECIAL_PARAMS) no_memory: if (type) xmlFree(type); +#ifndef WITH_HUBBUB if (gadget) form_free_control(gadget); - +#endif return false; } @@ -2419,14 +2421,17 @@ no_memory: bool box_input_text(BOX_SPECIAL_PARAMS, bool password) { +#ifndef WITH_HUBBUB char *s; +#endif struct box *inline_container, *inline_box; box->type = BOX_INLINE_BLOCK; - box->gadget = form_new_control((password) ? GADGET_PASSWORD : +#ifndef WITH_HUBBUB + box->gadget = form_new_control(n, (password) ? GADGET_PASSWORD : GADGET_TEXTBOX); if (!box->gadget) - return 0; + return false; box->gadget->box = box; if ((s = (char *) xmlGetProp(n, (const xmlChar *) "maxlength"))) { @@ -2446,6 +2451,7 @@ bool box_input_text(BOX_SPECIAL_PARAMS, bool password) return NULL; } box->gadget->length = strlen(box->gadget->value); +#endif inline_container = box_create(0, 0, 0, 0, 0, content); if (!inline_container) @@ -2488,19 +2494,16 @@ bool box_input_text(BOX_SPECIAL_PARAMS, bool password) bool box_button(BOX_SPECIAL_PARAMS) { +#ifndef WITH_HUBBUB xmlChar *s; char *type = (char *) xmlGetProp(n, (const xmlChar *) "type"); - box->type = BOX_INLINE_BLOCK; - if (!type || strcasecmp(type, "submit") == 0) { - box->gadget = form_new_control(GADGET_SUBMIT); + box->gadget = form_new_control(n, GADGET_SUBMIT); } else if (strcasecmp(type, "reset") == 0) { - box->gadget = form_new_control(GADGET_RESET); + box->gadget = form_new_control(n, GADGET_RESET); } else { - /* type="button" or unknown: just render the contents */ - xmlFree(type); - return true; + box->gadget = form_new_control(n, GADGET_BUTTON); } if (type) @@ -2512,6 +2515,7 @@ bool box_button(BOX_SPECIAL_PARAMS) if (content->data.html.forms) form_add_control(content->data.html.forms, box->gadget); box->gadget->box = box; + if ((s = xmlGetProp(n, (const xmlChar *) "name")) != NULL) { box->gadget->name = strdup((char *) s); xmlFree(s); @@ -2524,6 +2528,20 @@ bool box_button(BOX_SPECIAL_PARAMS) if (!box->gadget->value) return false; } +#else + struct form_control *gadget; + + gadget = binding_get_control_for_node(content->data.html.parser_binding, + n); + if (!gadget) + return false; + + box->gadget = gadget; + gadget->box = box; +#endif + box->type = BOX_INLINE_BLOCK; + + /* Just render the contents */ return true; } @@ -2538,23 +2556,24 @@ bool box_select(BOX_SPECIAL_PARAMS) struct box *inline_container; struct box *inline_box; struct form_control *gadget; - char* s; +#ifndef WITH_HUBBUB + char *s; +#endif xmlNode *c, *c2; - gadget = form_new_control(GADGET_SELECT); +#ifndef WITH_HUBBUB + gadget = form_new_control(n, GADGET_SELECT); +#else + gadget = binding_get_control_for_node(content->data.html.parser_binding, + n); +#endif if (!gadget) return false; - gadget->data.select.multiple = false; - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "multiple"))) { - gadget->data.select.multiple = true; - xmlFree(s); - } - - gadget->data.select.items = NULL; - gadget->data.select.last_item = NULL; - gadget->data.select.num_items = 0; - gadget->data.select.num_selected = 0; +#ifndef WITH_HUBBUB + gadget->data.select.multiple = + xmlHasProp(n, (const xmlChar *) "multiple"); +#endif for (c = n->children; c; c = c->next) { if (strcmp((const char *) c->name, "option") == 0) { @@ -2573,16 +2592,20 @@ bool box_select(BOX_SPECIAL_PARAMS) if (gadget->data.select.num_items == 0) { /* no options: ignore entire select */ +#ifndef WITH_HUBBUB form_free_control(gadget); +#endif return true; } +#ifndef WITH_HUBBUB if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { gadget->name = strdup(s); xmlFree(s); if (!gadget->name) goto no_memory; } +#endif box->type = BOX_INLINE_BLOCK; box->gadget = gadget; @@ -2621,14 +2644,18 @@ bool box_select(BOX_SPECIAL_PARAMS) inline_box->length = strlen(inline_box->text); +#ifndef WITH_HUBBUB if (content->data.html.forms) form_add_control(content->data.html.forms, box->gadget); +#endif *convert_children = false; return true; no_memory: +#ifndef WITH_HUBBUB form_free_control(gadget); +#endif return false; } @@ -2709,17 +2736,24 @@ bool box_textarea(BOX_SPECIAL_PARAMS) size_t len; box->type = BOX_INLINE_BLOCK; - box->gadget = form_new_control(GADGET_TEXTAREA); +#ifndef WITH_HUBBUB + box->gadget = form_new_control(n, GADGET_TEXTAREA); +#else + box->gadget = binding_get_control_for_node( + content->data.html.parser_binding, n); +#endif if (!box->gadget) return false; box->gadget->box = box; +#ifndef WITH_HUBBUB if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name"))) { box->gadget->name = strdup(s); xmlFree(s); if (!box->gadget->name) return false; } +#endif inline_container = box_create(0, 0, 0, box->title, 0, content); if (!inline_container) @@ -2727,6 +2761,9 @@ bool box_textarea(BOX_SPECIAL_PARAMS) inline_container->type = BOX_INLINE_CONTAINER; box_add_child(box, inline_container); + /** \todo Is it really necessary to reparse the content of a + * textarea element to remove entities? Hubbub will do that for us. + */ n2 = n->children; buf = xmlBufferCreate(); while(n2) { @@ -2806,8 +2843,10 @@ bool box_textarea(BOX_SPECIAL_PARAMS) xmlFree(string); xmlBufferFree(buf); +#ifndef WITH_HUBBUB if (content->data.html.forms) form_add_control(content->data.html.forms, box->gadget); +#endif *convert_children = false; return true; -- cgit v1.2.3