From 5c96acd6f119b71fc75e5d48465afca9fd13e87f Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 26 Sep 2018 17:14:25 +0100 Subject: fix url encoding to be compatible with nsurl API changes. As part of this fix the form submission error handling and reporting has been improved. --- content/handlers/html/box_textarea.c | 17 ++- content/handlers/html/form.c | 224 +++++++++++++++---------------- content/handlers/html/form_internal.h | 35 ++--- content/handlers/html/html_interaction.c | 41 ++++-- 4 files changed, 165 insertions(+), 152 deletions(-) (limited to 'content/handlers/html') diff --git a/content/handlers/html/box_textarea.c b/content/handlers/html/box_textarea.c index c19afbb77..f0ba9f9de 100644 --- a/content/handlers/html/box_textarea.c +++ b/content/handlers/html/box_textarea.c @@ -25,8 +25,11 @@ #include "utils/config.h" #include "utils/log.h" +#include "utils/messages.h" #include "netsurf/keypress.h" +#include "netsurf/misc.h" #include "desktop/textarea.h" +#include "desktop/gui_internal.h" #include "html/html_internal.h" #include "html/box.h" @@ -41,6 +44,7 @@ bool box_textarea_keypress(html_content *html, struct box *box, uint32_t key) struct textarea *ta = gadget->data.text.ta; struct form* form = box->gadget->form; struct content *c = (struct content *) html; + nserror res; assert(ta != NULL); @@ -48,9 +52,16 @@ bool box_textarea_keypress(html_content *html, struct box *box, uint32_t key) switch (key) { case NS_KEY_NL: case NS_KEY_CR: - if (form) - form_submit(content_get_url(c), html->bw, - form, 0); + if (form) { + res = form_submit(content_get_url(c), + html->bw, + form, + NULL); + if (res != NSERROR_OK) { + guit->misc->warning(messages_get_errorcode(res), NULL); + } + + } return true; case NS_KEY_TAB: diff --git a/content/handlers/html/form.c b/content/handlers/html/form.c index 4a9d7102d..f779f07bd 100644 --- a/content/handlers/html/form.c +++ b/content/handlers/html/form.c @@ -327,10 +327,28 @@ bool form_add_option(struct form_control *control, char *value, char *text, } -/* exported interface documented in html/form_internal.h */ -bool form_successful_controls_dom(struct form *_form, - struct form_control *_submit_button, - struct fetch_multipart_data **successful_controls) +/** + * Identify 'successful' controls via the DOM. + * + * All text strings in the successful controls list will be in the charset most + * appropriate for submission. Therefore, no utf8_to_* processing should be + * performed upon them. + * + * \todo The chosen charset needs to be made available such that it can be + * included in the submission request (e.g. in the fetch's Content-Type header) + * + * See HTML 4.01 section 17.13.2. + * + * \param[in] form form to search for successful controls + * \param[in] submit_button control used to submit the form, if any + * \param[out] successful_controls updated to point to linked list of + * fetch_multipart_data, NULL if no controls + * \return NSERROR_OK on success or appropriate error code + */ +static nserror +form_successful_controls_dom(struct form *_form, + struct form_control *_submit_button, + struct fetch_multipart_data **successful_controls) { dom_html_form_element *form = _form->node; dom_html_element *submit_button = (_submit_button != NULL) ? _submit_button->node : NULL; @@ -352,7 +370,7 @@ bool form_successful_controls_dom(struct form *_form, charset = form_acceptable_charset(_form); if (charset == NULL) { NSLOG(netsurf, INFO, "failed to find charset"); - return false; + return NSERROR_NOMEM; } #define ENCODE_ITEM(i) (((i) == NULL) ? ( \ @@ -685,6 +703,11 @@ bool form_successful_controls_dom(struct form *_form, } basename = ENCODE_ITEM(inputname); + if (basename == NULL) { + NSLOG(netsurf, INFO, + "Could not encode basename"); + goto dom_no_memory; + } success_new = calloc(1, sizeof(*success_new)); if (success_new == NULL) { @@ -704,6 +727,8 @@ bool form_successful_controls_dom(struct form *_form, "Could not allocate name for image.x"); goto dom_no_memory; } + sprintf(success_new->name, "%s.x", basename); + success_new->value = malloc(20); if (success_new->value == NULL) { free(basename); @@ -711,7 +736,6 @@ bool form_successful_controls_dom(struct form *_form, "Could not allocate value for image.x"); goto dom_no_memory; } - sprintf(success_new->name, "%s.x", basename); sprintf(success_new->value, "%d", coords->x); success_new = calloc(1, sizeof(*success_new)); @@ -890,7 +914,7 @@ bool form_successful_controls_dom(struct form *_form, *successful_controls = sentinel.next; - return true; + return NSERROR_OK; dom_no_memory: free(charset); @@ -915,73 +939,61 @@ dom_no_memory: if (rawfile_temp != NULL) free(rawfile_temp); - return false; + return NSERROR_NOMEM; } #undef ENCODE_ITEM /** * Encode controls using application/x-www-form-urlencoded. * - * \param form form to which successful controls relate - * \param control linked list of fetch_multipart_data - * \param query_string iff true add '?' to the start of returned data - * \return URL-encoded form, or 0 on memory exhaustion + * \param[in] form form to which successful controls relate + * \param[in] control linked list of fetch_multipart_data + * \param[out] encoded_out URL-encoded form data + * \return NSERROR_OK on success and \a encoded_out updated else appropriate error code */ - -static char *form_url_encode(struct form *form, +static nserror +form_url_encode(struct form *form, struct fetch_multipart_data *control, - bool query_string) + char **encoded_out) { char *name, *value; char *s, *s2; unsigned int len, len1, len_init; - nserror url_err; + nserror res; - if (query_string) - s = malloc(2); - else - s = malloc(1); + s = malloc(1); - if (s == NULL) - return NULL; - - if (query_string) { - s[0] = '?'; - s[1] = '\0'; - len_init = len = 1; - } else { - s[0] = '\0'; - len_init = len = 0; + if (s == NULL) { + return NSERROR_NOMEM; } + s[0] = '\0'; + len_init = len = 0; + for (; control; control = control->next) { - url_err = url_escape(control->name, true, NULL, &name); - if (url_err == NSERROR_NOMEM) { + res = url_escape(control->name, true, NULL, &name); + if (res != NSERROR_OK) { free(s); - return NULL; + return res; } - assert(url_err == NSERROR_OK); - - url_err = url_escape(control->value, true, NULL, &value); - if (url_err == NSERROR_NOMEM) { + res = url_escape(control->value, true, NULL, &value); + if (res != NSERROR_OK) { free(name); free(s); - return NULL; + return res; } - assert(url_err == NSERROR_OK); - /* resize string to allow for new key/value pair, * equals, amphersand and terminator */ len1 = len + strlen(name) + strlen(value) + 2; s2 = realloc(s, len1 + 1); - if (!s2) { + if (s2 == NULL) { free(value); free(name); free(s); - return NULL; + return NSERROR_NOMEM; } s = s2; @@ -995,7 +1007,10 @@ static char *form_url_encode(struct form *form, /* Replace trailing '&' */ s[len - 1] = '\0'; } - return s; + + *encoded_out = s; + + return NSERROR_OK; } /** @@ -1008,17 +1023,15 @@ char *form_acceptable_charset(struct form *form) { char *temp, *c; - if (!form) - return NULL; - if (!form->accept_charsets) { /* no accept-charsets attribute for this form */ - if (form->document_charset) + if (form->document_charset) { /* document charset present, so use it */ return strdup(form->document_charset); - else + } else { /* no document charset, so default to 8859-1 */ return strdup("ISO-8859-1"); + } } /* make temporary copy of accept-charsets attribute */ @@ -1768,98 +1781,85 @@ void form_radio_set(struct form_control *radio) } -/** - * Collect controls and submit a form. - */ - -void form_submit(nsurl *page_url, struct browser_window *target, - struct form *form, struct form_control *submit_button) +/* private interface described in html/form_internal.h */ +nserror +form_submit(nsurl *page_url, + struct browser_window *target, + struct form *form, + struct form_control *submit_button) { - char *data = NULL; - struct fetch_multipart_data *success; + nserror res; + char *data = NULL; /* encoded form data */ + struct fetch_multipart_data *success = NULL; /* gcc is incapable of correctly reasoning about use and generates "maybe used uninitialised" warnings */ nsurl *action_url; - nsurl *action_query; - nserror error; + nsurl *query_url; assert(form != NULL); - if (form_successful_controls_dom(form, submit_button, &success) == false) { - guit->misc->warning("NoMemory", 0); - return; + /* obtain list of controls from DOM */ + res = form_successful_controls_dom(form, submit_button, &success); + if (res != NSERROR_OK) { + return res; } /* Decompose action */ - if (nsurl_create(form->action, &action_url) != NSERROR_OK) { - free(data); + res = nsurl_create(form->action, &action_url); + if (res != NSERROR_OK) { fetch_multipart_data_destroy(success); - guit->misc->warning("NoMemory", 0); - return; + return res; } switch (form->method) { case method_GET: - data = form_url_encode(form, success, true); - if (data == NULL) { - fetch_multipart_data_destroy(success); - guit->misc->warning("NoMemory", 0); - return; - } - - /* Replace query segment */ - error = nsurl_replace_query(action_url, data, &action_query); - if (error != NSERROR_OK) { - nsurl_unref(action_query); + res = form_url_encode(form, success, &data); + if (res == NSERROR_OK) { + /* Replace query segment */ + res = nsurl_replace_query(action_url, data, &query_url); + if (res == NSERROR_OK) { + res = browser_window_navigate(target, + query_url, + page_url, + BW_NAVIGATE_HISTORY, + NULL, + NULL, + NULL); + + nsurl_unref(query_url); + } free(data); - fetch_multipart_data_destroy(success); - guit->misc->warning(messages_get_errorcode(error), 0); - return; } - - /* Construct submit url */ - browser_window_navigate(target, - action_query, - page_url, - BW_NAVIGATE_HISTORY, - NULL, - NULL, - NULL); - - nsurl_unref(action_query); break; case method_POST_URLENC: - data = form_url_encode(form, success, false); - if (data == NULL) { - fetch_multipart_data_destroy(success); - guit->misc->warning("NoMemory", 0); - nsurl_unref(action_url); - return; + res = form_url_encode(form, success, &data); + if (res == NSERROR_OK) { + res = browser_window_navigate(target, + action_url, + page_url, + BW_NAVIGATE_HISTORY, + data, + NULL, + NULL); + free(data); } - - browser_window_navigate(target, - action_url, - page_url, - BW_NAVIGATE_HISTORY, - data, - NULL, - NULL); break; case method_POST_MULTIPART: - browser_window_navigate(target, - action_url, - page_url, - BW_NAVIGATE_HISTORY, - NULL, - success, - NULL); + res = browser_window_navigate(target, + action_url, + page_url, + BW_NAVIGATE_HISTORY, + NULL, + success, + NULL); break; } nsurl_unref(action_url); fetch_multipart_data_destroy(success); - free(data); + + return res; } void form_gadget_update_value(struct form_control *control, char *value) diff --git a/content/handlers/html/form_internal.h b/content/handlers/html/form_internal.h index a77e823b3..f76f126b4 100644 --- a/content/handlers/html/form_internal.h +++ b/content/handlers/html/form_internal.h @@ -194,29 +194,6 @@ bool form_successful_controls(struct form *form, struct form_control *submit_button, struct fetch_multipart_data **successful_controls); -/** - * Identify 'successful' controls via the DOM. - * - * All text strings in the successful controls list will be in the charset most - * appropriate for submission. Therefore, no utf8_to_* processing should be - * performed upon them. - * - * \todo The chosen charset needs to be made available such that it can be - * included in the submission request (e.g. in the fetch's Content-Type header) - * - * See HTML 4.01 section 17.13.2. - * - * \param[in] form form to search for successful controls - * \param[in] submit_button control used to submit the form, if any - * \param[out] successful_controls updated to point to linked list of - * fetch_multipart_data, 0 if no controls - * \return true on success, false on memory exhaustion - */ -bool form_successful_controls_dom(struct form *form, - struct form_control *submit_button, - struct fetch_multipart_data **successful_controls); - - /** * Open a select menu for a select form control, creating it if necessary. * @@ -268,8 +245,18 @@ void form_select_mouse_drag_end(struct form_control *control, enum browser_mouse_state mouse, int x, int y); void form_select_get_dimensions(struct form_control *control, int *width, int *height); -void form_submit(struct nsurl *page_url, struct browser_window *target, + +/** + * navigate browser window based on form submission. + * + * \param page_url content url + * \param target The browsing context in which the navigation will occour. + * \param form The form to submit. + * \param submit_button The control used to submit the form. + */ +nserror form_submit(struct nsurl *page_url, struct browser_window *target, struct form *form, struct form_control *submit_button); + void form_radio_set(struct form_control *radio); void form_gadget_update_value(struct form_control *control, char *value); diff --git a/content/handlers/html/html_interaction.c b/content/handlers/html/html_interaction.c index 648d27467..04d14aa81 100644 --- a/content/handlers/html/html_interaction.c +++ b/content/handlers/html/html_interaction.c @@ -389,6 +389,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw, BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2 | BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2); + nserror res; + if (drag_type != DRAGGING_NONE && !mouse && html->visible_select_menu != NULL) { /* drag end: select menu */ @@ -875,9 +877,12 @@ void html_mouse_action(struct content *c, struct browser_window *bw, } } else if (url) { if (nsoption_bool(display_decoded_idn) == true) { - if (nsurl_get_utf8(url, &url_s, &url_l) != NSERROR_OK) { - /* Unable to obtain a decoded IDN. This is not a fatal error. - * Ensure the string pointer is NULL so we use the encoded version. */ + res = nsurl_get_utf8(url, &url_s, &url_l); + if (res != NSERROR_OK) { + /* Unable to obtain a decoded IDN. This is not + * a fatal error. Ensure the string pointer + * is NULL so we use the encoded version. + */ url_s = NULL; } } @@ -1072,22 +1077,32 @@ void html_mouse_action(struct content *c, struct browser_window *bw, */ switch (action) { case ACTION_SUBMIT: - form_submit(content_get_url(c), - browser_window_find_target(bw, target, mouse), - gadget->form, gadget); + res = form_submit(content_get_url(c), + browser_window_find_target(bw, target, mouse), + gadget->form, + gadget); break; + case ACTION_GO: - browser_window_navigate(browser_window_find_target(bw, target, mouse), - url, - content_get_url(c), - BW_NAVIGATE_HISTORY, - NULL, - NULL, - NULL); + res = browser_window_navigate( + browser_window_find_target(bw, target, mouse), + url, + content_get_url(c), + BW_NAVIGATE_HISTORY, + NULL, + NULL, + NULL); break; + case ACTION_NONE: + res = NSERROR_OK; break; } + + if (res != NSERROR_OK) { + guit->misc->warning(messages_get_errorcode(res), NULL); + } + } -- cgit v1.2.3