Пример #1
0
/* Initialise the document */
dom_exception _dom_document_initialise(dom_document *doc,
                                       dom_events_default_action_fetcher daf)
{
    dom_exception err;
    dom_string *name;

    err = dom_string_create((const uint8_t *) "#document",
                            SLEN("#document"), &name);
    if (err != DOM_NO_ERR)
        return err;

    doc->nodelists = NULL;

    err = _dom_node_initialise(&doc->base, doc, DOM_DOCUMENT_NODE,
                               name, NULL, NULL, NULL);
    dom_string_unref(name);
    if (err != DOM_NO_ERR)
        return err;

    list_init(&doc->pending_nodes);

    doc->id_name = NULL;
    doc->quirks = DOM_DOCUMENT_QUIRKS_MODE_NONE;

    err = dom_string_create_interned((const uint8_t *) "class",
                                     SLEN("class"), &doc->class_string);
    if (err != DOM_NO_ERR)
        return err;

    /* We should not pass a NULL when all things hook up */
    return _dom_document_event_internal_initialise(doc, &doc->dei, daf);
}
Пример #2
0
static hubbub_error add_attributes(void *parser, void *node,
		const hubbub_attribute *attributes, uint32_t n_attributes)
{
	dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser;
	dom_exception err;
	uint32_t i;

	for (i = 0; i < n_attributes; i++) {
		dom_string *name, *value;

		err = dom_string_create_interned(attributes[i].name.ptr,
				attributes[i].name.len, &name);
		if (err != DOM_NO_ERR) {
			dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx,
					"Can't create attribute name");
			goto fail;
		}

		err = dom_string_create(attributes[i].value.ptr,
				attributes[i].value.len, &value);
		if (err != DOM_NO_ERR) {
			dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx,
					"Can't create attribute value");
			dom_string_unref(name);
			goto fail;
		}

		if (attributes[i].ns == HUBBUB_NS_NULL) {
			err = dom_element_set_attribute(
					(struct dom_element *) node, name,
					value);
			dom_string_unref(name);
			dom_string_unref(value);
			if (err != DOM_NO_ERR) {
				dom_parser->msg(DOM_MSG_CRITICAL,
						dom_parser->mctx,
						"Can't add attribute");
			}
		} else {
			err = dom_element_set_attribute_ns(
					(struct dom_element *) node,
					dom_namespaces[attributes[i].ns], name,
					value);
			dom_string_unref(name);
			dom_string_unref(value);
			if (err != DOM_NO_ERR) {
				dom_parser->msg(DOM_MSG_CRITICAL,
						dom_parser->mctx,
						"Can't add attribute ns");
			}
		}
	}

	return HUBBUB_OK;

fail:
	return HUBBUB_UNKNOWN;
}
Пример #3
0
/**
 * Callback to determine if a node has an attribute with the given name whose
 * value contains the substring given.
 *
 * \param pw     HTML document
 * \param node   DOM node
 * \param qname  Name to match
 * \param value  Value to match
 * \param match  Pointer to location to receive result
 * \return CSS_OK on success,
 *         CSS_NOMEM on memory exhaustion.
 *
 * \post \a match will contain true if the node matches and false otherwise.
 */
css_error node_has_attribute_substring(void *pw, void *node,
		const css_qname *qname, lwc_string *value,
		bool *match)
{
	dom_node *n = node;
	dom_string *name;
	dom_string *atr_val;
	dom_exception err;

	size_t vlen = lwc_string_length(value);

	if (vlen == 0) {
		*match = false;
		return CSS_OK;
	}

	err = dom_string_create_interned(
		(const uint8_t *) lwc_string_data(qname->name),
		lwc_string_length(qname->name), &name);
	if (err != DOM_NO_ERR)
		return CSS_NOMEM;

	err = dom_element_get_attribute(n, name, &atr_val);
	if ((err != DOM_NO_ERR) || (atr_val == NULL)) {
		dom_string_unref(name);
		*match = false;
		return CSS_OK;
	}

	dom_string_unref(name);

	/* check for exact match */
	*match = dom_string_caseless_lwc_isequal(atr_val, value);

	/* check for prefix match */
	if (*match == false) {
		const char *vdata = lwc_string_data(value);
		const char *start = (const char *) dom_string_data(atr_val);
		size_t len = dom_string_byte_length(atr_val);
		const char *last_start = start + len - vlen;

		if (len >= vlen) {
			while (start <= last_start) {
				if (strncasecmp(start, vdata,
						vlen) == 0) {
					*match = true;
					break;
				}

				start++;
			}
		}
	}

	dom_string_unref(atr_val);

	return CSS_OK;
}
Пример #4
0
/**
 * Callback to determine if a node has an attribute with the given name whose
 * value includes that given.
 *
 * \param pw     HTML document
 * \param node   DOM node
 * \param qname  Name to match
 * \param value  Value to match
 * \param match  Pointer to location to receive result
 * \return CSS_OK on success,
 *         CSS_NOMEM on memory exhaustion.
 *
 * \post \a match will contain true if the node matches and false otherwise.
 */
