diff options
author | Sebastian Geerken <devnull@localhost> | 2013-08-12 23:39:00 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2013-08-12 23:39:00 +0200 |
commit | 008da77a28dcd854a0f2442c1681b1a477558c2f (patch) | |
tree | 095f86b0ed587ebb6894df4457195af5fd515972 /src/html.cc | |
parent | a156ffb7873009f07b03efba257a0d8f99938e60 (diff) | |
parent | 24d2063654f6f229f520972b43c946741a909cf0 (diff) |
Merge with main repo.
Diffstat (limited to 'src/html.cc')
-rw-r--r-- | src/html.cc | 64 |
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; |