Hubbub
in_table.c
Go to the documentation of this file.
1 /*
2  * This file is part of Hubbub.
3  * Licensed under the MIT License,
4  * http://www.opensource.org/licenses/mit-license.php
5  * Copyright 2008 Andrew Sidwell <takkaria@netsurf-browser.org>
6  */
7 
8 #include <assert.h>
9 #include <string.h>
10 
11 #include "treebuilder/modes.h"
12 #include "treebuilder/internal.h"
14 #include "utils/utils.h"
15 #include "utils/string.h"
16 
17 
23 static inline void clear_stack_table_context(hubbub_treebuilder *treebuilder)
24 {
25  hubbub_ns ns;
26  element_type type = current_node(treebuilder);
27  void *node;
28 
29  while (type != TABLE && type != HTML) {
30  element_stack_pop(treebuilder, &ns, &type, &node);
31 
32  treebuilder->tree_handler->unref_node(
33  treebuilder->tree_handler->ctx,
34  node);
35 
36  type = current_node(treebuilder);
37  }
38 }
39 
40 
45  hubbub_treebuilder *treebuilder,
46  const hubbub_token *token)
47 {
49  size_t i;
50 
51  for (i = 0; i < token->data.tag.n_attributes; i++) {
52  hubbub_attribute *attr = &token->data.tag.attributes[i];
53 
54  if (!hubbub_string_match_ci(attr->value.ptr, attr->value.len,
55  (uint8_t *) "hidden", SLEN("hidden"))) {
56  continue;
57  }
58 
60  err = insert_element(treebuilder, &token->data.tag, true);
61  }
62 
63  return err;
64 }
65 
66 
75  const hubbub_token *token)
76 {
77  hubbub_error err = HUBBUB_OK;
78  bool handled = true;
79 
80  switch (token->type) {
82  if (treebuilder->context.element_stack[
83  current_table(treebuilder)
84  ].tainted) {
85  handled = false;
86  } else {
88  treebuilder, token, true);
89  handled = (err == HUBBUB_OK);
90  }
91  break;
93  err = process_comment_append(treebuilder, token,
94  treebuilder->context.element_stack[
95  treebuilder->context.current_node].node);
96  break;
99  break;
101  {
103  &token->data.tag.name);
104  bool tainted = treebuilder->context.element_stack[
105  current_table(treebuilder)
106  ].tainted;
107 
108  if (type == CAPTION) {
109  clear_stack_table_context(treebuilder);
110 
111  treebuilder->tree_handler->ref_node(
112  treebuilder->tree_handler->ctx,
113  treebuilder->context.element_stack[
114  treebuilder->context.current_node].node);
115 
116  err = formatting_list_append(treebuilder,
117  token->data.tag.ns, type,
118  treebuilder->context.element_stack[
119  treebuilder->context.current_node].node,
120  treebuilder->context.current_node);
121  if (err != HUBBUB_OK) {
122  treebuilder->tree_handler->unref_node(
123  treebuilder->tree_handler->ctx,
124  treebuilder->context.element_stack[
125  treebuilder->context.current_node].node);
126 
127  return err;
128  }
129 
130  err = insert_element(treebuilder, &token->data.tag,
131  true);
132  if (err != HUBBUB_OK) {
133  hubbub_ns ns;
135  void *node;
136  uint32_t index;
137 
138  formatting_list_remove(treebuilder,
139  treebuilder->context.formatting_list_end,
140  &ns, &type, &node, &index);
141 
142  treebuilder->tree_handler->unref_node(
143  treebuilder->tree_handler->ctx,
144  node);
145 
146  return err;
147  }
148 
149  treebuilder->context.mode = IN_CAPTION;
150  } else if (type == COLGROUP || type == COL) {
151  hubbub_error e;
152  hubbub_tag tag = token->data.tag;
153 
154  if (type == COL) {
155  /* Insert colgroup and reprocess */
156  tag.name.ptr = (const uint8_t *) "colgroup";
157  tag.name.len = SLEN("colgroup");
158  tag.n_attributes = 0;
159  tag.attributes = NULL;
160 
161  err = HUBBUB_REPROCESS;
162  }
163 
164  clear_stack_table_context(treebuilder);
165 
166  e = insert_element(treebuilder, &tag, true);
167  if (e != HUBBUB_OK)
168  return e;
169 
170  treebuilder->context.mode = IN_COLUMN_GROUP;
171  } else if (type == TBODY || type == TFOOT || type == THEAD ||
172  type == TD || type == TH || type == TR) {
173  hubbub_error e;
174  hubbub_tag tag = token->data.tag;
175 
176  if (type == TD || type == TH || type == TR) {
177  /* Insert tbody and reprocess */
178  tag.name.ptr = (const uint8_t *) "tbody";
179  tag.name.len = SLEN("tbody");
180  tag.n_attributes = 0;
181  tag.attributes = NULL;
182 
183  err = HUBBUB_REPROCESS;
184  }
185 
186  clear_stack_table_context(treebuilder);
187 
188  e = insert_element(treebuilder, &tag, true);
189  if (e != HUBBUB_OK)
190  return e;
191 
192  treebuilder->context.mode = IN_TABLE_BODY;
193  } else if (type == TABLE) {
196  /* This should match "</table>" handling */
197  element_stack_pop_until(treebuilder, TABLE);
198 
199  reset_insertion_mode(treebuilder);
200 
201  err = HUBBUB_REPROCESS;
202  } else if (!tainted && (type == STYLE || type == SCRIPT)) {
203  err = handle_in_head(treebuilder, token);
204  } else if (!tainted && type == INPUT) {
205  err = process_input_in_table(treebuilder, token);
206  handled = (err == HUBBUB_OK);
207  } else {
208  handled = false;
209  }
210  }
211  break;
213  {
215  &token->data.tag.name);
216 
217  if (type == TABLE) {
220  element_stack_pop_until(treebuilder, TABLE);
221 
222  reset_insertion_mode(treebuilder);
223  } else if (type == BODY || type == CAPTION || type == COL ||
224  type == COLGROUP || type == HTML ||
225  type == TBODY || type == TD || type == TFOOT ||
226  type == TH || type == THEAD || type == TR) {
228  } else {
229  handled = false;
230  }
231  }
232  break;
233  case HUBBUB_TOKEN_EOF:
234  break;
235  }
236 
237  if (!handled) {
238  treebuilder->context.in_table_foster = true;
239 
241  err = handle_in_body(treebuilder, token);
242 
243  treebuilder->context.in_table_foster = false;
244  }
245 
246 
247  return err;
248 }
#define SLEN(s)
Definition: utils.h:21
bool tainted
Only for tables.
Definition: internal.h:48
element_type current_node(hubbub_treebuilder *treebuilder)
Peek at the top element of the element stack.
Definition: treebuilder.c:1259
hubbub_error process_comment_append(hubbub_treebuilder *treebuilder, const hubbub_token *token, void *parent)
Process a comment token, appending it to the given parent.
Definition: treebuilder.c:421
Definition: internal.h:25
hubbub_token_type type
The token type.
Definition: types.h:120
void * ctx
Context pointer.
Definition: tree.h:292
hubbub_ns ns
Tag namespace.
Definition: types.h:109
Data for a tag.
Definition: types.h:108
Token data.
Definition: types.h:119
hubbub_string name
Tag name.
Definition: types.h:110
hubbub_tree_handler * tree_handler
Callback table.
Definition: internal.h:122
const uint8_t * ptr
Pointer to data.
Definition: types.h:77
element_type
Definition: internal.h:13
static void clear_stack_table_context(hubbub_treebuilder *treebuilder)
Clear the stack back to a table context: "the UA must, while the current node is not a table element ...
Definition: in_table.c:23
hubbub_error process_characters_expect_whitespace(hubbub_treebuilder *treebuilder, const hubbub_token *token, bool insert_into_current_node)
Process a character token in cases where we expect only whitespace.
Definition: treebuilder.c:375
hubbub_string value
Attribute value.
Definition: types.h:87
Definition: internal.h:17
Definition: internal.h:25
Definition: internal.h:25
hubbub_error formatting_list_remove(hubbub_treebuilder *treebuilder, formatting_list_entry *entry, hubbub_ns *ns, element_type *type, void **node, uint32_t *stack_index)
Remove an element from the list of active formatting elements.
Definition: treebuilder.c:1384
Definition: internal.h:22
bool in_table_foster
Whether nodes that would be inserted into the current node should be foster parented.
Definition: internal.h:106
Definition: internal.h:25
insertion_mode mode
The current insertion mode.
Definition: internal.h:75
Definition: internal.h:22
size_t len
Byte length of string.
Definition: types.h:78
bool hubbub_string_match_ci(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len)
Check that one string is case-insensitively equal to another.
Definition: string.c:40
Definition: internal.h:22
hubbub_error handle_in_table(hubbub_treebuilder *treebuilder, const hubbub_token *token)
Handle token in "in table" insertion mode.
Definition: in_table.c:74
hubbub_error handle_in_body(hubbub_treebuilder *treebuilder, const hubbub_token *token)
Handle tokens in "in body" insertion mode.
Definition: in_body.c:123
Definition: internal.h:20
formatting_list_entry * formatting_list_end
End of active formatting list.
Definition: internal.h:85
hubbub_treebuilder_context context
Our context.
Definition: internal.h:120
hubbub_error insert_element(hubbub_treebuilder *treebuilder, const hubbub_tag *tag_name, bool push)
Create element and insert it into the DOM, potentially pushing it on the stack.
Definition: treebuilder.c:752
hubbub_error handle_in_head(hubbub_treebuilder *treebuilder, const hubbub_token *token)
Handle token in "in head" insertion mode.
Definition: in_head.c:109
static hubbub_error process_input_in_table(hubbub_treebuilder *treebuilder, const hubbub_token *token)
Process an input start tag in the "in table" insertion mode.
Definition: in_table.c:44
hubbub_attribute * attributes
Array of attribute data.
Definition: types.h:112
hubbub_error
Definition: errors.h:18
hubbub_error element_stack_pop_until(hubbub_treebuilder *treebuilder, element_type type)
Pop elements until an element of type "element" has been popped.
Definition: treebuilder.c:1162
void * node
Node pointer.
Definition: internal.h:54
uint32_t current_table(hubbub_treebuilder *treebuilder)
Find the stack index of the current table.
Definition: treebuilder.c:1239
hubbub_tree_ref_node ref_node
Reference node.
Definition: tree.h:278
Definition: internal.h:22
Definition: internal.h:17
hubbub_tree_unref_node unref_node
Unreference node.
Definition: tree.h:279
element_type type
Definition: treebuilder.c:26
No error.
Definition: errors.h:19
hubbub_tag tag
Definition: types.h:125
Tag attribute data.
Definition: types.h:84
hubbub_ns
Possible namespaces.
Definition: types.h:63
union hubbub_token::@3 data
Type-specific data.
hubbub_error formatting_list_append(hubbub_treebuilder *treebuilder, hubbub_ns ns, element_type type, void *node, uint32_t stack_index)
Append an element to the end of the list of active formatting elements.
Definition: treebuilder.c:1292
hubbub_error element_stack_pop(hubbub_treebuilder *treebuilder, hubbub_ns *ns, element_type *type, void **node)
Pop an element off the stack of open elements.
Definition: treebuilder.c:1113
element_type element_type_from_name(hubbub_treebuilder *treebuilder, const hubbub_string *tag_name)
Convert an element name into an element type.
Definition: treebuilder.c:987
Definition: internal.h:23
Treebuilder object.
Definition: internal.h:116
void reset_insertion_mode(hubbub_treebuilder *treebuilder)
Reset the insertion mode.
Definition: treebuilder.c:863
element_context * element_stack
Stack of open elements.
Definition: internal.h:79
uint32_t n_attributes
Count of attributes.
Definition: types.h:111
uint32_t current_node
Index of current node in stack.
Definition: internal.h:81