css_error node_has_attribute_includes(void *pw, void *node,
		const css_qname *qname, lwc_string *value,
		bool *match)
{
	dom_node *n = node;
	dom_string *name;
	dom_string *atr_val;
	dom_exception err;
	size_t vlen = lwc_string_length(value);
	const char *p;
	const char *start;
	const char *end;

	*match = false;

	if (vlen == 0) {
		return CSS_OK;
	}

	err = dom_string_create_interned(
		(const uint8_t *) lwc_string_data(qname->name),
		lwc_string_length(qname->name), &name);
	if (err != DOM_NO_ERR)
		return CSS_NOMEM;

	err = dom_element_get_attribute(n, name, &atr_val);
	if ((err != DOM_NO_ERR) || (atr_val == NULL)) {
		dom_string_unref(name);
		*match = false;
		return CSS_OK;
	}

	dom_string_unref(name);

	/* check for match */
	start = (const char *) dom_string_data(atr_val);
	end = start + dom_string_byte_length(atr_val);

	for (p = start; p <= end; p++) {
		if (*p == ' ' || *p == '\0') {
			if ((size_t) (p - start) == vlen &&
			    strncasecmp(start,
					lwc_string_data(value),
					vlen) == 0) {
				*match = true;
				break;
			}

			start = p + 1;
		}
	}

	dom_string_unref(atr_val);

	return CSS_OK;
}
Пример #5
0
static hubbub_error create_element(void *parser, const hubbub_tag *tag,
		void **result)
{
	dom_hubbub_parser *dom_parser = (dom_hubbub_parser *) parser;
	dom_exception err;
	dom_string *name;
	struct dom_element *element = NULL;
	hubbub_error herr;

	*result = NULL;

	err = dom_string_create_interned(tag->name.ptr, tag->name.len, &name);
	if (err != DOM_NO_ERR) {
		dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx,
				"Can't create element name");
		goto fail;
	}

	if (tag->ns == HUBBUB_NS_NULL) {
		err = dom_document_create_element(dom_parser->doc, name,
				&element);
		if (err != DOM_NO_ERR) {
			dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx,
					"Can't create the DOM element");
			goto clean1;
		}
	} else {
		err = dom_document_create_element_ns(dom_parser->doc,
				dom_namespaces[tag->ns], name, &element);
		if (err != DOM_NO_ERR) {
			dom_parser->msg(DOM_MSG_CRITICAL, dom_parser->mctx,
					"Can't create the DOM element");
			goto clean1;
		}
	}

	if (element != NULL && tag->n_attributes > 0) {
		herr = add_attributes(parser, element, tag->attributes,
				tag->n_attributes);
		if (herr != HUBBUB_OK)
			goto clean1;
	}

	*result = element;

clean1:
	dom_string_unref(name);

fail:
	if (*result == NULL)
		return HUBBUB_UNKNOWN;
	else
		return HUBBUB_OK;
}
Пример #6
0
dom_exception dom_element_get_attribute(dom_node *node, dom_string *string, dom_string **outAttribute) {
  /* xmlAttrPtr attrPtr = xmlHasProp(node->node, (const xmlChar *)string->s); */
	const char *attr = ezxml_attr(node->node, string->s);
  if (NULL == attr) {
    if (strchr(string->s, ':')) {
      fprintf(stderr, "TODO:dom_element_get_attribute - namespace %s\n", string->s);
    }
  } else {
    return dom_string_create_interned((const uint8_t *)attr, strlen(attr), outAttribute);
  }
  *outAttribute = NULL;
  return DOM_NO_ERR;
}
Пример #7
0
/**
 * Callback to determine if a node has an attribute with the given name whose
 * value dashmatches that given.
 *
 * \param pw     HTML document
 * \param node   DOM node
 * \param qname  Name to match
 * \param value  Value to match
 * \param match  Pointer to location to receive result
 * \return CSS_OK on success,
 *         CSS_NOMEM on memory exhaustion.
 *
 * \post \a match will contain true if the node matches and false otherwise.
 */
