aboutsummaryrefslogtreecommitdiff
path: root/src/html.cc
diff options
context:
space:
mode:
authorSebastian Geerken <devnull@localhost>2013-08-12 23:39:00 +0200
committerSebastian Geerken <devnull@localhost>2013-08-12 23:39:00 +0200
commit008da77a28dcd854a0f2442c1681b1a477558c2f (patch)
tree095f86b0ed587ebb6894df4457195af5fd515972 /src/html.cc
parenta156ffb7873009f07b03efba257a0d8f99938e60 (diff)
parent24d2063654f6f229f520972b43c946741a909cf0 (diff)
Merge with main repo.
Diffstat (limited to 'src/html.cc')
-rw-r--r--src/html.cc64
1 files changed, 61 insertions, 3 deletions
diff --git a/src/html.cc b/src/html.cc
index 35f5bf02..47b02f71 100644
--- a/src/html.cc
+++ b/src/html.cc
@@ -1331,6 +1331,9 @@ static void Html_tag_cleanup_to_idx(DilloHtml *html, int idx)
*/
static void Html_tag_cleanup_at_close(DilloHtml *html, int new_idx)
{
+ static int i_BUTTON = a_Html_tag_index("button"),
+ i_SELECT = a_Html_tag_index("select"),
+ i_TEXTAREA = a_Html_tag_index("textarea");
int w3c_mode = !prefs.w3c_plus_heuristics;
int stack_idx, tag_idx, matched = 0, expected = 0;
TagInfo new_tag = Tags[new_idx];
@@ -1346,6 +1349,11 @@ static void Html_tag_cleanup_at_close(DilloHtml *html, int new_idx)
} else if (Tags[tag_idx].EndTag == 'O') {
/* skip an optional tag */
continue;
+ } else if ((new_idx == i_BUTTON && html->InFlags & IN_BUTTON) ||
+ (new_idx == i_SELECT && html->InFlags & IN_SELECT) ||
+ (new_idx == i_TEXTAREA && html->InFlags & IN_TEXTAREA)) {
+ /* let these elements close tags inside them */
+ continue;
} else if (w3c_mode || Tags[tag_idx].TagLevel >= new_tag.TagLevel) {
/* this is the tag that should have been closed */
expected = 1;
@@ -1364,6 +1372,50 @@ static void Html_tag_cleanup_at_close(DilloHtml *html, int new_idx)
}
/*
+ * Avoid nesting and inter-nesting of BUTTON, SELECT and TEXTAREA,
+ * by closing them before opening another.
+ * This is not an HTML SPEC restriction , but it avoids lots of trouble
+ * inside dillo (concurrent inputs), and makes almost no sense to have.
+ */
+static void Html_tag_cleanup_nested_inputs(DilloHtml *html, int new_idx)
+{
+ static int i_BUTTON = a_Html_tag_index("button"),
+ i_SELECT = a_Html_tag_index("select"),
+ i_TEXTAREA = a_Html_tag_index("textarea");
+ int stack_idx, u_idx, matched = 0;
+
+ dReturn_if_fail(html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA));
+ dReturn_if_fail(new_idx == i_BUTTON || new_idx == i_SELECT ||
+ new_idx == i_TEXTAREA);
+
+ /* Get the unclosed tag index */
+ u_idx = (html->InFlags & IN_BUTTON) ? i_BUTTON :
+ (html->InFlags & IN_SELECT) ? i_SELECT : i_TEXTAREA;
+
+ /* Look for it inside the stack */
+ stack_idx = html->stack->size();
+ while (--stack_idx) {
+ if (html->stack->getRef(stack_idx)->tag_idx == u_idx) {
+ /* matching tag found */
+ matched = 1;
+ break;
+ }
+ }
+
+ if (matched) {
+ BUG_MSG("attempt to nest <%s> element inside <%s> -- closing <%s>\n",
+ Tags[new_idx].name, Tags[u_idx].name, Tags[u_idx].name);
+ Html_tag_cleanup_to_idx(html, stack_idx);
+ } else {
+ MSG_WARN("Inconsistent parser state, flag is SET but no '%s' element"
+ "was found in the stack\n", Tags[u_idx].name);
+ }
+
+ html->InFlags &= ~(IN_BUTTON | IN_SELECT | IN_TEXTAREA);
+}
+
+
+/*
* Some parsing routines.
*/
@@ -3571,6 +3623,10 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
if ((html->InFlags & IN_PRE) && Html_tag_pre_excludes(ni))
BUG_MSG("<pre> is not allowed to contain <%s>\n", Tags[ni].name);
+ /* Make sure these elements don't nest each other */
+ if (html->InFlags & (IN_BUTTON | IN_SELECT | IN_TEXTAREA))
+ Html_tag_cleanup_nested_inputs(html, ni);
+
/* Push the tag into the stack */
Html_push_tag(html, ni);
@@ -3581,7 +3637,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
Html_parse_common_attrs(html, tag, tagsize);
/* Call the open function for this tag */
- _MSG("Open : %s\n", Tags[ni].name);
+ _MSG("Html_process_tag Open : %s\n", Tags[ni].name);
Tags[ni].open (html, tag, tagsize);
if (! S_TOP(html)->display_none) {
@@ -3609,7 +3665,9 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
if (html->stop_parser)
break;
- if (S_TOP(html)->parse_mode != DILLO_HTML_PARSE_MODE_PRE &&
+ if (S_TOP(html)->parse_mode == DILLO_HTML_PARSE_MODE_VERBATIM) {
+ /* don't change anything */
+ } else if (S_TOP(html)->parse_mode != DILLO_HTML_PARSE_MODE_PRE &&
(html->styleEngine->style ()->whiteSpace == WHITE_SPACE_PRE ||
html->styleEngine->style ()->whiteSpace == WHITE_SPACE_PRE_WRAP)) {
S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_PRE;
@@ -3638,7 +3696,7 @@ static void Html_process_tag(DilloHtml *html, char *tag, int tagsize)
(strchr(" \"'", tag[tagsize-3]) || /* [ "']/> */
(size_t)tagsize == strlen(Tags[ni].name) + 3))) { /* <x/> */
- _MSG("Close: %s\n", Tags[ni].name);
+ _MSG("Html_process_tag Close: %s\n", Tags[ni].name);
Html_tag_cleanup_at_close(html, ni);
/* This was a close tag */
html->ReqTagClose = false;