summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/env.sh4
-rw-r--r--amiga/Makefile.target1
-rw-r--r--content/fetchers/curl.c1
-rw-r--r--desktop/save_complete.c2
-rw-r--r--render/form.c748
-rw-r--r--render/form.h8
-rw-r--r--render/html.c41
-rw-r--r--render/html_interaction.c60
-rw-r--r--render/html_object.c26
-rw-r--r--utils/corestrings.c39
-rw-r--r--utils/corestrings.h16
11 files changed, 633 insertions, 313 deletions
diff --git a/Docs/env.sh b/Docs/env.sh
index 27ae2e92d..7b5aedd1d 100644
--- a/Docs/env.sh
+++ b/Docs/env.sh
@@ -52,8 +52,8 @@ NS_BROWSER="netsurf"
# deb packages
NS_DEV_DEB="build-essential pkg-config git gperf"
-NS_TOOL_DEB="flex bison"
-NS_GTK_DEB="libgtk2.0-dev libcurl3-dev libpng-dev librsvg2-dev libjpeg-dev libmozjs-dev"
+NS_TOOL_DEB="flex bison libhtml-parser-perl"
+NS_GTK_DEB="libgtk2.0-dev libcurl3-dev libpng-dev librsvg2-dev libjpeg-dev libmozjs185-dev"
#add target specific libraries
if [ "x${TARGET_ABI}" = "xriscos" ]; then
diff --git a/amiga/Makefile.target b/amiga/Makefile.target
index b3220a142..7b04f3763 100644
--- a/amiga/Makefile.target
+++ b/amiga/Makefile.target
@@ -46,6 +46,7 @@ else
$(eval $(call pkg_config_find_and_add_enabled,PNG,libpng,PNG))
$(eval $(call pkg_config_find_and_add_enabled,NSSVG,libsvgtiny,NSSVG))
$(eval $(call pkg_config_find_and_add_enabled,AMIGA_CAIRO,cairo,Cairo))
+ $(eval $(call feature_enabled,MOZJS,-DXP_AMIGA -DWITH_MOZJS -DJS_VERSION=170 -DJSVERSION_LATEST=170 -DJSOPTION_JIT=0 -DJSCLASS_GLOBAL_FLAGS=0,-ljs,JavaScript))
$(eval $(call feature_enabled,AMIGA_ICON,-DWITH_AMIGA_ICON,,Amiga icon))
$(eval $(call feature_enabled,AMIGA_DATATYPES,-DWITH_AMIGA_DATATYPES,,DataTypes))
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index 1fada9d0a..7578ad4cb 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -1299,7 +1299,6 @@ fetch_curl_post_convert(const struct fetch_multipart_data *control)
code, control->name));
} else {
char *mimetype = fetch_mimetype(control->value);
- LOG(("XYZZY: Using rawfile of %s", control->rawfile));
code = curl_formadd(&post, &last,
CURLFORM_COPYNAME, control->name,
CURLFORM_FILE, control->rawfile,
diff --git a/desktop/save_complete.c b/desktop/save_complete.c
index 0c67654a6..efe223747 100644
--- a/desktop/save_complete.c
+++ b/desktop/save_complete.c
@@ -435,7 +435,7 @@ static bool save_complete_save_html_objects(save_complete_ctx *ctx,
object = html_get_objects(c, &count);
for (; object != NULL; object = object->next) {
- if (object->content != NULL) {
+ if (object->content != NULL || object->box != NULL) {
if (save_complete_save_html_object(ctx,
object->content) == false)
return false;
diff --git a/render/form.c b/render/form.c
index fe18e4336..761fc4c69 100644
--- a/render/form.c
+++ b/render/form.c
@@ -88,7 +88,7 @@ static plot_font_style_t plot_fstyle_entry = {
};
static char *form_acceptable_charset(struct form *form);
-static char *form_encode_item(const char *item, const char *charset,
+static char *form_encode_item(const char *item, uint32_t len, const char *charset,
const char *fallback);
static void form_select_menu_clicked(struct form_control *control,
int x, int y);
@@ -321,7 +321,7 @@ bool form_add_option(struct form_control *control, char *value, char *text,
/**
- * Identify '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
@@ -338,337 +338,498 @@ bool form_add_option(struct form_control *control, char *value, char *text,
*
* See HTML 4.01 section 17.13.2.
*/
-bool form_successful_controls(struct form *form,
- struct form_control *submit_button,
- struct fetch_multipart_data **successful_controls)
+bool form_successful_controls_dom(struct form *_form,
+ struct form_control *_submit_button,
+ struct fetch_multipart_data **successful_controls)
{
- struct form_control *control;
- struct form_option *option;
+ dom_html_form_element *form = _form->node;
+ dom_html_element *submit_button = (_submit_button != NULL) ? _submit_button->node : NULL;
+ dom_html_collection *form_elements = NULL;
+ dom_html_options_collection *options = NULL;
+ dom_node *form_element = NULL, *option_element = NULL;
+ dom_exception err;
+ dom_string *nodename = NULL, *inputname = NULL, *inputvalue = NULL, *inputtype = NULL;
struct fetch_multipart_data sentinel, *last_success, *success_new;
- char *value = NULL;
- bool had_submit = false;
- char *charset, *rawfile_temp;
+ bool had_submit = false, element_disabled;
+ char *charset, *rawfile_temp = NULL, *basename;
+ uint32_t index, element_count;
+ struct image_input_coords *coords;
last_success = &sentinel;
sentinel.next = NULL;
-
- charset = form_acceptable_charset(form);
- if (charset == NULL)
+
+ LOG(("XYZZY: Yay, let's look for a form"));
+
+ /** \todo Replace this call with something DOMish */
+ charset = form_acceptable_charset(_form);
+ if (charset == NULL) {
+ LOG(("failed to find charset"));
return false;
+ }
-#define ENCODE_ITEM(i) form_encode_item((i), charset, form->document_charset)
-
- for (control = form->controls; control; control = control->next) {
- /* ignore disabled controls */
- if (control->disabled)
+#define ENCODE_ITEM(i) (((i) == NULL) ? ( \
+ form_encode_item("", 0, charset, _form->document_charset) \
+ ):( \
+ form_encode_item(dom_string_data(i), dom_string_byte_length(i), \
+ charset, _form->document_charset) \
+ ))
+
+ err = dom_html_form_element_get_elements(form, &form_elements);
+
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get form elements"));
+ goto dom_no_memory;
+ }
+
+ LOG(("Reffed %p", form_elements));
+
+ err = dom_html_collection_get_length(form_elements, &element_count);
+
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get form element count"));
+ goto dom_no_memory;
+ }
+
+ for (index = 0; index < element_count; index++) {
+ if (form_element != NULL) {
+ LOG(("Unreffed %p", form_element));
+ dom_node_unref(form_element);
+ form_element = NULL;
+ }
+ if (nodename != NULL) {
+ dom_string_unref(nodename);
+ nodename = NULL;
+ }
+ if (inputname != NULL) {
+ dom_string_unref(inputname);
+ inputname = NULL;
+ }
+ if (inputvalue != NULL) {
+ dom_string_unref(inputvalue);
+ inputvalue = NULL;
+ }
+ if (inputtype != NULL) {
+ dom_string_unref(inputtype);
+ inputtype = NULL;
+ }
+ if (options != NULL) {
+ dom_html_options_collection_unref(options);
+ options = NULL;
+ }
+ err = dom_html_collection_item(form_elements,
+ index, &form_element);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not retrieve form element %d", index));
+ goto dom_no_memory;
+ }
+ LOG(("Reffed %p", form_element));
+ /* Form elements are one of:
+ * HTMLInputElement
+ * HTMLTextAreaElement
+ * HTMLSelectElement
+ */
+ err = dom_node_get_node_name(form_element, &nodename);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get node name"));
+ goto dom_no_memory;
+ }
+ LOG(("Found a node(%p): `%*s`", nodename,
+ dom_string_byte_length(nodename),
+ dom_string_data(nodename)));
+ if (dom_string_isequal(nodename, corestring_dom_TEXTAREA)) {
+ err = dom_html_text_area_element_get_disabled(
+ (dom_html_text_area_element *)form_element,
+ &element_disabled);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get text area disabled property"));
+ goto dom_no_memory;
+ }
+ err = dom_html_text_area_element_get_name(
+ (dom_html_text_area_element *)form_element,
+ &inputname);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get text area name property"));
+ goto dom_no_memory;
+ }
+ } else if (dom_string_isequal(nodename, corestring_dom_SELECT)) {
+ err = dom_html_select_element_get_disabled(
+ (dom_html_select_element *)form_element,
+ &element_disabled);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get select disabled property"));
+ goto dom_no_memory;
+ }
+ err = dom_html_select_element_get_name(
+ (dom_html_select_element *)form_element,
+ &inputname);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get select name property"));
+ goto dom_no_memory;
+ }
+ } else if (dom_string_isequal(nodename, corestring_dom_INPUT)) {
+ err = dom_html_input_element_get_disabled(
+ (dom_html_input_element *)form_element,
+ &element_disabled);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get input disabled property"));
+ goto dom_no_memory;
+ }
+ err = dom_html_input_element_get_name(
+ (dom_html_input_element *)form_element,
+ &inputname);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get input name property"));
+ goto dom_no_memory;
+ }
+ } else if (dom_string_isequal(nodename, corestring_dom_BUTTON)) {
+ /* It was a button, no fair */
continue;
-
- /* ignore controls with no name */
- if (!control->name)
+ } else {
+ /* Unknown element type came through! */
+ LOG(("Unknown element type: %*s",
+ dom_string_byte_length(nodename),
+ dom_string_data(nodename)));
+ goto dom_no_memory;
+ }
+ if (element_disabled)
continue;
-
- switch (control->type) {
- case GADGET_HIDDEN:
- if (control->value)
- value = ENCODE_ITEM(control->value);
- else
- value = ENCODE_ITEM("");
- if (!value) {
- LOG(("failed to duplicate value"
- "'%s' for control %s",
- control->value,
- control->name));
- goto no_memory;
+ if (inputname == NULL)
+ continue;
+
+ if (dom_string_isequal(nodename, corestring_dom_TEXTAREA)) {
+ err = dom_html_text_area_element_get_value(
+ (dom_html_text_area_element *)form_element,
+ &inputvalue);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get text area content"));
+ goto dom_no_memory;
+ }
+ } else if (dom_string_isequal(nodename, corestring_dom_SELECT)) {
+ uint32_t options_count, option_index;
+ err = dom_html_select_element_get_options(
+ (dom_html_select_element *)form_element,
+ &options);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get select options collection"));
+ goto dom_no_memory;
+ }
+ err = dom_html_options_collection_get_length(
+ options, &options_count);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get select options collection length"));
+ goto dom_no_memory;
+ }
+ for(option_index = 0; option_index < options_count;
+ ++option_index) {
+ bool selected;
+ if (option_element != NULL) {
+ dom_node_unref(option_element);
+ option_element = NULL;
}
- break;
-
- case GADGET_RADIO:
- case GADGET_CHECKBOX:
- /* ignore checkboxes and radio buttons which
- * aren't selected */
- if (!control->selected)
- continue;
- if (control->value)
- value = ENCODE_ITEM(control->value);
- else
- value = ENCODE_ITEM("on");
- if (!value) {
- LOG(("failed to duplicate"
- "value '%s' for"
- "control %s",
- control->value,
- control->name));
- goto no_memory;
+ if (inputvalue != NULL) {
+ dom_string_unref(inputvalue);
+ inputvalue = NULL;
}
- break;
-
- case GADGET_SELECT:
- /* select */
- for (option = control->data.select.items;
- option != NULL;
- option = option->next) {
- if (!option->selected)
- continue;
- success_new =
- malloc(sizeof(*success_new));
- if (!success_new) {
- LOG(("malloc failed"));
- goto no_memory;
- }
- success_new->file = false;
- success_new->name =
- ENCODE_ITEM(control->name);
- success_new->value =
- ENCODE_ITEM(option->value);
- success_new->next = NULL;
- last_success->next = success_new;
- last_success = success_new;
- if (!success_new->name ||
- !success_new->value) {
- LOG(("strdup failed"));
- goto no_memory;
- }
+ err = dom_html_options_collection_item(
+ options, option_index, &option_element);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get options item %d", option_index));
+ goto dom_no_memory;
}
-
- continue;
- break;
-
- case GADGET_TEXTBOX:
- case GADGET_PASSWORD:
- case GADGET_TEXTAREA:
- {
- char *v2;
- int ta_len = textarea_get_text(
- control->data.text.ta,
- NULL, 0);
-
- value = malloc(ta_len);
- if (!value) {
- LOG(("failed handling textarea"));
- goto no_memory;
+ err = dom_html_option_element_get_selected(
+ (dom_html_option_element *)option_element,
+ &selected);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get option selected property"));
+ goto dom_no_memory;
}
- textarea_get_text(control->data.text.ta,
- value, ta_len);
-
- if (control->type == GADGET_TEXTAREA &&
- value[0] == '\0') {
- /* Textarea not submitted if empty */
- free(value);
+ if (!selected)
continue;
+ err = dom_html_option_element_get_value(
+ (dom_html_option_element *)option_element,
+ &inputvalue);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get option value"));
+ goto dom_no_memory;
}
-
- v2 = ENCODE_ITEM(value);
- if (!v2) {
- LOG(("failed handling textarea"));
- free(value);
- goto no_memory;
- }
-
- free(value);
- value = v2;
- }
- break;
-
- case GADGET_IMAGE: {
- /* image */
- size_t len;
- char *name;
-
- if (control != submit_button)
- /* only the activated submit button
- * is successful */
- continue;
-
- name = ENCODE_ITEM(control->name);
- if (name == NULL)
- goto no_memory;
-
- len = strlen(name) + 3;
-
- /* x */
- success_new = malloc(sizeof(*success_new));
- if (!success_new) {
- free(name);
- LOG(("malloc failed"));
- goto no_memory;
+
+ success_new = calloc(1, sizeof(*success_new));
+ if (success_new == NULL) {
+ LOG(("Could not allocate data for option"));
+ goto dom_no_memory;
}
- success_new->file = false;
- 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);
- free(name);
- LOG(("malloc failed"));
- goto no_memory;
- }
- sprintf(success_new->name, "%s.x", 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 = malloc(sizeof(*success_new));
- if (!success_new) {
- free(name);
- LOG(("malloc failed"));
- goto no_memory;
+
+ success_new->name = ENCODE_ITEM(inputname);
+ if (success_new->name == NULL) {
+ LOG(("Could not encode name for option"));
+ goto dom_no_memory;
}
- success_new->file = false;
- 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);
- free(name);
- LOG(("malloc failed"));
- goto no_memory;
+ success_new->value = ENCODE_ITEM(inputvalue);
+ if (success_new->value == NULL) {
+ LOG(("Could not encode value for option"));
+ goto dom_no_memory;
}
- sprintf(success_new->name, "%s.y", name);
- sprintf(success_new->value, "%i",
- control->data.image.my);
- success_new->next = 0;
- last_success->next = success_new;
- last_success = success_new;
-
- free(name);
-
- continue;
- break;
}
-
- case GADGET_SUBMIT:
- if (!submit_button && !had_submit)
- /* no submit button specified, so
- * use first declared in form */
+ continue;
+ } else if (dom_string_isequal(nodename, corestring_dom_INPUT)) {
+ /* Things to consider here */
+ /* Buttons -- only if the successful control */
+ /* radio and checkbox -- only if selected */
+ /* file -- also get the rawfile */
+ /* everything else -- just value */
+ err = dom_html_input_element_get_type(
+ (dom_html_input_element *) form_element,
+ &inputtype);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get input element type"));
+ goto dom_no_memory;
+ }
+ if (dom_string_caseless_isequal(
+ inputtype, corestring_dom_submit)) {
+ LOG(("Examining submit button"));
+ if (submit_button == NULL && !had_submit)
+ /* no button used, and first submit
+ * node found, so use it
+ */
had_submit = true;
- else if (control != submit_button)
- /* only the activated submit button
- * is successful */
+ else if ((dom_node *)submit_button !=
+ (dom_node *)form_element)
continue;
- if (control->value)
- value = ENCODE_ITEM(control->value);
- else
- value = ENCODE_ITEM("");
- if (!value) {
- LOG(("failed to duplicate value"
- "'%s' for control %s",
- control->value,
- control->name));
- goto no_memory;
+ err = dom_html_input_element_get_value(
+ (dom_html_input_element *)form_element,
+ &inputvalue);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get submit button value"));
+ goto dom_no_memory;
}
- break;
-
- case GADGET_RESET:
- /* ignore reset */
- continue;
- break;
-
- case GADGET_FILE:
- /* file */
- /* Handling of blank file entries is
- * implementation defined - we're perfectly
- * within our rights to treat it as an
- * unsuccessful control. Unfortunately, every
- * other browser submits the field with
- * a blank filename and no content. So,
- * that's what we have to do, too.
+ /* Drop through to report the successful button */
+ } else if (dom_string_caseless_isequal(
+ inputtype, corestring_dom_image)) {
+ /* We *ONLY* use an image input if it was the
+ * thing which activated us
*/
- success_new = malloc(sizeof(*success_new));
- if (!success_new) {
- LOG(("malloc failed"));
- goto no_memory;
+ LOG(("Examining image button"));
+ if ((dom_node *)submit_button !=
+ (dom_node *)form_element)
+ continue;
+
+ err = dom_node_get_user_data(
+ form_element,
+ corestring_dom___ns_key_image_coords_node_data,
+ &coords);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get image XY data"));
+ goto dom_no_memory;
+ }
+ if (coords == NULL) {
+ LOG(("No XY data on the image input"));
+ goto dom_no_memory;
+ }
+
+ basename = ENCODE_ITEM(inputname);
+
+ success_new = calloc(1, sizeof(*success_new));
+ if (success_new == NULL) {
+ free(basename);
+ LOG(("Could not allocate data for image.x"));
+ goto dom_no_memory;
+ }
+
+ last_success->next = success_new;
+ last_success = success_new;
+
+ success_new->name = malloc(strlen(basename) + 3);
+ if (success_new->name == NULL) {
+ free(basename);
+ LOG(("Could not allocate name for image.x"));
+ goto dom_no_memory;
+ }
+ success_new->value = malloc(20);
+ if (success_new->value == NULL) {
+ free(basename);
+ LOG(("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));
+ if (success_new == NULL) {
+ free(basename);
+ LOG(("Could not allocate data for image.y"));
+ goto dom_no_memory;
+ }
+
+ last_success->next = success_new;
+ last_success = success_new;
+
+ success_new->name = malloc(strlen(basename) + 3);
+ if (success_new->name == NULL) {
+ free(basename);
+ LOG(("Could not allocate name for image.y"));
+ goto dom_no_memory;
+ }
+ success_new->value = malloc(20);
+ if (success_new->value == NULL) {
+ free(basename);
+ LOG(("Could not allocate value for image.y"));
+ goto dom_no_memory;
+ }
+ sprintf(success_new->name, "%s.y", basename);
+ sprintf(success_new->value, "%d", coords->y);
+ free(basename);
+ continue;
+ } else if (dom_string_caseless_isequal(
+ inputtype, corestring_dom_radio) ||
+ dom_string_caseless_isequal(
+ inputtype, corestring_dom_checkbox)) {
+ LOG(("Examining radio or checkbox"));
+ err = dom_html_input_element_get_value(
+ (dom_html_input_element *)form_element,
+ &inputvalue);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get input element value"));
+ goto dom_no_memory;
}
- success_new->file = true;
- success_new->name = ENCODE_ITEM(control->name);
- success_new->value =
- ENCODE_ITEM(control->value ?
- control->value : "");
- success_new->rawfile = NULL;
- /* Retrieve the filename from the DOM annotation */
- LOG(("XYZZY: Attempting to retrieve data"));
- if (dom_node_get_user_data(
- control->node,
- corestring_dom___ns_key_file_name_node_data,
- &rawfile_temp) != DOM_NO_ERR) {
- LOG(("XYZZY: unable to get rawfile"));
- goto no_memory;
+ if (inputvalue == NULL)
+ inputvalue = dom_string_ref(
+ corestring_dom_on);
+ /* Fall through to simple allocation */
+ } else if (dom_string_caseless_isequal(
+ inputtype, corestring_dom_file)) {
+ LOG(("Examining file input"));
+ err = dom_html_input_element_get_value(
+ (dom_html_input_element *)form_element,
+ &inputvalue);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get file value"));
+ goto dom_no_memory;
}
- LOG(("XYZZY: Got raw filename: %s", rawfile_temp));
- if (rawfile_temp == NULL) {
- /* No annotation means the file was not
- */
- success_new->rawfile = strdup("");
- } else {
- success_new->rawfile = strdup(rawfile_temp);
- }
-
- if (success_new->rawfile == NULL) {
- LOG(("strdup failed"));
- goto no_memory;
+ err = dom_node_get_user_data(
+ form_element,
+ corestring_dom___ns_key_file_name_node_data,
+ &rawfile_temp);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get file rawname"));
+ goto dom_no_memory;
}
-
- success_new->next = 0;
- last_success->next = success_new;
- last_success = success_new;
- if (!success_new->name ||
- !success_new->value) {
- LOG(("strdup failed"));
- goto no_memory;
+ rawfile_temp = strdup(rawfile_temp != NULL ?
+ rawfile_temp :
+ "");
+ if (rawfile_temp == NULL) {
+ LOG(("Could not copy file rawname"));
+ goto dom_no_memory;
}
-
- continue;
- break;
-
- case GADGET_BUTTON:
- /* Ignore it */
+ /* Fall out to the allocation */
+ } else if (dom_string_caseless_isequal(
+ inputtype, corestring_dom_reset) ||
+ dom_string_caseless_isequal(
+ inputtype, corestring_dom_button)) {
+ /* Skip these */
+ LOG(("Skipping RESET and BUTTON"));
continue;
- break;
-
- default:
- assert(0);
- break;
+ } else {
+ /* Everything else is treated as text values */
+ LOG(("Retrieving generic input text"));
+ err = dom_html_input_element_get_value(
+ (dom_html_input_element *)form_element,
+ &inputvalue);
+ if (err != DOM_NO_ERR) {
+ LOG(("Could not get input value"));
+ goto dom_no_memory;
+ }
+ /* Fall out to the allocation */
+ }
}
-
- success_new = malloc(sizeof(*success_new));
- if (!success_new) {
- LOG(("malloc failed"));
- free(value);
- goto no_memory;
+
+ success_new = calloc(1, sizeof(*success_new));
+ if (success_new == NULL) {
+ LOG(("Could not allocate data for generic"));
+ goto dom_no_memory;
}
- success_new->file = false;
- success_new->name = ENCODE_ITEM(control->name);
- success_new->value = value;
- success_new->next = NULL;
+
last_success->next = success_new;
last_success = success_new;
- if (!success_new->name) {
- LOG(("failed to duplicate name '%s'",
- control->name));
- goto no_memory;
+
+ success_new->name = ENCODE_ITEM(inputname);
+ if (success_new->name == NULL) {
+ LOG(("Could not encode name for generic"));
+ goto dom_no_memory;
+ }
+ success_new->value = ENCODE_ITEM(inputvalue);
+ if (success_new->value == NULL) {
+ LOG(("Could not encode value for generic"));
+ goto dom_no_memory;
+ }
+ if (rawfile_temp != NULL) {
+ success_new->file = true;
+ success_new->rawfile = rawfile_temp;
+ rawfile_temp = NULL;
}
}
-
+
free(charset);
-
+ if (form_element != NULL) {
+ LOG(("Unreffed %p", form_element));
+ dom_node_unref(form_element);
+ }
+ if (form_elements != NULL) {
+ LOG(("Unreffed %p", form_elements));
+ dom_html_collection_unref(form_elements);
+ }
+ if (nodename != NULL)
+ dom_string_unref(nodename);
+ if (inputname != NULL)
+ dom_string_unref(inputname);
+ if (inputvalue != NULL)
+ dom_string_unref(inputvalue);
+ if (options != NULL)
+ dom_html_options_collection_unref(options);
+ if (option_element != NULL)
+ dom_node_unref(option_element);
+ if (inputtype != NULL)
+ dom_string_unref(inputtype);
+ if (rawfile_temp != NULL)
+ free(rawfile_temp);
*successful_controls = sentinel.next;
+
+ for (success_new = *successful_controls; success_new != NULL;
+ success_new = success_new->next) {
+ LOG(("%p -> %s=%s", success_new, success_new->name, success_new->value));
+ LOG(("%p -> file=%s rawfile=%s", success_new,
+ success_new->file ? "yes" : "no", success_new->rawfile));
+ }
return true;
-
-no_memory:
- warn_user("NoMemory", 0);
+
+dom_no_memory:
free(charset);
fetch_multipart_data_destroy(sentinel.next);
+
+ if (form_elements != NULL)
+ dom_html_collection_unref(form_elements);
+ if (form_element != NULL)
+ dom_node_unref(form_element);
+ if (nodename != NULL)
+ dom_string_unref(nodename);
+ if (inputname != NULL)
+ dom_string_unref(inputname);
+ if (inputvalue != NULL)
+ dom_string_unref(inputvalue);
+ if (options != NULL)
+ dom_html_options_collection_unref(options);
+ if (option_element != NULL)
+ dom_node_unref(option_element);
+ if (inputtype != NULL)
+ dom_string_unref(inputtype);
+ if (rawfile_temp != NULL)
+ free(rawfile_temp);
+
return false;
-
-#undef ENCODE_ITEM
}
-
+#undef ENCODE_ITEM
/**
* Encode controls using application/x-www-form-urlencoded.
@@ -813,12 +974,13 @@ char *form_acceptable_charset(struct form *form)
* \todo Return charset used?
*
* \param item String to convert
+ * \param len Length of string to convert
* \param charset Destination charset
* \param fallback Fallback charset (may be NULL),
* used iff converting to charset fails
* \return Pointer to converted string (on heap, caller frees), or NULL
*/
-char *form_encode_item(const char *item, const char *charset,
+char *form_encode_item(const char *item, uint32_t len, const char *charset,
const char *fallback)
{
utf8_convert_ret err;
@@ -834,7 +996,7 @@ char *form_encode_item(const char *item, const char *charset,
if (err == UTF8_CONVERT_BADENC) {
/* charset not understood, try without transliteration */
snprintf(cset, sizeof cset, "%s", charset);
- err = utf8_to_enc(item, cset, 0, &ret);
+ err = utf8_to_enc(item, cset, len, &ret);
if (err == UTF8_CONVERT_BADENC) {
/* nope, try fallback charset (if any) */
@@ -1491,7 +1653,7 @@ void form_submit(nsurl *page_url, struct browser_window *target,
assert(form != NULL);
- if (form_successful_controls(form, submit_button, &success) == false) {
+ if (form_successful_controls_dom(form, submit_button, &success) == false) {
warn_user("NoMemory", 0);
return;
}
diff --git a/render/form.h b/render/form.h
index b538c3b33..78211ee19 100644
--- a/render/form.h
+++ b/render/form.h
@@ -134,6 +134,11 @@ struct form_option {
struct form_option* next;
};
+struct image_input_coords {
+ int x;
+ int y;
+};
+
/**
* Called by the select menu when it wants an area to be redrawn. The
* coordinates are menu origin relative.
@@ -159,6 +164,9 @@ bool form_add_option(struct form_control *control, char *value, char *text,
bool form_successful_controls(struct form *form,
struct form_control *submit_button,
struct fetch_multipart_data **successful_controls);
+bool form_successful_controls_dom(struct form *form,
+ struct form_control *submit_button,
+ struct fetch_multipart_data **successful_controls);
bool form_open_select_menu(void *client_data,
struct form_control *control,
diff --git a/render/html.c b/render/html.c
index 103dec14f..e10f1e930 100644
--- a/render/html.c
+++ b/render/html.c
@@ -507,6 +507,37 @@ static nserror html_meta_refresh_process_element(html_content *c, dom_node *n)
return error;
}
+static bool html_process_img(html_content *c, dom_node *node)
+{
+ dom_string *src;
+ nsurl *url;
+ nserror err;
+ dom_exception exc;
+ bool success;
+
+ /* Do nothing if foreground images are disabled */
+ if (nsoption_bool(foreground_images) == false) {
+ return true;
+ }
+
+ exc = dom_element_get_attribute(node, corestring_dom_src, &src);
+ if (exc != DOM_NO_ERR || src == NULL) {
+ return true;
+ }
+
+ err = nsurl_join(c->base_url, dom_string_data(src), &url);
+ if (err != NSERROR_OK) {
+ dom_string_unref(src);
+ return false;
+ }
+ dom_string_unref(src);
+
+ /* Speculatively fetch the image */
+ success = html_fetch_object(c, url, NULL, CONTENT_IMAGE, 0, 0, false);
+ nsurl_unref(url);
+
+ return success;
+}
/**
* Complete conversion of an HTML document
@@ -608,6 +639,10 @@ dom_default_action_DOMNodeInserted_cb(struct dom_event *evt, void *pw)
name, corestring_lwc_title) &&
htmlc->title == NULL) {
htmlc->title = dom_node_ref(node);
+ } else if (dom_string_caseless_lwc_isequal(
+ name, corestring_lwc_img)) {
+ html_process_img(htmlc,
+ (dom_node *) node);
}
dom_string_unref(name);
@@ -1697,14 +1732,13 @@ static void html__dom_user_data_handler(dom_node_operation operation,
char *oldfile;
char *data = (char *)_data;
- if (!dom_string_isequal(corestring_dom___ns_key_libcss_node_data,
+ if (!dom_string_isequal(corestring_dom___ns_key_file_name_node_data,
key) || data == NULL) {
return;
}
switch (operation) {
case DOM_NODE_CLONED:
- LOG(("XYZZY: Cloned, so copying to the new location"));
if (dom_node_set_user_data(dst,
corestring_dom___ns_key_file_name_node_data,
strdup(data), html__dom_user_data_handler,
@@ -1720,7 +1754,6 @@ static void html__dom_user_data_handler(dom_node_operation operation,
break;
case DOM_NODE_DELETED:
- LOG(("XYZZY: Freeing data due to node deletion"));
free(data);
break;
default:
@@ -1748,12 +1781,10 @@ static void html__set_file_gadget_filename(struct content *c,
form_gadget_update_value(html, gadget, utf8_fn);
/* corestring_dom___ns_key_file_name_node_data */
- LOG(("XYZZY: Setting userdata to %s", fn));
if (dom_node_set_user_data((dom_node *)file_box->gadget->node,
corestring_dom___ns_key_file_name_node_data,
strdup(fn), html__dom_user_data_handler,
&oldfile) == DOM_NO_ERR) {
- LOG(("XYZZY: Userdata used to be %s", oldfile));
if (oldfile != NULL)
free(oldfile);
}
diff --git a/render/html_interaction.c b/render/html_interaction.c
index b04d42586..84c64ca20 100644
--- a/render/html_interaction.c
+++ b/render/html_interaction.c
@@ -45,8 +45,10 @@
#include "render/imagemap.h"
#include "render/search.h"
#include "javascript/js.h"
+#include "utils/corestrings.h"
#include "utils/messages.h"
#include "utils/utils.h"
+#include "utils/log.h"
/**
@@ -228,6 +230,47 @@ void html_mouse_track(struct content *c, struct browser_window *bw,
html_mouse_action(c, bw, mouse, x, y);
}
+/** Helper for file gadgets to store their filename unencoded on the
+ * dom node associated with the gadget.
+ *
+ * \todo Get rid of this crap eventually
+ */
+static void html__image_coords_dom_user_data_handler(dom_node_operation operation,
+ dom_string *key, void *_data, struct dom_node *src,
+ struct dom_node *dst)
+{
+ struct image_input_coords *oldcoords, *coords = _data, *newcoords;
+
+ if (!dom_string_isequal(corestring_dom___ns_key_image_coords_node_data,
+ key) || coords == NULL) {
+ return;
+ }
+
+ switch (operation) {
+ case DOM_NODE_CLONED:
+ newcoords = calloc(1, sizeof(*newcoords));
+ *newcoords = *coords;
+ if (dom_node_set_user_data(dst,
+ corestring_dom___ns_key_image_coords_node_data,
+ newcoords, html__image_coords_dom_user_data_handler,
+ &oldcoords) == DOM_NO_ERR) {
+ free(oldcoords);
+ }
+ break;
+
+ case DOM_NODE_RENAMED:
+ case DOM_NODE_IMPORTED:
+ case DOM_NODE_ADOPTED:
+ break;
+
+ case DOM_NODE_DELETED:
+ free(coords);
+ break;
+ default:
+ LOG(("User data operation not handled."));
+ assert(0);
+ }
+}
/**
* Handle mouse clicks and movements in an HTML content window.
@@ -630,8 +673,21 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
break;
case GADGET_IMAGE:
if (mouse & BROWSER_MOUSE_CLICK_1) {
- gadget->data.image.mx = x - gadget_box_x;
- gadget->data.image.my = y - gadget_box_y;
+ struct image_input_coords *coords, *oldcoords;
+ /** \todo Find a way to not ignore errors */
+ coords = calloc(1, sizeof(*coords));
+ if (coords == NULL) {
+ return;
+ }
+ coords->x = x - gadget_box_x;
+ coords->y = y - gadget_box_y;
+ if (dom_node_set_user_data(
+ gadget->node,
+ corestring_dom___ns_key_image_coords_node_data,
+ coords, html__image_coords_dom_user_data_handler,
+ &oldcoords) != DOM_NO_ERR)
+ return;
+ free(oldcoords);
}
/* drop through */
case GADGET_SUBMIT:
diff --git a/render/html_object.c b/render/html_object.c
index 15ca7ed3b..e76919dd4 100644
--- a/render/html_object.c
+++ b/render/html_object.c
@@ -123,6 +123,9 @@ html_object_callback(hlcache_handle *object,
assert(c->base.status != CONTENT_STATUS_ERROR);
box = o->box;
+ if (box == NULL && event->type != CONTENT_MSG_ERROR) {
+ return NSERROR_OK;
+ }
switch (event->type) {
case CONTENT_MSG_LOADING:
@@ -181,11 +184,13 @@ html_object_callback(hlcache_handle *object,
o->content = NULL;
- c->base.active--;
- LOG(("%d fetches active", c->base.active));
+ if (box != NULL) {
+ c->base.active--;
+ LOG(("%d fetches active", c->base.active));
- content_add_error(&c->base, "?", 0);
- html_object_failed(box, c, o->background);
+ content_add_error(&c->base, "?", 0);
+ html_object_failed(box, c, o->background);
+ }
break;
case CONTENT_MSG_STATUS:
@@ -461,7 +466,7 @@ html_object_callback(hlcache_handle *object,
* then reformat the page to display newly fetched objects */
else if (nsoption_bool(incremental_reflow) &&
event->type == CONTENT_MSG_DONE &&
- !(box->flags & REPLACE_DIM) &&
+ box != NULL && !(box->flags & REPLACE_DIM) &&
(c->base.status == CONTENT_STATUS_READY ||
c->base.status == CONTENT_STATUS_DONE) &&
(wallclock() > c->base.reformat_time)) {
@@ -488,6 +493,7 @@ static bool html_replace_object(struct content_html_object *object, nsurl *url)
nserror error;
assert(object != NULL);
+ assert(object->box != NULL);
c = (html_content *) object->parent;
@@ -559,7 +565,7 @@ nserror html_object_open_objects(html_content *html, struct browser_window *bw)
for (object = html->object_list; object != NULL; object = next) {
next = object->next;
- if (object->content == NULL)
+ if (object->content == NULL || object->box == NULL)
continue;
if (content_get_type(object->content) == CONTENT_NONE)
@@ -618,7 +624,7 @@ nserror html_object_close_objects(html_content *html)
for (object = html->object_list; object != NULL; object = next) {
next = object->next;
- if (object->content == NULL)
+ if (object->content == NULL || object->box == NULL)
continue;
if (content_get_type(object->content) == CONTENT_NONE)
@@ -698,8 +704,10 @@ bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
c->object_list = object;
c->num_objects++;
- c->base.active++;
- LOG(("%d fetches active", c->base.active));
+ if (box != NULL) {
+ c->base.active++;
+ LOG(("%d fetches active", c->base.active));
+ }
return true;
}
diff --git a/utils/corestrings.c b/utils/corestrings.c
index 8623d127b..e60a75bdc 100644
--- a/utils/corestrings.c
+++ b/utils/corestrings.c
@@ -232,8 +232,19 @@ dom_string *corestring_dom_volumechange;
dom_string *corestring_dom_vspace;
dom_string *corestring_dom_waiting;
dom_string *corestring_dom_width;
+dom_string *corestring_dom_BUTTON;
+dom_string *corestring_dom_INPUT;
+dom_string *corestring_dom_SELECT;
+dom_string *corestring_dom_TEXTAREA;
+dom_string *corestring_dom_button;
+dom_string *corestring_dom_image;
+dom_string *corestring_dom_radio;
+dom_string *corestring_dom_checkbox;
+dom_string *corestring_dom_file;
+dom_string *corestring_dom_on;
dom_string *corestring_dom___ns_key_libcss_node_data;
dom_string *corestring_dom___ns_key_file_name_node_data;
+dom_string *corestring_dom___ns_key_image_coords_node_data;
/*
* Free the core strings
@@ -463,8 +474,22 @@ void corestrings_fini(void)
CSS_DOM_STRING_UNREF(vspace);
CSS_DOM_STRING_UNREF(waiting);
CSS_DOM_STRING_UNREF(width);
+ /* DOM node names, not really CSS */
+ CSS_DOM_STRING_UNREF(BUTTON);
+ CSS_DOM_STRING_UNREF(INPUT);
+ CSS_DOM_STRING_UNREF(SELECT);
+ CSS_DOM_STRING_UNREF(TEXTAREA);
+ /* DOM input types, not really CSS */
+ CSS_DOM_STRING_UNREF(button);
+ CSS_DOM_STRING_UNREF(image);
+ CSS_DOM_STRING_UNREF(radio);
+ CSS_DOM_STRING_UNREF(checkbox);
+ CSS_DOM_STRING_UNREF(file);
+ CSS_DOM_STRING_UNREF(on);
+ /* DOM userdata keys, not really CSS */
CSS_DOM_STRING_UNREF(__ns_key_libcss_node_data);
CSS_DOM_STRING_UNREF(__ns_key_file_name_node_data);
+ CSS_DOM_STRING_UNREF(__ns_key_image_coords_node_data);
#undef CSS_DOM_STRING_UNREF
}
@@ -725,8 +750,22 @@ nserror corestrings_init(void)
CSS_DOM_STRING_INTERN(vspace);
CSS_DOM_STRING_INTERN(waiting);
CSS_DOM_STRING_INTERN(width);
+ /* DOM node names, not really CSS */
+ CSS_DOM_STRING_INTERN(BUTTON);
+ CSS_DOM_STRING_INTERN(INPUT);
+ CSS_DOM_STRING_INTERN(SELECT);
+ CSS_DOM_STRING_INTERN(TEXTAREA);
+ /* DOM input types, not really CSS */
+ CSS_DOM_STRING_INTERN(button);
+ CSS_DOM_STRING_INTERN(image);
+ CSS_DOM_STRING_INTERN(radio);
+ CSS_DOM_STRING_INTERN(checkbox);
+ CSS_DOM_STRING_INTERN(file);
+ CSS_DOM_STRING_INTERN(on);
+ /* DOM userdata keys, not really CSS */
CSS_DOM_STRING_INTERN(__ns_key_libcss_node_data);
CSS_DOM_STRING_INTERN(__ns_key_file_name_node_data);
+ CSS_DOM_STRING_INTERN(__ns_key_image_coords_node_data);
#undef CSS_DOM_STRING_INTERN
exc = dom_string_create_interned((const uint8_t *) "text/javascript",
diff --git a/utils/corestrings.h b/utils/corestrings.h
index a8c345946..90fef5aaa 100644
--- a/utils/corestrings.h
+++ b/utils/corestrings.h
@@ -238,8 +238,24 @@ extern struct dom_string *corestring_dom_volumechange;
extern struct dom_string *corestring_dom_vspace;
extern struct dom_string *corestring_dom_waiting;
extern struct dom_string *corestring_dom_width;
+/* DOM node types */
+extern struct dom_string *corestring_dom_BUTTON;
+extern struct dom_string *corestring_dom_INPUT;
+extern struct dom_string *corestring_dom_SELECT;
+extern struct dom_string *corestring_dom_TEXTAREA;
+/* DOM input node types */
+extern struct dom_string *corestring_dom_button;
+/* extern struct dom_string *corestring_dom_submit; */
+/* extern struct dom_string *corestring_dom_reset; */
+extern struct dom_string *corestring_dom_image;
+extern struct dom_string *corestring_dom_radio;
+extern struct dom_string *corestring_dom_checkbox;
+extern struct dom_string *corestring_dom_file;
+extern struct dom_string *corestring_dom_on;
+/* DOM userdata keys */
extern struct dom_string *corestring_dom___ns_key_libcss_node_data;
extern struct dom_string *corestring_dom___ns_key_file_name_node_data;
+extern struct dom_string *corestring_dom___ns_key_image_coords_node_data;
#endif