css_error node_has_attribute_dashmatch(void *pw, void *node,
		const css_qname *qname, lwc_string *value,
		bool *match)
{
	dom_node *n = node;
	dom_string *name;
	dom_string *atr_val;
	dom_exception err;

	size_t vlen = lwc_string_length(value);

	if (vlen == 0) {
		*match = false;
		return CSS_OK;
	}

	err = dom_string_create_interned(
		(const uint8_t *) lwc_string_data(qname->name),
		lwc_string_length(qname->name), &name);
	if (err != DOM_NO_ERR)
		return CSS_NOMEM;

	err = dom_element_get_attribute(n, name, &atr_val);
	if ((err != DOM_NO_ERR) || (atr_val == NULL)) {
		dom_string_unref(name);
		*match = false;
		return CSS_OK;
	}

	dom_string_unref(name);

	/* check for exact match */
	*match = dom_string_caseless_lwc_isequal(atr_val, value);

	/* check for dashmatch */
	if (*match == false) {
		const char *vdata = lwc_string_data(value);
		const char *data = (const char *) dom_string_data(atr_val);
		size_t len = dom_string_byte_length(atr_val);

		if (len > vlen && data[vlen] == '-' &&
		    strncasecmp(data, vdata, vlen) == 0) {
				*match = true;
		}
	}

	dom_string_unref(atr_val);

	return CSS_OK;
}
Пример #8
0
/** Convert the given string to lowercase
 *
 * \param source 
 * \param ascii_only  Whether to only convert [a-z] to [A-Z]
 * \param lower       Result pointer for lowercase string.  Caller owns ref
 *
 * \return DOM_NO_ERR on success.
 *
 * \note Right now, will return DOM_NOT_SUPPORTED_ERR if ascii_only is false.
 */
dom_exception
dom_string_tolower(dom_string *source, bool ascii_only, dom_string **lower)
{
	const uint8_t *orig_s = (const uint8_t *) dom_string_data(source);
	const size_t nbytes = dom_string_byte_length(source);
	uint8_t *copy_s;
	size_t index = 0, clen;
	parserutils_error err;
	dom_exception exc;
	
	if (ascii_only == false)
		return DOM_NOT_SUPPORTED_ERR;
	
	copy_s = malloc(nbytes);
	if (copy_s == NULL)
		return DOM_NO_MEM_ERR;
	memcpy(copy_s, orig_s, nbytes);
	
	while (index < nbytes) {
		err = parserutils_charset_utf8_char_byte_length(orig_s + index,
								&clen);
		if (err != PARSERUTILS_OK) {
			free(copy_s);
			/** \todo Find a better exception */
			return DOM_NO_MEM_ERR;
		}
		
		if (clen == 1) {
			if (orig_s[index] >= 'A' &&
			    orig_s[index] <= 'Z')
				copy_s[index] += 'a' - 'A';
		}
		
		index += clen;
	}
	
	if (((dom_string_internal*)source)->type == DOM_STRING_CDATA) {
		exc = dom_string_create(copy_s, nbytes, lower);
	} else {
		exc = dom_string_create_interned(copy_s, nbytes, lower);
	}
	
	free(copy_s);
	
	return exc;
}
Пример #9
0
/**
 * Callback to determine if a node has an attribute with the given name.
 *
 * \param pw     HTML document
 * \param node   DOM node
 * \param qname  Name to match
 * \param match  Pointer to location to receive result
 * \return CSS_OK on success,
 *         CSS_NOMEM on memory exhaustion.
 *
 * \post \a match will contain true if the node matches and false otherwise.
 */
