[project @ 2004-08-08 19:13:40 by bursa]
Fix form submitting with an empty file upload. Update form_textarea_value(). Purge xcalloc() etc from form.c and handle memory exhaustion. svn path=/import/netsurf/; revision=1195
This commit is contained in:
parent
94103b8c96
commit
8337acfc78
|
@ -1638,12 +1638,20 @@ void browser_form_submit(struct browser_window *bw, struct form *form,
|
||||||
assert(form);
|
assert(form);
|
||||||
assert(bw->current_content->type == CONTENT_HTML);
|
assert(bw->current_content->type == CONTENT_HTML);
|
||||||
|
|
||||||
success = form_successful_controls(form, submit_button);
|
if (!form_successful_controls(form, submit_button, &success)) {
|
||||||
|
warn_user("NoMemory", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
base = bw->current_content->data.html.base_url;
|
base = bw->current_content->data.html.base_url;
|
||||||
|
|
||||||
switch (form->method) {
|
switch (form->method) {
|
||||||
case method_GET:
|
case method_GET:
|
||||||
data = form_url_encode(success);
|
data = form_url_encode(success);
|
||||||
|
if (!data) {
|
||||||
|
form_free_successful(success);
|
||||||
|
warn_user("NoMemory", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
url = xcalloc(1, strlen(form->action) + strlen(data) + 2);
|
url = xcalloc(1, strlen(form->action) + strlen(data) + 2);
|
||||||
if(form->action[strlen(form->action)-1] == '?') {
|
if(form->action[strlen(form->action)-1] == '?') {
|
||||||
sprintf(url, "%s%s", form->action, data);
|
sprintf(url, "%s%s", form->action, data);
|
||||||
|
@ -1659,6 +1667,11 @@ void browser_form_submit(struct browser_window *bw, struct form *form,
|
||||||
|
|
||||||
case method_POST_URLENC:
|
case method_POST_URLENC:
|
||||||
data = form_url_encode(success);
|
data = form_url_encode(success);
|
||||||
|
if (!data) {
|
||||||
|
form_free_successful(success);
|
||||||
|
warn_user("NoMemory", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
url = url_join(form->action, base);
|
url = url_join(form->action, base);
|
||||||
if (!url)
|
if (!url)
|
||||||
break;
|
break;
|
||||||
|
|
232
render/form.c
232
render/form.c
|
@ -2,7 +2,7 @@
|
||||||
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
* This file is part of NetSurf, http://netsurf.sourceforge.net/
|
||||||
* Licensed under the GNU General Public License,
|
* Licensed under the GNU General Public License,
|
||||||
* http://www.opensource.org/licenses/gpl-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>
|
* Copyright 2003 Phil Mellor <monkeyson@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -100,23 +100,28 @@ void form_free_control(struct form_control *control)
|
||||||
/**
|
/**
|
||||||
* Identify 'successful' controls.
|
* 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.
|
* See HTML 4.01 section 17.13.2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct form_successful_control *form_successful_controls(struct form *form,
|
bool form_successful_controls(struct form *form,
|
||||||
struct form_control *submit_button)
|
struct form_control *submit_button,
|
||||||
|
struct form_successful_control **successful_controls)
|
||||||
{
|
{
|
||||||
struct form_control *control;
|
struct form_control *control;
|
||||||
struct form_option *option;
|
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;
|
last_success = &sentinel;
|
||||||
sentinel.next = 0;
|
sentinel.next = 0;
|
||||||
|
|
||||||
for (control = form->controls; control; control = control->next) {
|
for (control = form->controls; control; control = control->next) {
|
||||||
struct form_successful_control *success_new;
|
|
||||||
bool add_val;
|
|
||||||
|
|
||||||
/* ignore disabled controls */
|
/* ignore disabled controls */
|
||||||
if (control->disabled)
|
if (control->disabled)
|
||||||
continue;
|
continue;
|
||||||
|
@ -129,15 +134,20 @@ struct form_successful_control *form_successful_controls(struct form *form,
|
||||||
case GADGET_HIDDEN:
|
case GADGET_HIDDEN:
|
||||||
case GADGET_TEXTBOX:
|
case GADGET_TEXTBOX:
|
||||||
case GADGET_PASSWORD:
|
case GADGET_PASSWORD:
|
||||||
add_val = true;
|
value = strdup(control->value);
|
||||||
|
if (!value)
|
||||||
|
goto no_memory;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GADGET_RADIO:
|
case GADGET_RADIO:
|
||||||
case GADGET_CHECKBOX:
|
case GADGET_CHECKBOX:
|
||||||
/* ignore checkboxes and radio buttons which
|
/* ignore checkboxes and radio buttons which
|
||||||
* aren't selected
|
* aren't selected */
|
||||||
*/
|
if (!control->selected)
|
||||||
add_val = control->selected;
|
continue;
|
||||||
|
value = strdup(control->value);
|
||||||
|
if (!value)
|
||||||
|
goto no_memory;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GADGET_SELECT:
|
case GADGET_SELECT:
|
||||||
|
@ -145,31 +155,34 @@ struct form_successful_control *form_successful_controls(struct form *form,
|
||||||
for (option = control->data.select.items;
|
for (option = control->data.select.items;
|
||||||
option != NULL;
|
option != NULL;
|
||||||
option = option->next) {
|
option = option->next) {
|
||||||
if (option->selected) {
|
if (!option->selected)
|
||||||
success_new = xcalloc(1, sizeof(*success_new));
|
continue;
|
||||||
success_new->file = false;
|
success_new = malloc(sizeof(*success_new));
|
||||||
success_new->name = cnv_str_local_enc(control->name);
|
if (!success_new)
|
||||||
success_new->value = cnv_str_local_enc(option->value);
|
goto no_memory;
|
||||||
success_new->next = NULL;
|
success_new->file = false;
|
||||||
last_success->next = success_new;
|
success_new->name = strdup(control->name);
|
||||||
last_success = success_new;
|
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;
|
break;
|
||||||
|
|
||||||
case GADGET_TEXTAREA:
|
case GADGET_TEXTAREA:
|
||||||
/* textarea */
|
/* textarea */
|
||||||
success_new = xcalloc(1, sizeof(*success_new));
|
value = form_textarea_value(control);
|
||||||
success_new->file = false;
|
if (!value)
|
||||||
success_new->name = cnv_str_local_enc(control->name);
|
goto no_memory;
|
||||||
success_new->value = form_textarea_value(control);
|
if (value[0] == 0) {
|
||||||
success_new->next = 0;
|
free(value);
|
||||||
last_success->next = success_new;
|
continue;
|
||||||
last_success = success_new;
|
}
|
||||||
|
|
||||||
add_val = false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GADGET_IMAGE: {
|
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;
|
const size_t len = strlen(control->name) + 3;
|
||||||
|
|
||||||
/* x */
|
/* 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->file = false;
|
||||||
success_new->name = xcalloc(1, len);
|
success_new->name = malloc(len);
|
||||||
sprintf(success_new->name, "%s.x", control->name);
|
success_new->value = malloc(20);
|
||||||
success_new->value = xcalloc(1, 20);
|
if (!success_new->name ||
|
||||||
sprintf(success_new->value, "%i", control->data.image.mx);
|
!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;
|
success_new->next = 0;
|
||||||
last_success->next = success_new;
|
last_success->next = success_new;
|
||||||
last_success = success_new;
|
last_success = success_new;
|
||||||
|
|
||||||
/* y */
|
/* 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->file = false;
|
||||||
success_new->name = xcalloc(1, len);
|
success_new->name = malloc(len);
|
||||||
sprintf(success_new->name, "%s.y", control->name);
|
success_new->value = malloc(20);
|
||||||
success_new->value = xcalloc(1, 20);
|
if (!success_new->name ||
|
||||||
sprintf(success_new->value, "%i", control->data.image.my);
|
!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;
|
success_new->next = 0;
|
||||||
last_success->next = success_new;
|
last_success->next = success_new;
|
||||||
last_success = success_new;
|
last_success = success_new;
|
||||||
|
|
||||||
add_val = false;
|
continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GADGET_SUBMIT:
|
case GADGET_SUBMIT:
|
||||||
/* only the activated submit button is
|
/* only the activated submit button is
|
||||||
* successful
|
* successful */
|
||||||
*/
|
if (control != submit_button)
|
||||||
add_val = (control != submit_button) ? false : true;
|
continue;
|
||||||
|
value = strdup(control->value);
|
||||||
|
if (!value)
|
||||||
|
goto no_memory;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GADGET_RESET:
|
case GADGET_RESET:
|
||||||
/* ignore reset */
|
/* ignore reset */
|
||||||
add_val = false;
|
continue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GADGET_FILE:
|
case GADGET_FILE:
|
||||||
/* 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->file = true;
|
||||||
success_new->name = cnv_str_local_enc(control->name);
|
success_new->name = strdup(control->name);
|
||||||
success_new->value = cnv_str_local_enc(control->value);
|
success_new->value = strdup(control->value);
|
||||||
success_new->next = 0;
|
success_new->next = 0;
|
||||||
last_success->next = success_new;
|
last_success->next = success_new;
|
||||||
last_success = success_new;
|
last_success = success_new;
|
||||||
|
if (!success_new->name || !success_new->value)
|
||||||
|
goto no_memory;
|
||||||
|
|
||||||
add_val = false;
|
continue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -232,58 +276,65 @@ struct form_successful_control *form_successful_controls(struct form *form,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* all others added if they have a value */
|
success_new = malloc(sizeof(*success_new));
|
||||||
if (add_val && control->value != NULL) {
|
if (!success_new)
|
||||||
success_new = xcalloc(1, sizeof(*success_new));
|
goto no_memory;
|
||||||
success_new->file = false;
|
success_new->file = false;
|
||||||
success_new->name = cnv_str_local_enc(control->name);
|
success_new->name = strdup(control->name);
|
||||||
success_new->value = cnv_str_local_enc(control->value);
|
success_new->value = value;
|
||||||
success_new->next = NULL;
|
success_new->next = NULL;
|
||||||
last_success->next = success_new;
|
last_success->next = success_new;
|
||||||
last_success = 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.
|
* 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)
|
char *form_textarea_value(struct form_control *textarea)
|
||||||
{
|
{
|
||||||
unsigned int len = 1;
|
unsigned int len = 0;
|
||||||
char *value, *s;
|
char *value, *s;
|
||||||
struct box *inline_container, *text_box;
|
struct box *text_box;
|
||||||
|
|
||||||
/* find required length */
|
/* find required length */
|
||||||
for (inline_container = textarea->box->children;
|
for (text_box = textarea->box->children->children; text_box;
|
||||||
inline_container != NULL;
|
text_box = text_box->next) {
|
||||||
inline_container = inline_container->next) {
|
if (text_box->type == BOX_INLINE)
|
||||||
for (text_box = inline_container->children;
|
|
||||||
text_box != NULL;
|
|
||||||
text_box = text_box->next) {
|
|
||||||
len += text_box->length + 1;
|
len += text_box->length + 1;
|
||||||
}
|
else /* BOX_BR */
|
||||||
len += 2;
|
len += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* construct value */
|
/* construct value */
|
||||||
s = value = xcalloc(1, len);
|
s = value = malloc(len + 1);
|
||||||
for (inline_container = textarea->box->children;
|
if (!s)
|
||||||
inline_container != NULL;
|
return 0;
|
||||||
inline_container = inline_container->next) {
|
for (text_box = textarea->box->children->children; text_box;
|
||||||
for (text_box = inline_container->children;
|
text_box = text_box->next) {
|
||||||
text_box != NULL;
|
if (text_box->type == BOX_INLINE) {
|
||||||
text_box = text_box->next) {
|
|
||||||
strncpy(s, text_box->text, text_box->length);
|
strncpy(s, text_box->text, text_box->length);
|
||||||
s += text_box->length;
|
s += text_box->length;
|
||||||
*s++ = ' ';
|
*s++ = ' ';
|
||||||
|
} else { /* BOX_BR */
|
||||||
|
*s++ = '\r';
|
||||||
|
*s++ = '\n';
|
||||||
}
|
}
|
||||||
*s++ = '\r';
|
|
||||||
*s++ = '\n';
|
|
||||||
}
|
}
|
||||||
*s = 0;
|
*s = 0;
|
||||||
|
|
||||||
|
@ -293,18 +344,33 @@ char *form_textarea_value(struct form_control *textarea)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode controls using application/x-www-form-urlencoded.
|
* 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 *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;
|
unsigned int len = 0, len1;
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return 0;
|
||||||
|
s[0] = 0;
|
||||||
|
|
||||||
for (; control; control = control->next) {
|
for (; control; control = control->next) {
|
||||||
const char *name = curl_escape(control->name, 0);
|
name = curl_escape(control->name, 0);
|
||||||
const char *value = curl_escape(control->value, 0);
|
value = curl_escape(control->value, 0);
|
||||||
len1 = len + strlen(name) + strlen(value) + 2;
|
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);
|
sprintf(s + len, "%s=%s&", name, value);
|
||||||
len = len1;
|
len = len1;
|
||||||
curl_free(name);
|
curl_free(name);
|
||||||
|
|
|
@ -100,8 +100,9 @@ struct form_successful_control {
|
||||||
struct form_control *form_new_control(form_control_type type);
|
struct form_control *form_new_control(form_control_type type);
|
||||||
void form_add_control(struct form *form, struct form_control *control);
|
void form_add_control(struct form *form, struct form_control *control);
|
||||||
void form_free_control(struct form_control *control);
|
void form_free_control(struct form_control *control);
|
||||||
struct form_successful_control *form_successful_controls(struct form *form,
|
bool form_successful_controls(struct form *form,
|
||||||
struct form_control *submit_button);
|
struct form_control *submit_button,
|
||||||
|
struct form_successful_control **successful_controls);
|
||||||
char *form_url_encode(struct form_successful_control *control);
|
char *form_url_encode(struct form_successful_control *control);
|
||||||
void form_free_successful(struct form_successful_control *control);
|
void form_free_successful(struct form_successful_control *control);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue