Esempio n. 1
0
static void xml_sax_node_end(GF_SAXParser *parser, Bool had_children)
{
	char *name, *sep, c;

	assert(parser->elt_name_start);
	assert(parser->elt_name_end);
	if (!parser->node_depth) {
		format_sax_error(parser, 0, "Markup error");
		return;
	}
	c = parser->buffer[parser->elt_name_end - 1];
	parser->buffer[parser->elt_name_end - 1] = 0;
	name = parser->buffer + parser->elt_name_start - 1;
	
	if (parser->sax_node_end) {
		sep = strchr(name, ':');
		if (sep) {
			sep[0] = 0;
			parser->sax_node_end(parser->sax_cbck, sep+1, name);
			sep[0] = ':';
		} else {
			parser->sax_node_end(parser->sax_cbck, name, NULL);
		}
	}
	parser->buffer[parser->elt_name_end - 1] = c;
	parser->node_depth--;
	if (!parser->init_state && !parser->node_depth) parser->sax_state = SAX_STATE_DONE;
	xml_sax_swap(parser);
	parser->text_start = parser->text_end = 0;
}
Esempio n. 2
0
static void on_dom_node_end(void *cbk, const char *name, const char *ns)
{
	GF_DOMParser *par = (GF_DOMParser *)cbk;
	GF_XMLNode *last = (GF_XMLNode *)gf_list_last(par->stack);
	gf_list_rem_last(par->stack);

	if (!last || strcmp(last->name, name) || (!ns && last->ns) || (ns && !last->ns) || (ns && strcmp(last->ns, ns) ) ) {
		format_sax_error(par->parser, 0, "Invalid node stack: closing node is %s but %s was expected", name, last->name);
		par->parser->suspended = 1;
		gf_xml_dom_node_del(last);
		if (last==par->root) par->root=NULL;
		return;
	}

	if (last != par->root) {
		GF_XMLNode *node = (GF_XMLNode *)gf_list_last(par->stack);
		assert(node->content);
		assert(gf_list_find(node->content, last) == -1);
		gf_list_add(node->content, last);
	}
}
Esempio n. 3
0
static Bool xml_sax_parse_attribute(GF_SAXParser *parser)
{
	char *sep;
	GF_XMLSaxAttribute *att = NULL;

	/*looking for attribute name*/
	if (parser->sax_state==SAX_STATE_ATT_NAME) {
		/*looking for start*/
		if (!parser->att_name_start) {
			while (parser->current_pos < parser->line_size) {
				u8 c = parser->buffer[parser->current_pos];
				switch (c) {
				case '\n':
					parser->line++;
				case ' ':
				case '\r':
				case '\t':
					parser->current_pos++;
					continue;
				/*end of element*/
				case '?':
					if (parser->init_state!=1) break;
				case '/':
					/*not enough data*/
					if (parser->current_pos+1 == parser->line_size) return 1;
					if (parser->buffer[parser->current_pos+1]=='>') {
						parser->current_pos+=2;
						parser->elt_end_pos = parser->file_pos + parser->current_pos - 1;
						/*done parsing attr AND elements*/
						if (!parser->init_state) {
							xml_sax_node_start(parser);
							/*move to SAX_STATE_TEXT_CONTENT to force text flush*/
							parser->sax_state = SAX_STATE_TEXT_CONTENT;
							xml_sax_node_end(parser, 0);
						} else {
							parser->nb_attrs = 0;
						}
						parser->sax_state = (parser->init_state) ? SAX_STATE_ELEMENT : SAX_STATE_TEXT_CONTENT;
						parser->text_start = parser->text_end = 0;
						return 0;
					}
					if (!parser->in_quote && (c=='/')) {
						if (!parser->init_state) {
							format_sax_error(parser, 0, "Markup error");
							return 1;
						}
					}
					break;
				case '"':
					if (parser->sax_state==SAX_STATE_ATT_VALUE) break;
					if (parser->in_quote && (parser->in_quote!=c) ) {
						format_sax_error(parser, 0, "Markup error");
						return 1;
					}
					if (parser->in_quote) parser->in_quote = 0;
					else parser->in_quote = c;
					break;
				case '>':
					parser->current_pos+=1;
					/*end of <!DOCTYPE>*/
					if (parser->init_state) {
						if (parser->init_state==1) {
							format_sax_error(parser, 0, "Invalid DOCTYPE");
							return 1;
						}
						parser->sax_state = SAX_STATE_ELEMENT;
						return 0;
					}
					/*done parsing attr*/
					parser->sax_state = SAX_STATE_TEXT_CONTENT;
					xml_sax_node_start(parser);
					return 0;
				case '[':
					if (parser->init_state) {
						parser->current_pos+=1;
						if (parser->init_state==1) {
							format_sax_error(parser, 0, "Invalid DOCTYPE");
							return 1;
						}
						parser->sax_state = SAX_STATE_ELEMENT;
						return 0;
					}
					break;
				case '<':
					format_sax_error(parser, 0, "Invalid character '<'");
					return 0;
				/*first char of attr name*/
				default:
					parser->att_name_start = parser->current_pos + 1;
					break;
				}
				parser->current_pos++;
				if (parser->att_name_start) break;
			}
			if (parser->current_pos == parser->line_size) return 1;
		}

		if (parser->init_state==2) {
			sep = strchr(parser->buffer + parser->att_name_start - 1, parser->in_quote ?  parser->in_quote : ' ');
			/*not enough data*/
			if (!sep) return 1;
			parser->current_pos = sep - parser->buffer;
			parser->att_name_start = 0;
			if (parser->in_quote) {
				parser->current_pos++;
				parser->in_quote = 0;
			}
			return 0;
		}

		/*looking for '"'*/
		if (parser->att_name_start) {
			u32 i, first=1;
			sep = strchr(parser->buffer + parser->att_name_start - 1, '=');
			/*not enough data*/
			if (!sep) return 1;

			parser->current_pos = sep - parser->buffer;
			att = xml_get_sax_attribute(parser);
			att->name_start = parser->att_name_start;
			att->name_end = parser->current_pos + 1;
			while (strchr(" \n\t", parser->buffer[att->name_end - 2])) {
				assert(att->name_end);
				att->name_end --;
			}
			att->has_entities = 0;

			for (i=att->name_start; i<att->name_end; i++) {
				char c = parser->buffer[i-1];
				if ((c>='a') && (c<='z')) {}
				else if ((c>='A') && (c<='Z')) {}
				else if ((c==':') || (c=='_')) {}

				else if (!first && ((c=='-') || (c=='.') || ((c>='0') && (c<='9')) )) {}

				else {
					format_sax_error(parser, att->name_start-1, "Invalid character \'%c\' for attribute name", c);
					return 1;
				}

				first=0;
			}

			parser->att_name_start = 0;
			parser->current_pos++;
			parser->sax_state = SAX_STATE_ATT_VALUE;

		}
	}
	
	if (parser->sax_state == SAX_STATE_ATT_VALUE) {
		att = &parser->sax_attrs[parser->nb_attrs-1];
		/*looking for first delimiter*/
		if (!parser->att_sep) {
			while (parser->current_pos < parser->line_size) {
				u8 c = parser->buffer[parser->current_pos];
				switch (c) {
				case '\n':
					parser->line++;
				case ' ':
				case '\r':
				case '\t':
					parser->current_pos++;
					continue;
				case '\'':
				case '"':
					parser->att_sep = c;
					att->val_start = parser->current_pos + 2;
					break;
				default:
					break;
				}
				parser->current_pos++;
				if (parser->att_sep) break;
			}
			if (parser->current_pos == parser->line_size) return 1;
		} 

att_retry:

		assert(parser->att_sep);
		sep = strchr(parser->buffer + parser->current_pos, parser->att_sep);
		if (!sep || !sep[1]) return 1;

		if (sep[1]==parser->att_sep) {
			format_sax_error(parser, sep - parser->buffer, "Invalid character %c after attribute value separator %c ", sep[1], parser->att_sep);
			return 1;
		}

		if (!parser->init_state && (strchr(" />\n\t\r", sep[1])==NULL)) {
			parser->current_pos = sep - parser->buffer + 1;
			goto att_retry;
		}

		parser->current_pos = sep - parser->buffer;
		att->val_end = parser->current_pos + 1;
		parser->current_pos++;

		/*"style" always at the begining of the attributes for ease of parsing*/
		if (!strncmp(parser->buffer + att->name_start-1, "style", 5)) {
			GF_XMLSaxAttribute prev = parser->sax_attrs[0];
			parser->sax_attrs[0] = *att;
			*att = prev;
		}
		parser->att_sep = 0;
		parser->sax_state = SAX_STATE_ATT_NAME;
		parser->att_name_start = 0;
		return 0;
	}
	return 1;
}