css_error node_has_attribute(void *pw, void *node,
		const css_qname *qname, bool *match)
{
	dom_node *n = node;
	dom_string *name;
	dom_exception err;

	err = dom_string_create_interned(
			(const uint8_t *) lwc_string_data(qname->name),
			lwc_string_length(qname->name), &name);
	if (err != DOM_NO_ERR)
		return CSS_NOMEM;

	err = dom_element_has_attribute(n, name, match);
	if (err != DOM_NO_ERR) {
		dom_string_unref(name);
		return CSS_OK;
	}

	dom_string_unref(name);

	return CSS_OK;
}
Пример #10
0
/**
 * Callback to determine if a node has an attribute with given name and value.
 *
 * \param pw     HTML document
 * \param node   DOM node
 * \param qname  Name to match
 * \param value  Value to match
 * \param match  Pointer to location to receive result
 * \return CSS_OK on success,
 *         CSS_NOMEM on memory exhaustion.
 *
 * \post \a match will contain true if the node matches and false otherwise.
 */
css_error node_has_attribute_equal(void *pw, void *node,
		const css_qname *qname, lwc_string *value,
		bool *match)
{
	dom_node *n = node;
	dom_string *name;
	dom_string *atr_val;
	dom_exception err;

	size_t vlen = lwc_string_length(value);

	if (vlen == 0) {
		*match = false;
		return CSS_OK;
	}

	err = dom_string_create_interned(
		(const uint8_t *) lwc_string_data(qname->name),
		lwc_string_length(qname->name), &name);
	if (err != DOM_NO_ERR)
		return CSS_NOMEM;

	err = dom_element_get_attribute(n, name, &atr_val);
	if ((err != DOM_NO_ERR) || (atr_val == NULL)) {
		dom_string_unref(name);
		*match = false;
		return CSS_OK;
	}

	dom_string_unref(name);

	*match = dom_string_caseless_lwc_isequal(atr_val, value);

	dom_string_unref(atr_val);

	return CSS_OK;
}
Пример #11
0
lwc_error lwc_intern_string(const char *data, size_t len, lwc_string **outString) {
  return (lwc_error)dom_string_create_interned((const uint8_t *)data, len, outString);
}
Пример #12
0
dom_exception dom_node_get_node_name(dom_node *node, dom_string **outString) {
  ezxml_t n = node->node;
  dom_exception errCode = DOM_NO_ERR;
  errCode = dom_string_create_interned(n->name, strlen((const char *)n->name), outString);
  return errCode;
}
Пример #13
0
/* exported function documented in string.h */
dom_exception dom_string_whitespace_op(dom_string *s,
		enum dom_whitespace_op op, dom_string **ret)
{
	const uint8_t *src_text = (const uint8_t *) dom_string_data(s);
	size_t len = dom_string_byte_length(s);
	const uint8_t *src_pos;
	const uint8_t *src_end;
	dom_exception exc;
	uint8_t *temp_pos;
	uint8_t *temp;

	if (len == 0) {
		*ret = dom_string_ref(s);
	}

	temp = malloc(len);
	if (temp == NULL) {
		return DOM_NO_MEM_ERR;
	}

	src_pos = src_text;
	src_end = src_text + len;
	temp_pos = temp;

	if (op & DOM_WHITESPACE_STRIP_LEADING) {
		while (src_pos < src_end) {
			if (*src_pos == ' '  || *src_pos == '\t' ||
			    *src_pos == '\n' || *src_pos == '\r' ||
			    *src_pos == '\f')
				src_pos++;
			else
				break;
		}
	}

	while (src_pos < src_end) {
		if ((op & DOM_WHITESPACE_COLLAPSE) &&
				(*src_pos == ' ' || *src_pos == '\t' ||
				*src_pos == '\n' || *src_pos == '\r' ||
				*src_pos == '\f')) {
			/* Got a whitespace character */
			do {
				/* Skip all adjacent whitespace */
				src_pos++;
			} while (src_pos < src_end &&
					(*src_pos == ' ' || *src_pos == '\t' ||
					*src_pos == '\n' || *src_pos == '\r' ||
					*src_pos == '\f'));
			/* Gets replaced with single space in output */
			*temp_pos++ = ' ';
		} else {
			/* Otherwise, copy to output */
			*temp_pos++ = *src_pos++;
		}
	}

	if (op & DOM_WHITESPACE_STRIP_TRAILING) {
		while (temp_pos > temp) {
			temp_pos--;
			if (*temp_pos != ' '  && *temp_pos != '\t' &&
			    *temp_pos != '\n' && *temp_pos != '\r' &&
			    *temp_pos != '\f') {
				temp_pos++;
				break;
			}
		}
	}

