summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
Diffstat (limited to 'render')
-rw-r--r--render/form.c232
-rw-r--r--render/form.h5
2 files changed, 152 insertions, 85 deletions
diff --git a/render/form.c b/render/form.c
index 3713071e9..f2424849b 100644
--- a/render/form.c
+++ b/render/form.c
@@ -2,7 +2,7 @@
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
- * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
*/
@@ -100,23 +100,28 @@ void form_free_control(struct form_control *control)
/**
* Identify 'successful' controls.
*
+ * \param form form to search for successful controls
+ * \param submit_button control used to submit the form, if any
+ * \parma successful_controls updated to point to linked list of
+ * form_successful_control, 0 if no controls
+ * \return true on success, false on memory exhaustion
+ *
* See HTML 4.01 section 17.13.2.
*/
-struct form_successful_control *form_successful_controls(struct form *form,
- struct form_control *submit_button)
+bool form_successful_controls(struct form *form,
+ struct form_control *submit_button,
+ struct form_successful_control **successful_controls)
{
struct form_control *control;
struct form_option *option;
- struct form_successful_control sentinel, *last_success;
+ struct form_successful_control sentinel, *last_success, *success_new;
+ char *value;
last_success = &sentinel;
sentinel.next = 0;
for (control = form->controls; control; control = control->next) {
- struct form_successful_control *success_new;
- bool add_val;
-
/* ignore disabled controls */
if (control->disabled)
continue;
@@ -129,15 +134,20 @@ struct form_successful_control *form_successful_controls(struct form *form,
case GADGET_HIDDEN:
case GADGET_TEXTBOX:
case GADGET_PASSWORD:
- add_val = true;
+ value = strdup(control->value);
+ if (!value)
+ goto no_memory;
break;
case GADGET_RADIO:
case GADGET_CHECKBOX:
/* ignore checkboxes and radio buttons which
- * aren't selected
- */
- add_val = control->selected;
+ * aren't selected */
+ if (!control->selected)
+ continue;
+ value = strdup(control->value);
+ if (!value)
+ goto no_memory;
break;
case GADGET_SELECT:
@@ -145,31 +155,34 @@ struct form_successful_control *form_successful_controls(struct form *form,
for (option = control->data.select.items;
option != NULL;
option = option->next) {
- if (option->selected) {
- success_new = xcalloc(1, sizeof(*success_new));
- success_new->file = false;
- success_new->name = cnv_str_local_enc(control->name);
- success_new->value = cnv_str_local_enc(option->value);
- success_new->next = NULL;
- last_success->next = success_new;
- last_success = success_new;
- }
+ if (!option->selected)
+ continue;
+ success_new = malloc(sizeof(*success_new));
+ if (!success_new)
+ goto no_memory;
+ success_new->file = false;
+ success_new->name = strdup(control->name);
+ success_new->value = strdup(option->value);
+ success_new->next = NULL;
+ last_success->next = success_new;
+ last_success = success_new;
+ if (!success_new->name ||
+ !success_new->value)
+ goto no_memory;
}
- add_val = false;
+ continue;
break;
case GADGET_TEXTAREA:
/* textarea */
- success_new = xcalloc(1, sizeof(*success_new));
- success_new->file = false;
- success_new->name = cnv_str_local_enc(control->name);
- success_new->value = form_textarea_value(control);
- success_new->next = 0;
- last_success->next = success_new;
- last_success = success_new;
-
- add_val = false;
+ value = form_textarea_value(control);
+ if (!value)
+ goto no_memory;
+ if (value[0] == 0) {
+ free(value);
+ continue;
+ }
break;
case GADGET_IMAGE: {
@@ -177,54 +190,85 @@ struct form_successful_control *form_successful_controls(struct form *form,
const size_t len = strlen(control->name) + 3;
/* x */
- success_new = xcalloc(1, sizeof(*success_new));
+ success_new = malloc(sizeof(*success_new));
+ if (!success_new)
+ goto no_memory;
success_new->file = false;
- success_new->name = xcalloc(1, len);
- sprintf(success_new->name, "%s.x", control->name);
- success_new->value = xcalloc(1, 20);
- sprintf(success_new->value, "%i", control->data.image.mx);
+ success_new->name = malloc(len);
+ success_new->value = malloc(20);
+ if (!success_new->name ||
+ !success_new->value) {
+ free(success_new->name);
+ free(success_new->value);
+ free(success_new);
+ goto no_memory;
+ }
+ sprintf(success_new->name, "%s.x",
+ control->name);
+ sprintf(success_new->value, "%i",
+ control->data.image.mx);
success_new->next = 0;
last_success->next = success_new;
last_success = success_new;
/* y */
- success_new = xcalloc(1, sizeof(*success_new));
+ success_new = malloc(sizeof(*success_new));
+ if (!success_new)
+ goto no_memory;
success_new->file = false;
- success_new->name = xcalloc(1, len);
- sprintf(success_new->name, "%s.y", control->name);
- success_new->value = xcalloc(1, 20);
- sprintf(success_new->value, "%i", control->data.image.my);
+ success_new->name = malloc(len);
+ success_new->value = malloc(20);
+ if (!success_new->name ||
+ !success_new->value) {
+ free(success_new->name);
+ free(success_new->value);
+ free(success_new);
+ goto no_memory;
+ }
+ sprintf(success_new->name, "%s.y",
+ control->name);
+ sprintf(success_new->value, "%i",
+ control->data.image.my);
success_new->next = 0;
last_success->next = success_new;
last_success = success_new;
- add_val = false;
+ continue;
break;
}
case GADGET_SUBMIT:
/* only the activated submit button is
- * successful
- */
- add_val = (control != submit_button) ? false : true;
+ * successful */
+ if (control != submit_button)
+ continue;
+ value = strdup(control->value);
+ if (!value)
+ goto no_memory;
break;
case GADGET_RESET:
/* ignore reset */
- add_val = false;
+ continue;
break;
case GADGET_FILE:
/* file */
- success_new = xcalloc(1, sizeof(*success_new));
+ if (!control->value)
+ continue;
+ success_new = malloc(sizeof(*success_new));
+ if (!success_new)
+ goto no_memory;
success_new->file = true;
- success_new->name = cnv_str_local_enc(control->name);
- success_new->value = cnv_str_local_enc(control->value);
+ success_new->name = strdup(control->name);
+ success_new->value = strdup(control->value);
success_new->next = 0;
last_success->next = success_new;
last_success = success_new;
+ if (!success_new->name || !success_new->value)
+ goto no_memory;
- add_val = false;
+ continue;
break;
default:
@@ -232,58 +276,65 @@ struct form_successful_control *form_successful_controls(struct form *form,
break;
}
- /* all others added if they have a value */
- if (add_val && control->value != NULL) {
- success_new = xcalloc(1, sizeof(*success_new));
- success_new->file = false;
- success_new->name = cnv_str_local_enc(control->name);
- success_new->value = cnv_str_local_enc(control->value);
- success_new->next = NULL;
- last_success->next = success_new;
- last_success = success_new;
- }
+ success_new = malloc(sizeof(*success_new));
+ if (!success_new)
+ goto no_memory;
+ success_new->file = false;
+ success_new->name = strdup(control->name);
+ success_new->value = value;
+ success_new->next = NULL;
+ last_success->next = success_new;
+ last_success = success_new;
+ if (!success_new->name)
+ goto no_memory;
}
- return sentinel.next;
+ *successful_controls = sentinel.next;
+ return true;
+
+no_memory:
+ warn_user("NoMemory", 0);
+ form_free_successful(sentinel.next);
+ return false;
}
/**
* Find the value for a textarea control.
+ *
+ * \param textarea control of type GADGET_TEXTAREA
+ * \return the value as a UTF-8 string on heap, or 0 on memory exhaustion
*/
char *form_textarea_value(struct form_control *textarea)
{
- unsigned int len = 1;
+ unsigned int len = 0;
char *value, *s;
- struct box *inline_container, *text_box;
+ struct box *text_box;
/* find required length */
- for (inline_container = textarea->box->children;
- inline_container != NULL;
- inline_container = inline_container->next) {
- for (text_box = inline_container->children;
- text_box != NULL;
- text_box = text_box->next) {
+ for (text_box = textarea->box->children->children; text_box;
+ text_box = text_box->next) {
+ if (text_box->type == BOX_INLINE)
len += text_box->length + 1;
- }
- len += 2;
+ else /* BOX_BR */
+ len += 2;
}
/* construct value */
- s = value = xcalloc(1, len);
- for (inline_container = textarea->box->children;
- inline_container != NULL;
- inline_container = inline_container->next) {
- for (text_box = inline_container->children;
- text_box != NULL;
- text_box = text_box->next) {
+ s = value = malloc(len + 1);
+ if (!s)
+ return 0;
+ for (text_box = textarea->box->children->children; text_box;
+ text_box = text_box->next) {
+ if (text_box->type == BOX_INLINE) {
strncpy(s, text_box->text, text_box->length);
s += text_box->length;
*s++ = ' ';
+ } else { /* BOX_BR */
+ *s++ = '\r';
+ *s++ = '\n';
}
- *s++ = '\r';
- *s++ = '\n';
}
*s = 0;
@@ -293,18 +344,33 @@ char *form_textarea_value(struct form_control *textarea)
/**
* Encode controls using application/x-www-form-urlencoded.
+ *
+ * \param control linked list of form_successful_control
+ * \return URL-encoded form, or 0 on memory exhaustion
+ *
+ * \todo encoding conversion
*/
char *form_url_encode(struct form_successful_control *control)
{
- char *s = xcalloc(1, 0);
+ char *name, *value;
+ char *s = malloc(1), *s2;
unsigned int len = 0, len1;
+ if (!s)
+ return 0;
+ s[0] = 0;
+
for (; control; control = control->next) {
- const char *name = curl_escape(control->name, 0);
- const char *value = curl_escape(control->value, 0);
+ name = curl_escape(control->name, 0);
+ value = curl_escape(control->value, 0);
len1 = len + strlen(name) + strlen(value) + 2;
- s = xrealloc(s, len1 + 1);
+ s2 = realloc(s, len1 + 1);
+ if (!s2) {
+ free(s);
+ return 0;
+ }
+ s = s2;
sprintf(s + len, "%s=%s&", name, value);
len = len1;
curl_free(name);
diff --git a/render/form.h b/render/form.h
index e6f77aaa7..d0abd8e86 100644
--- a/render/form.h
+++ b/render/form.h
@@ -100,8 +100,9 @@ struct form_successful_control {
struct form_control *form_new_control(form_control_type type);
void form_add_control(struct form *form, struct form_control *control);
void form_free_control(struct form_control *control);
-struct form_successful_control *form_successful_controls(struct form *form,
- struct form_control *submit_button);
+bool form_successful_controls(struct form *form,
+ struct form_control *submit_button,
+ struct form_successful_control **successful_controls);
char *form_url_encode(struct form_successful_control *control);
void form_free_successful(struct form_successful_control *control);