	/* New length */
	len = temp_pos - temp;

	/* Make new string */
	if (((dom_string_internal *) s)->type == DOM_STRING_CDATA) {
		exc = dom_string_create(temp, len, ret);
	} else {
		exc = dom_string_create_interned(temp, len, ret);
	}

	free(temp);

	return exc;
}
Пример #14
0
/**
 * Create a Hubbub parser instance
 *
 * \param params The binding creation parameters
 * \param parser Pointer to location to recive instance.
 * \param document Pointer to location to receive document.
 * \return Error code
 */
dom_hubbub_error
dom_hubbub_parser_create(dom_hubbub_parser_params *params,
			 dom_hubbub_parser **parser,
			 dom_document **document)
{
	dom_hubbub_parser *binding;
	hubbub_parser_optparams optparams;
	hubbub_error error;
	dom_exception err;
	dom_string *idname = NULL;

	/* check result parameters */
	if (document == NULL) {
		return DOM_HUBBUB_BADPARM;
	}

	if (parser == NULL) {
		return DOM_HUBBUB_BADPARM;
	}

	/* setup binding parser context */
	binding = malloc(sizeof(dom_hubbub_parser));
	if (binding == NULL) {
		return DOM_HUBBUB_NOMEM;
	}

	binding->parser = NULL;
	binding->doc = NULL;
	binding->encoding = params->enc;

	if (params->enc != NULL) {
		binding->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_HEADER;
	} else {
		binding->encoding_source = DOM_HUBBUB_ENCODING_SOURCE_DETECTED;
	}

	binding->complete = false;

	if (params->msg == NULL) {
		binding->msg = dom_hubbub_parser_default_msg;
	} else {
		binding->msg = params->msg;
	}
	binding->mctx = params->ctx;

	/* ensure script function is valid or use the default */
	if (params->script == NULL) {
		binding->script = dom_hubbub_parser_default_script;
	} else {
		binding->script = params->script;
	}

	/* create hubbub parser */
	error = hubbub_parser_create(binding->encoding,
				     params->fix_enc,
				     dom_hubbub_alloc,
				     NULL,
				     &binding->parser);
	if (error != HUBBUB_OK)	 {
		free(binding);
		return (DOM_HUBBUB_HUBBUB_ERR | error);
	}

	/* create DOM document */
	err = dom_implementation_create_document(DOM_IMPLEMENTATION_HTML,
						 NULL,
						 NULL,
						 NULL,
						 params->daf,
						 params->ctx,
						 &binding->doc);
	if (err != DOM_NO_ERR) {
		hubbub_parser_destroy(binding->parser);
		free(binding);
		return DOM_HUBBUB_DOM;
	}

	binding->tree_handler = tree_handler;
	binding->tree_handler.ctx = (void *)binding;

	/* set tree handler on parser */
	optparams.tree_handler = &binding->tree_handler;
	hubbub_parser_setopt(binding->parser,
			     HUBBUB_PARSER_TREE_HANDLER,
			     &optparams);

	/* set document node*/
	optparams.document_node = dom_node_ref((struct dom_node *)binding->doc);
	hubbub_parser_setopt(binding->parser,
			     HUBBUB_PARSER_DOCUMENT_NODE,
			     &optparams);

	/* set scripting state */
	optparams.enable_scripting = params->enable_script;
	hubbub_parser_setopt(binding->parser,
			     HUBBUB_PARSER_ENABLE_SCRIPTING,
			     &optparams);

	/* set the document id parameter before the parse so searches
	 * based on id succeed.
	 */
	err = dom_string_create_interned((const uint8_t *) "id",
					 SLEN("id"),
					 &idname);
	if (err != DOM_NO_ERR) {
		binding->msg(DOM_MSG_ERROR, binding->mctx, "Can't set DOM document id name");
		hubbub_parser_destroy(binding->parser);
		free(binding);
		return DOM_HUBBUB_DOM;
	}
	_dom_document_set_id_name(binding->doc, idname);
	dom_string_unref(idname);

	/* set return parameters */
	*document = (dom_document *)dom_node_ref(binding->doc);
	*parser = binding;

	return DOM_HUBBUB_OK;
}