示例#1
0
float svgtiny_parse_length(dom_string *s, int viewport_size,
			   const struct svgtiny_parse_state state)
{
	char *ss = strndup(dom_string_data(s), dom_string_byte_length(s));
	float ret = _svgtiny_parse_length(ss, viewport_size, state);
	free(ss);
	return ret;
}
示例#2
0
文件: select.c 项目: kyllikki/netsurf
/**
 * 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;
}
示例#3
0
/**
 * Case insensitively compare two DOM strings
 *
 * \param s1  The first string to compare
 * \param s2  The second string to compare
 * \return true if strings match, false otherwise
 */
bool dom_string_caseless_isequal(const dom_string *s1, const dom_string *s2)
{
	const uint8_t *d1 = NULL;
	const uint8_t *d2 = NULL;
	size_t len;
	const dom_string_internal *is1 = (dom_string_internal *) s1;
	const dom_string_internal *is2 = (dom_string_internal *) s2;

	if (s1 == NULL)
		is1 = &empty_string;

	if (s2 == NULL)
		is2 = &empty_string;

	if (is1->type == DOM_STRING_INTERNED && 
			is2->type == DOM_STRING_INTERNED) {
		bool match;

		if (lwc_string_caseless_isequal(is1->data.intern,
				is2->data.intern, &match) != lwc_error_ok)
			return false;

		return match;
	}

	len = dom_string_byte_length((dom_string *) is1);

	if (len != dom_string_byte_length((dom_string *)is2))
		return false;

	d1 = (const uint8_t *) dom_string_data((dom_string *) is1);
	d2 = (const uint8_t *) dom_string_data((dom_string *)is2);

	while (len > 0) {
		if (dolower(*d1) != dolower(*d2))
			return false;

		d1++;
		d2++;
		len--;
	}

	return true;
}
示例#4
0
文件: select.c 项目: kyllikki/netsurf
/**
 * 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
/** 
 * Concatenate two dom strings 
 * 
 * \param s1      The first string
 * \param s2      The second string
 * \param result  Pointer to location to receive result
 * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
 *
 * The returned string will be referenced. The client
 * should dereference it once it has finished with it.
 */
dom_exception dom_string_concat(dom_string *s1, dom_string *s2,
		dom_string **result)
{
	dom_string_internal *concat;
	const uint8_t *s1ptr, *s2ptr;
	size_t s1len, s2len;

	assert(s1 != NULL);
	assert(s2 != NULL);

	s1ptr = (const uint8_t *) dom_string_data(s1);
	s2ptr = (const uint8_t *) dom_string_data(s2);
	s1len = dom_string_byte_length(s1);
	s2len = dom_string_byte_length(s2);

	concat = malloc(sizeof(*concat));
	if (concat == NULL) {
		return DOM_NO_MEM_ERR;
	}

	concat->data.cdata.ptr = malloc(s1len + s2len + 1);
	if (concat->data.cdata.ptr == NULL) {
		free(concat);

		return DOM_NO_MEM_ERR;
	}

	memcpy(concat->data.cdata.ptr, s1ptr, s1len);

	memcpy(concat->data.cdata.ptr + s1len, s2ptr, s2len);

	concat->data.cdata.ptr[s1len + s2len] = '\0';

	concat->data.cdata.len = s1len + s2len;

	concat->base.refcnt = 1;

	concat->type = DOM_STRING_CDATA;

	*result = (dom_string *)concat;

	return DOM_NO_ERR;
}
示例#6
0
文件: select.c 项目: kyllikki/netsurf
/**
 * 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;
}
示例#7
0
static struct form_control *
parse_select_element(struct form *forms, dom_html_select_element *select)
{
	struct form_control *control = NULL;
	dom_html_form_element *form = NULL;
	dom_string *ds_name = NULL;

	char *name = NULL;

	if (dom_html_select_element_get_form(select, &form) != DOM_NO_ERR)
		goto out;

	if (dom_html_select_element_get_name(select, &ds_name) != DOM_NO_ERR)
		goto out;

	if (ds_name != NULL)
		name = strndup(dom_string_data(ds_name),
			       dom_string_byte_length(ds_name));

	control = form_new_control(select, GADGET_SELECT);

	if (control == NULL)
		goto out;

	if (name != NULL) {
		/* Hand the name string over */
		control->name = name;
		name = NULL;
	}

	dom_html_select_element_get_multiple(select,
			&(control->data.select.multiple));

	if (form != NULL && control != NULL)
		form_add_control(find_form(forms, form), control);

out:
	if (form != NULL)
		dom_node_unref(form);
	if (ds_name != NULL)
		dom_string_unref(ds_name);

	if (name != NULL)
		free(name);


	return control;
}
示例#8
0
/**
 * Calculate a hash value from a dom string 
 *
 * \param str  The string to calculate a hash of
 * \return The hash value associated with the string
 */
uint32_t dom_string_hash(dom_string *str)
{
	const uint8_t *s = (const uint8_t *) dom_string_data(str);
	size_t slen = dom_string_byte_length(str);
	uint32_t hash = 0x811c9dc5;

	while (slen > 0) {
		hash *= 0x01000193;
		hash ^= *s;

		s++;
		slen--;
	}

	return hash;
}
示例#9
0
/**
 * Get the length, in characters, of a dom string
 *
 * \param str  The string to measure the length of
 * \return The length of the string, in characters
 */
size_t dom_string_length(dom_string *str)
{
	const uint8_t *s;
	size_t slen, clen;
	parserutils_error err;

	s = (const uint8_t *) dom_string_data(str);
	slen = dom_string_byte_length(str);

	err = parserutils_charset_utf8_length(s, slen, &clen);
	if (err != PARSERUTILS_OK) {
		return 0;
	}

	return clen;
}
示例#10
0
/**
 * Validate whether the string is a legal NCName.
 * Refer http://www.w3.org/TR/REC-xml-names/ for detail.
 *
 * \param str  The name to validate
 * \return true if ::name is valid, false otherwise.
 */
bool _dom_validate_ncname(dom_string *name)
{
	uint32_t ch;
	size_t clen, slen;
	parserutils_error err;
	const uint8_t *s;

	if (name == NULL)
		return false;

	slen = dom_string_length(name);
	if (slen == 0)
		return false;

	s = (const uint8_t *) dom_string_data(name);
	slen = dom_string_byte_length(name);
	
	err = parserutils_charset_utf8_to_ucs4(s, slen, &ch, &clen);
	if (err != PARSERUTILS_OK) {
		return false;
	}
	
	if (is_letter(ch) == false && ch != (uint32_t) '_')
		return false;
	
	s += clen;
	slen -= clen;
	
	while (slen > 0) {
		err = parserutils_charset_utf8_to_ucs4(s, slen, &ch, &clen);
		if (err != PARSERUTILS_OK) {
			return false;
		}

		if (is_name_char(ch) == false)
			return false;

		if (ch == (uint32_t) ':')
			return false;

		s += clen;
		slen -= clen;
	}

	return true;
}
示例#11
0
/**
 * Extract a substring from a dom string 
 *
 * \param str     The string to extract from
 * \param i1      The character index of the start of the substring
 * \param i2      The character index of the end of the substring
 * \param result  Pointer to location to receive result
 * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion
 *
 * The returned string will have its reference count increased. The client
 * should dereference it once it has finished with it.
 */
dom_exception dom_string_substr(dom_string *str, 
		off_t i1, off_t i2, dom_string **result)
{
	const uint8_t *s;
	size_t slen;
	off_t b1, b2;
	parserutils_error err;

	/* target string is NULL equivalent to empty. */
	if (str == NULL)
		str = (dom_string *)&empty_string;

	s = (const uint8_t *) dom_string_data(str);
	slen = dom_string_byte_length(str);

	/* Initialise the byte index of the start to 0 */
	b1 = 0;
	/* Make the end a character offset from the start */
	i2 -= i1;

	/* Calculate the byte index of the start */
	while (i1 > 0) {
		err = parserutils_charset_utf8_next(s, slen, b1, &b1);
		if (err != PARSERUTILS_OK) {
			return DOM_NO_MEM_ERR;
		}

		i1--;
	}

	/* Initialise the byte index of the end to that of the start */
	b2 = b1;

	/* Calculate the byte index of the end */
	while (i2 > 0) {
		err = parserutils_charset_utf8_next(s, slen, b2, &b2);
		if (err != PARSERUTILS_OK) {
			return DOM_NO_MEM_ERR;
		}

		i2--;
	}

	/* Create a string from the specified byte range */
	return dom_string_create(s + b1, (size_t)(b2 - b1), result);
}
示例#12
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;
}
示例#13
0
static struct form_control *
parse_textarea_element(struct form *forms, dom_html_text_area_element *ta)
{
	struct form_control *control = NULL;
	dom_html_form_element *form = NULL;
	dom_string *ds_name = NULL;

	char *name = NULL;

	if (dom_html_text_area_element_get_form(ta, &form) != DOM_NO_ERR)
		goto out;

	if (dom_html_text_area_element_get_name(ta, &ds_name) != DOM_NO_ERR)
		goto out;

	if (ds_name != NULL)
		name = strndup(dom_string_data(ds_name),
			       dom_string_byte_length(ds_name));

	control = form_new_control(ta, GADGET_TEXTAREA);

	if (control == NULL)
		goto out;

	if (name != NULL) {
		/* Hand the name string over */
		control->name = name;
		name = NULL;
	}

	if (form != NULL && control != NULL)
		form_add_control(find_form(forms, form), control);

out:
	if (form != NULL)
		dom_node_unref(form);
	if (ds_name != NULL)
		dom_string_unref(ds_name);

	if (name != NULL)
		free(name);


	return control;
}
示例#14
0
void svgtiny_parse_transform_attributes(dom_element *node,
		struct svgtiny_parse_state *state)
{
	char *transform;
	dom_string *attr;
	dom_exception exc;
	
	exc = dom_element_get_attribute(node, state->interned_transform,
					&attr);
	if (exc == DOM_NO_ERR && attr != NULL) {
		transform = strndup(dom_string_data(attr),
				    dom_string_byte_length(attr));
		svgtiny_parse_transform(transform, &state->ctm.a, &state->ctm.b,
				&state->ctm.c, &state->ctm.d,
				&state->ctm.e, &state->ctm.f);
		free(transform);
		dom_string_unref(attr);
	}
}
示例#15
0
static bool save_complete_handle_attr(save_complete_ctx *ctx,
		dom_string *node_name, dom_attr *attr)
{
	dom_string *name;
	const char *name_data;
	size_t name_len;
	dom_string *value;
	dom_exception error;

	error = dom_attr_get_name(attr, &name);
	if (error != DOM_NO_ERR)
		return false;

	if (name == NULL)
		return true;

	error = dom_attr_get_value(attr, &value);
	if (error != DOM_NO_ERR) {
		dom_string_unref(name);
		return false;
	}

	name_data = dom_string_data(name);
	name_len = dom_string_byte_length(name);

	fputc(' ', ctx->fp);
	fwrite(name_data, sizeof(*name_data), name_len, ctx->fp);

	if (value != NULL) {
		fputc('=', ctx->fp);
		if (save_complete_handle_attr_value(ctx, node_name, 
				name, value) == false) {
			dom_string_unref(value);
			dom_string_unref(name);
			return false;
		}
	}

	dom_string_unref(name);

	return true;
}
示例#16
0
static dom_hubbub_error
exec_inline_script(html_content *c, dom_node *node, dom_string *mimetype)
{
	union content_msg_data msg_data;
	dom_string *script;
	dom_exception exc; /* returned by libdom functions */
	struct lwc_string_s *lwcmimetype;
	script_handler_t *script_handler;
	struct html_script *nscript;

	/* does not appear to be a src so script is inline content */
	exc = dom_node_get_text_content(node, &script);
	if ((exc != DOM_NO_ERR) || (script == NULL)) {
		return DOM_HUBBUB_OK; /* no contents, skip */
	}

	nscript = html_process_new_script(c, mimetype, HTML_SCRIPT_INLINE);
	if (nscript == NULL) {
		dom_string_unref(script);

		msg_data.error = messages_get("NoMemory");
		content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
		return DOM_HUBBUB_NOMEM;

	}

	nscript->data.string = script;
	nscript->already_started = true;

	/* ensure script handler for content type */
	dom_string_intern(mimetype, &lwcmimetype);
	script_handler = select_script_handler(content_factory_type_from_mime_type(lwcmimetype));
	lwc_string_unref(lwcmimetype);

	if (script_handler != NULL) {
		script_handler(c->jscontext,
			       dom_string_data(script),
			       dom_string_byte_length(script));
	}
	return DOM_HUBBUB_OK;
}
示例#17
0
/**
 * Get the UCS4 character at position index
 *
 * \param index  The position of the charater
 * \param ch     The UCS4 character
 * \return DOM_NO_ERR on success, appropriate dom_exception on failure.
 */
dom_exception dom_string_at(dom_string *str, uint32_t index, 
		uint32_t *ch)
{
	const uint8_t *s;
	size_t clen, slen;
	uint32_t c, i;
	parserutils_error err;

	s = (const uint8_t *) dom_string_data(str);
	slen = dom_string_byte_length(str);

	i = 0;

	while (slen > 0) {
		err = parserutils_charset_utf8_char_byte_length(s, &clen);
		if (err != PARSERUTILS_OK) {
			return (uint32_t) -1;
		}

		i++;
		if (i == index + 1)
			break;

		s += clen;
		slen -= clen;
	}

	if (i == index + 1) {
		err = parserutils_charset_utf8_to_ucs4(s, slen, &c, &clen);
		if (err != PARSERUTILS_OK) {
			return (uint32_t) -1;
		}

		*ch = c;
		return DOM_NO_ERR;
	} else {
		return DOM_DOMSTRING_SIZE_ERR;
	}
}
示例#18
0
/**
 * Case sensitively compare DOM string with lwc_string
 *
 * \param s1  The first string to compare
 * \param s2  The second string to compare
 * \return true if strings match, false otherwise
 *
 * Returns false if either are NULL.
 */
bool dom_string_lwc_isequal(const dom_string *s1, lwc_string *s2)
{
	size_t len;
	dom_string_internal *is1 = (dom_string_internal *) s1;

	if (s1 == NULL || s2 == NULL)
		return false;

	if (is1->type == DOM_STRING_INTERNED) {
		bool match;

		(void) lwc_string_isequal(is1->data.intern, s2, &match);

		return match;
	}

	/* Handle non-interned case */
	len = dom_string_byte_length(s1);

	if (len != lwc_string_length(s2))
		return false;

	return 0 == memcmp(dom_string_data(s1), lwc_string_data(s2), len);
}
示例#19
0
static struct form_control *
parse_button_element(struct form *forms, dom_html_button_element *button)
{
	struct form_control *control = NULL;
	dom_exception err;
	dom_html_form_element *form = NULL;
	dom_string *ds_type = NULL;
	dom_string *ds_value = NULL;
	dom_string *ds_name = NULL;

	err = dom_html_button_element_get_form(button, &form);
	if (err != DOM_NO_ERR)
		goto out;

	err = dom_html_button_element_get_type(button, &ds_type);
	if (err != DOM_NO_ERR)
		goto out;

	if (ds_type == NULL) {
		control = form_new_control(button, GADGET_SUBMIT);
	} else {
		if (dom_string_caseless_lwc_isequal(ds_type,
				corestring_lwc_submit)) {
			control = form_new_control(button, GADGET_SUBMIT);
		} else if (dom_string_caseless_lwc_isequal(ds_type,
				corestring_lwc_reset)) {
			control = form_new_control(button, GADGET_RESET);
		} else {
			control = form_new_control(button, GADGET_BUTTON);
		}
	}

	if (control == NULL)
		goto out;

	err = dom_html_button_element_get_value(button, &ds_value);
	if (err != DOM_NO_ERR)
		goto out;
	err = dom_html_button_element_get_name(button, &ds_name);
	if (err != DOM_NO_ERR)
		goto out;

	if (ds_value != NULL) {
		control->value = strndup(
			dom_string_data(ds_value),
			dom_string_byte_length(ds_value));

		if (control->value == NULL) {
			form_free_control(control);
			control = NULL;
			goto out;
		}
	}

	if (ds_name != NULL) {
		control->name = strndup(
			dom_string_data(ds_name),
			dom_string_byte_length(ds_name));

		if (control->name == NULL) {
			form_free_control(control);
			control = NULL;
			goto out;
		}
	}

	if (form != NULL && control != NULL)
		form_add_control(find_form(forms, form), control);

out:
	if (form != NULL)
		dom_node_unref(form);
	if (ds_type != NULL)
		dom_string_unref(ds_type);
	if (ds_value != NULL)
		dom_string_unref(ds_value);
	if (ds_name != NULL)
		dom_string_unref(ds_name);

	return control;
}
示例#20
0
svgtiny_code svgtiny_parse_text(dom_element *text,
		struct svgtiny_parse_state state)
{
	float x, y, width, height;
	float px, py;
	dom_node *child;
	dom_exception exc;

	svgtiny_setup_state_local(&state);

	svgtiny_parse_position_attributes(text, state,
			&x, &y, &width, &height);
	svgtiny_parse_font_attributes(text, &state);
	svgtiny_parse_transform_attributes(text, &state);

	px = state.ctm.a * x + state.ctm.c * y + state.ctm.e;
	py = state.ctm.b * x + state.ctm.d * y + state.ctm.f;
/* 	state.ctm.e = px - state.origin_x; */
/* 	state.ctm.f = py - state.origin_y; */

	/*struct css_style style = state.style;
	style.font_size.value.length.value *= state.ctm.a;*/
	
        exc = dom_node_get_first_child(text, &child);
	if (exc != DOM_NO_ERR) {
		return svgtiny_LIBDOM_ERROR;
		svgtiny_cleanup_state_local(&state);
	}
	while (child != NULL) {
		dom_node *next;
		dom_node_type nodetype;
		svgtiny_code code = svgtiny_OK;

		exc = dom_node_get_node_type(child, &nodetype);
		if (exc != DOM_NO_ERR) {
			dom_node_unref(child);
			svgtiny_cleanup_state_local(&state);
			return svgtiny_LIBDOM_ERROR;
		}
		if (nodetype == DOM_ELEMENT_NODE) {
			dom_string *nodename;
			exc = dom_node_get_node_name(child, &nodename);
			if (exc != DOM_NO_ERR) {
				dom_node_unref(child);
				svgtiny_cleanup_state_local(&state);
				return svgtiny_LIBDOM_ERROR;
			}
			if (dom_string_caseless_isequal(nodename,
							state.interned_tspan))
				code = svgtiny_parse_text((dom_element *)child,
							  state);
			dom_string_unref(nodename);
		} else if (nodetype == DOM_TEXT_NODE) {
			struct svgtiny_shape *shape = svgtiny_add_shape(&state);
			dom_string *content;
			if (shape == NULL) {
				dom_node_unref(child);
				svgtiny_cleanup_state_local(&state);
				return svgtiny_OUT_OF_MEMORY;
			}
			exc = dom_text_get_whole_text(child, &content);
			if (exc != DOM_NO_ERR) {
				dom_node_unref(child);
				svgtiny_cleanup_state_local(&state);
				return svgtiny_LIBDOM_ERROR;
			}
			if (content != NULL) {
				shape->text = strndup(dom_string_data(content),
						      dom_string_byte_length(content));
				dom_string_unref(content);
			} else {
				shape->text = strdup("");
			}
			shape->text_x = px;
			shape->text_y = py;
			state.diagram->shape_count++;
		}

		if (code != svgtiny_OK) {
			dom_node_unref(child);
			svgtiny_cleanup_state_local(&state);
			return code;
		}
		exc = dom_node_get_next_sibling(child, &next);
		dom_node_unref(child);
		if (exc != DOM_NO_ERR) {
			svgtiny_cleanup_state_local(&state);
			return svgtiny_LIBDOM_ERROR;
		}
		child = next;
	}

	svgtiny_cleanup_state_local(&state);

	return svgtiny_OK;
}
示例#21
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;
}
示例#22
0
static bool save_complete_handle_element(save_complete_ctx *ctx,
		dom_node *node, save_complete_event_type event_type)
{
	dom_string *name;
	dom_namednodemap *attrs;
	const char *name_data;
	size_t name_len;
	bool process = true;
	dom_exception error;

	ctx->iter_state = STATE_NORMAL;

	error = dom_node_get_node_name(node, &name);
	if (error != DOM_NO_ERR)
		return false;

	if (name == NULL)
		return true;

	name_data = dom_string_data(name);
	name_len = dom_string_byte_length(name);

	if (name_len == SLEN("base") &&
			strncasecmp(name_data, "base", name_len) == 0) {
		/* Elide BASE elements from the output */
		process = false;
	} else if (name_len == SLEN("meta") && 
			strncasecmp(name_data, "meta", name_len) == 0) {
		/* Don't emit close tags for META elements */
		if (event_type == EVENT_LEAVE) {
			process = false;
		} else {
			/* Elide meta charsets */
			dom_string *value;
			error = dom_element_get_attribute(node,
					corestring_dom_http_equiv, &value);
			if (error != DOM_NO_ERR) {
				dom_string_unref(name);
				return false;
			}

			if (value != NULL) {
				if (dom_string_length(value) ==
					SLEN("Content-Type") &&
					strncasecmp(dom_string_data(value),
						"Content-Type",
						SLEN("Content-Type")) == 0)
					process = false;

				dom_string_unref(value);
			} else {
				bool yes;

				error = dom_element_has_attribute(node,
						corestring_dom_charset, &yes);
				if (error != DOM_NO_ERR) {
					dom_string_unref(name);
					return false;
				}

				if (yes)
					process = false;
			}
		}
	} else if (event_type == EVENT_LEAVE && 
			((name_len == SLEN("link") && 
			strncasecmp(name_data, "link", name_len) == 0))) {
		/* Don't emit close tags for void elements */
		process = false;
	}

	if (process == false) {
		dom_string_unref(name);
		return true;
	}

	fputc('<', ctx->fp);
	if (event_type == EVENT_LEAVE)
		fputc('/', ctx->fp);
	fwrite(name_data, sizeof(*name_data), name_len, ctx->fp);

	if (event_type == EVENT_ENTER) {
		error = dom_node_get_attributes(node, &attrs);
		if (error != DOM_NO_ERR) {
			dom_string_unref(name);
			return false;
		}

		if (save_complete_handle_attrs(ctx, name, attrs) == false) {
			dom_namednodemap_unref(attrs);
			dom_string_unref(name);
			return false;
		}

		dom_namednodemap_unref(attrs);
	}

	fputc('>', ctx->fp);

	/* Rewrite contents of style elements */
	if (event_type == EVENT_ENTER && name_len == SLEN("style") &&
			strncasecmp(name_data, "style", name_len) == 0) {
		dom_string *content;

		error = dom_node_get_text_content(node, &content);
		if (error != DOM_NO_ERR) {
			dom_string_unref(name);
			return false;
		}

		if (content != NULL) {
			char *rewritten;
			unsigned long len;

			/* Rewrite @import rules */
			rewritten = save_complete_rewrite_stylesheet_urls(
					ctx,
					dom_string_data(content),
					dom_string_byte_length(content),
					ctx->base,
					&len);
			if (rewritten == NULL) {
				dom_string_unref(content);
				dom_string_unref(name);
				return false;
			}

			dom_string_unref(content);

			fwrite(rewritten, sizeof(*rewritten), len, ctx->fp);

			free(rewritten);
		}

		ctx->iter_state = STATE_IN_STYLE;
	} else if (event_type == EVENT_ENTER && name_len == SLEN("head") &&
			strncasecmp(name_data, "head", name_len) == 0) {
		/* If this is a HEAD element, insert a meta charset */
		fputs("<META http-equiv=\"Content-Type\" "
				"content=\"text/html; charset=utf-8\">",
				ctx->fp);
	}

	dom_string_unref(name);

	return true;
}
示例#23
0
svgtiny_code svgtiny_parse_poly(dom_element *poly,
		struct svgtiny_parse_state state, bool polygon)
{
	svgtiny_code err;
	dom_string *points_str;
	dom_exception exc;
	char *s, *points;
	float *p;
	unsigned int i;

	svgtiny_setup_state_local(&state);

	svgtiny_parse_paint_attributes(poly, &state);
	svgtiny_parse_transform_attributes(poly, &state);
	
	exc = dom_element_get_attribute(poly, state.interned_points,
					&points_str);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	
	if (points_str == NULL) {
		state.diagram->error_line = -1; /* poly->line; */
		state.diagram->error_message =
				"polyline/polygon: missing points attribute";
		svgtiny_cleanup_state_local(&state);
		return svgtiny_SVG_ERROR;
	}

	s = points = strndup(dom_string_data(points_str),
			     dom_string_byte_length(points_str));
	dom_string_unref(points_str);
	/* read points attribute */
	if (s == NULL) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}
	/* allocate space for path: it will never have more elements than s */
	p = malloc(sizeof p[0] * strlen(s));
	if (!p) {
		free(points);
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}

	/* parse s and build path */
	for (i = 0; s[i]; i++)
		if (s[i] == ',')
			s[i] = ' ';
	i = 0;
	while (*s) {
		float x, y;
		int n;

		if (sscanf(s, "%f %f %n", &x, &y, &n) == 2) {
			if (i == 0)
				p[i++] = svgtiny_PATH_MOVE;
			else
				p[i++] = svgtiny_PATH_LINE;
			p[i++] = x;
			p[i++] = y;
			s += n;
                } else {
                	break;
                }
        }
        if (polygon)
		p[i++] = svgtiny_PATH_CLOSE;

	free(points);

	err = svgtiny_add_path(p, i, &state);

	svgtiny_cleanup_state_local(&state);

	return err;
}
示例#24
0
svgtiny_code svgtiny_parse_svg(dom_element *svg,
		struct svgtiny_parse_state state)
{
	float x, y, width, height;
	dom_string *view_box;
	dom_element *child;
	dom_exception exc;

	svgtiny_setup_state_local(&state);

	svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height);
	svgtiny_parse_paint_attributes(svg, &state);
	svgtiny_parse_font_attributes(svg, &state);

	exc = dom_element_get_attribute(svg, state.interned_viewBox,
					&view_box);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}

	if (view_box) {
		char *s = strndup(dom_string_data(view_box),
				  dom_string_byte_length(view_box));
		float min_x, min_y, vwidth, vheight;
		if (sscanf(s, "%f,%f,%f,%f",
				&min_x, &min_y, &vwidth, &vheight) == 4 ||
				sscanf(s, "%f %f %f %f",
				&min_x, &min_y, &vwidth, &vheight) == 4) {
			state.ctm.a = (float) state.viewport_width / vwidth;
			state.ctm.d = (float) state.viewport_height / vheight;
			state.ctm.e += -min_x * state.ctm.a;
			state.ctm.f += -min_y * state.ctm.d;
		}
		free(s);
		dom_string_unref(view_box);
	}

	svgtiny_parse_transform_attributes(svg, &state);

	exc = dom_node_get_first_child(svg, (dom_node **) (void *) &child);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	while (child != NULL) {
		dom_element *next;
		dom_node_type nodetype;
		svgtiny_code code = svgtiny_OK;

		exc = dom_node_get_node_type(child, &nodetype);
		if (exc != DOM_NO_ERR) {
			dom_node_unref(child);
			return svgtiny_LIBDOM_ERROR;
		}
		if (nodetype == DOM_ELEMENT_NODE) {
			dom_string *nodename;
			exc = dom_node_get_node_name(child, &nodename);
			if (exc != DOM_NO_ERR) {
				dom_node_unref(child);
				svgtiny_cleanup_state_local(&state);
				return svgtiny_LIBDOM_ERROR;
			}
			if (dom_string_caseless_isequal(state.interned_svg,
							nodename))
				code = svgtiny_parse_svg(child, state);
			else if (dom_string_caseless_isequal(state.interned_g,
							     nodename))
				code = svgtiny_parse_svg(child, state);
			else if (dom_string_caseless_isequal(state.interned_a,
							     nodename))
				code = svgtiny_parse_svg(child, state);
			else if (dom_string_caseless_isequal(state.interned_path,
							     nodename))
				code = svgtiny_parse_path(child, state);
			else if (dom_string_caseless_isequal(state.interned_rect,
							     nodename))
				code = svgtiny_parse_rect(child, state);
			else if (dom_string_caseless_isequal(state.interned_circle,
							     nodename))
				code = svgtiny_parse_circle(child, state);
			else if (dom_string_caseless_isequal(state.interned_ellipse,
							     nodename))
				code = svgtiny_parse_ellipse(child, state);
			else if (dom_string_caseless_isequal(state.interned_line,
							     nodename))
				code = svgtiny_parse_line(child, state);
			else if (dom_string_caseless_isequal(state.interned_polyline,
							     nodename))
				code = svgtiny_parse_poly(child, state, false);
			else if (dom_string_caseless_isequal(state.interned_polygon,
							     nodename))
				code = svgtiny_parse_poly(child, state, true);
			else if (dom_string_caseless_isequal(state.interned_text,
							     nodename))
				code = svgtiny_parse_text(child, state);
			dom_string_unref(nodename);
		}
		if (code != svgtiny_OK) {
			dom_node_unref(child);
			svgtiny_cleanup_state_local(&state);
			return code;
		}
		exc = dom_node_get_next_sibling(child,
						(dom_node **) (void *) &next);
		dom_node_unref(child);
		if (exc != DOM_NO_ERR) {
			svgtiny_cleanup_state_local(&state);
			return svgtiny_LIBDOM_ERROR;
		}
		child = next;
	}

	svgtiny_cleanup_state_local(&state);
	return svgtiny_OK;
}
示例#25
0
/** 
 * process form element from dom
 */
static struct form *
parse_form_element(const char *docenc, dom_node *node)
{
	dom_string *ds_action = NULL;
	dom_string *ds_charset = NULL;
	dom_string *ds_target = NULL;
	dom_string *ds_method = NULL;
	dom_string *ds_enctype = NULL;
	char *action = NULL, *charset = NULL, *target = NULL;
	form_method method;
	dom_html_form_element *formele = (dom_html_form_element *)(node);
	struct form * ret = NULL;

	/* Retrieve the attributes from the node */
	if (dom_html_form_element_get_action(formele,
			&ds_action) != DOM_NO_ERR)
		goto out;

	if (dom_html_form_element_get_accept_charset(formele,
			&ds_charset) != DOM_NO_ERR)
		goto out;

	if (dom_html_form_element_get_target(formele,
			&ds_target) != DOM_NO_ERR)
		goto out;

	if (dom_html_form_element_get_method(formele,
			&ds_method) != DOM_NO_ERR)
		goto out;

	if (dom_html_form_element_get_enctype(formele,
			&ds_enctype) != DOM_NO_ERR)
		goto out;

	/* Extract the plain attributes ready for use.  We have to do this
	 * because we cannot guarantee that the dom_strings are NULL terminated
	 * and thus we copy them.
	 */
	if (ds_action != NULL)
		action = strndup(dom_string_data(ds_action),
				 dom_string_byte_length(ds_action));

	if (ds_charset != NULL)
		charset = strndup(dom_string_data(ds_charset),
				  dom_string_byte_length(ds_charset));

	if (ds_target != NULL)
		target = strndup(dom_string_data(ds_target),
				 dom_string_byte_length(ds_target));

	/* Determine the method */
	method = method_GET;
	if (ds_method != NULL) {
		if (dom_string_caseless_lwc_isequal(ds_method,
				corestring_lwc_post)) {
			method = method_POST_URLENC;
			if (ds_enctype != NULL) {
				if (dom_string_caseless_lwc_isequal(ds_enctype,
					corestring_lwc_multipart_form_data)) {

					method = method_POST_MULTIPART;
				}
			}
		}
	}

	/* Construct the form object */
	ret = form_new(node, action, target, method, charset, docenc);

out:
	if (ds_action != NULL)
		dom_string_unref(ds_action);
	if (ds_charset != NULL)
		dom_string_unref(ds_charset);
	if (ds_target != NULL)
		dom_string_unref(ds_target);
	if (ds_method != NULL)
		dom_string_unref(ds_method);
	if (ds_enctype != NULL)
		dom_string_unref(ds_enctype);
	if (action != NULL)
		free(action);
	if (charset != NULL)
		free(charset);
	if (target != NULL)
		free(target);
	return ret;
}
示例#26
0
static struct form_control *
parse_input_element(struct form *forms, dom_html_input_element *input)
{
	struct form_control *control = NULL;
	dom_html_form_element *form = NULL;
	dom_string *ds_type = NULL;
	dom_string *ds_name = NULL;
	dom_string *ds_value = NULL;

	char *name = NULL;

	if (dom_html_input_element_get_form(input, &form) != DOM_NO_ERR)
		goto out;

	if (dom_html_input_element_get_type(input, &ds_type) != DOM_NO_ERR)
		goto out;

	if (dom_html_input_element_get_name(input, &ds_name) != DOM_NO_ERR)
		goto out;

	if (ds_name != NULL)
		name = strndup(dom_string_data(ds_name),
			       dom_string_byte_length(ds_name));

	if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_password)) {
		control = form_new_control(input, GADGET_PASSWORD);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_file)) {
		control = form_new_control(input, GADGET_FILE);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_hidden)) {
		control = form_new_control(input, GADGET_HIDDEN);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_checkbox)) {
		control = form_new_control(input, GADGET_CHECKBOX);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_radio)) {
		control = form_new_control(input, GADGET_RADIO);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_submit)) {
		control = form_new_control(input, GADGET_SUBMIT);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_reset)) {
		control = form_new_control(input, GADGET_RESET);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_button)) {
		control = form_new_control(input, GADGET_BUTTON);
	} else if (ds_type != NULL && dom_string_caseless_lwc_isequal(ds_type,
			corestring_lwc_image)) {
		control = form_new_control(input, GADGET_IMAGE);
	} else {
		control = form_new_control(input, GADGET_TEXTBOX);
	}

	if (control == NULL)
		goto out;

	if (name != NULL) {
		/* Hand the name string over */
		control->name = name;
		name = NULL;
	}

	if (control->type == GADGET_CHECKBOX || control->type == GADGET_RADIO) {
		bool selected;
		if (dom_html_input_element_get_checked(
			    input, &selected) == DOM_NO_ERR) {
			control->selected = selected;
		}
	}

	if (control->type == GADGET_PASSWORD ||
	    control->type == GADGET_TEXTBOX) {
		int32_t maxlength;
		if (dom_html_input_element_get_max_length(
			    input, &maxlength) != DOM_NO_ERR) {
			maxlength = -1;
		}

		if (maxlength >= 0) {
			/* Got valid maxlength */
			control->maxlength = maxlength;
		} else {
			/* Input has no maxlength attr, or
			 * dom_html_input_element_get_max_length failed.
			 *
			 * Set it to something insane. */
			control->maxlength = UINT_MAX;
		}
	}

	if (control->type != GADGET_FILE && control->type != GADGET_IMAGE) {
		if (dom_html_input_element_get_value(
			    input, &ds_value) == DOM_NO_ERR) {
			if (ds_value != NULL) {
				control->value = strndup(
					dom_string_data(ds_value),
					dom_string_byte_length(ds_value));
				if (control->value == NULL) {
					form_free_control(control);
					control = NULL;
					goto out;
				}
				control->length = strlen(control->value);
			}
		}

		if (control->type == GADGET_TEXTBOX ||
				control->type == GADGET_PASSWORD) {
			if (control->value == NULL) {
				control->value = strdup("");
				if (control->value == NULL) {
					form_free_control(control);
					control = NULL;
					goto out;
				}

				control->length = 0;
			}

			control->initial_value = strdup(control->value);
			if (control->initial_value == NULL) {
				form_free_control(control);
				control = NULL;
				goto out;
			}
		}
	}

	if (form != NULL && control != NULL)
		form_add_control(find_form(forms, form), control);

out:
	if (form != NULL)
		dom_node_unref(form);
	if (ds_type != NULL)
		dom_string_unref(ds_type);
	if (ds_name != NULL)
		dom_string_unref(ds_name);
	if (ds_value != NULL)
		dom_string_unref(ds_value);

	if (name != NULL)
		free(name);

	return control;
}
示例#27
0
/** 
 * Replace a section of a dom string
 *
 * \param target  Pointer to string of which to replace a section
 * \param source  Pointer to replacement string
 * \param i1      Character index of start of region to replace
 * \param i2      Character index of end of region to replace
 * \param result  Pointer to location to receive result
 * \return DOM_NO_ERR on success, DOM_NO_MEM_ERR on memory exhaustion.
 *
 * The returned string will have its reference count increased. The client
 * should dereference it once it has finished with it. 
 */
dom_exception dom_string_replace(dom_string *target,
		dom_string *source, off_t i1, off_t i2,
		dom_string **result)
{
	dom_string_internal *res;
	const uint8_t *t, *s;
	size_t tlen, slen;
	off_t b1, b2;
	parserutils_error err;

	/* target string is NULL equivalent to empty. */
	if (target == NULL)
		target = (dom_string *)&empty_string;

	t = (const uint8_t *) dom_string_data(target);
	tlen = dom_string_byte_length(target);
	s = (const uint8_t *) dom_string_data(source);
	slen = dom_string_byte_length(source);

	/* Initialise the byte index of the start to 0 */
	b1 = 0;
	/* Make the end a character offset from the start */
	i2 -= i1;

	/* Calculate the byte index of the start */
	while (i1 > 0) {
		err = parserutils_charset_utf8_next(t, tlen, b1, &b1);

		if (err != PARSERUTILS_OK) {
			return DOM_NO_MEM_ERR;
		}

		i1--;
	}

	/* Initialise the byte index of the end to that of the start */
	b2 = b1;

	/* Calculate the byte index of the end */
	while (i2 > 0) {
		err = parserutils_charset_utf8_next(t, tlen, b2, &b2);

		if (err != PARSERUTILS_OK) {
			return DOM_NO_MEM_ERR;
		}

		i2--;
	}

	/* Allocate result string */
	res = malloc(sizeof(*res));
	if (res == NULL) {
		return DOM_NO_MEM_ERR;
	}

	/* Allocate data buffer for result contents */
	res->data.cdata.ptr = malloc((unsigned long)(tlen + slen - (b2 - b1) + 1));
	if (res->data.cdata.ptr == NULL) {
		free(res);
		return DOM_NO_MEM_ERR;
	}

	/* Copy initial portion of target, if any, into result */
	if (b1 > 0) {
		memcpy(res->data.cdata.ptr, t, (unsigned long)b1);
	}

	/* Copy replacement data into result */
	if (slen > 0) {
		memcpy(res->data.cdata.ptr + b1, s, slen);
	}

	/* Copy remainder of target, if any, into result */
	if (tlen - b2 > 0) {
		memcpy(res->data.cdata.ptr + b1 + slen, t + b2, (unsigned long)(tlen - b2));
	}

	res->data.cdata.ptr[tlen + slen - (b2 - b1)] = '\0';

	res->data.cdata.len = (size_t)(tlen + slen - (b2 - b1));

	res->base.refcnt = 1;

	res->type = DOM_STRING_CDATA;

	*result = (dom_string *)res;

	return DOM_NO_ERR;
}
示例#28
0
static bool save_complete_node_handler(dom_node *node,
		save_complete_event_type event_type, void *ctxin)
{
	save_complete_ctx *ctx = ctxin;
	dom_node_type type;
	dom_exception error;
	utf8_convert_ret ret;

	error = dom_node_get_node_type(node, &type);
	if (error != DOM_NO_ERR)
		return false;

	if (type == DOM_ELEMENT_NODE) {
		return save_complete_handle_element(ctx, node, event_type);
	} else if (type == DOM_TEXT_NODE || type == DOM_COMMENT_NODE) {
		if (event_type != EVENT_ENTER)
			return true;

		if (ctx->iter_state != STATE_IN_STYLE) {
			/* Emit text content */
			dom_string *text;
			const char *text_data;
			size_t text_len;

			error = dom_characterdata_get_data(node, &text);
			if (error != DOM_NO_ERR) {
				return false;
			}

			if (type == DOM_COMMENT_NODE)
				fwrite("<!--", 1, sizeof("<!--") - 1, ctx->fp);

			if (text != NULL) {
				char *escaped;

				text_data = dom_string_data(text);
				text_len = dom_string_byte_length(text);

				ret = utf8_to_html(text_data, "UTF-8",
						text_len, &escaped);
				if (ret != UTF8_CONVERT_OK)
					return false;

				fwrite(escaped, sizeof(*escaped), 
						strlen(escaped), ctx->fp);

				free(escaped);

				dom_string_unref(text);
			}

			if (type == DOM_COMMENT_NODE) {
				fwrite("-->", 1, sizeof("-->") - 1, ctx->fp);
			}
		}

	} else if (type == DOM_DOCUMENT_TYPE_NODE) {
		dom_string *name;
		const char *name_data;
		size_t name_len;

		if (event_type != EVENT_ENTER)
			return true;

		error = dom_document_type_get_name(node, &name);
		if (error != DOM_NO_ERR)
			return false;

		if (name == NULL)
			return true;

		name_data = dom_string_data(name);
		name_len = dom_string_byte_length(name);

		fputs("<!DOCTYPE ", ctx->fp);
		fwrite(name_data, sizeof(*name_data), name_len, ctx->fp);

		dom_string_unref(name);

		error = dom_document_type_get_public_id(node, &name);
		if (error != DOM_NO_ERR)
			return false;

		if (name != NULL) {
			name_data = dom_string_data(name);
			name_len = dom_string_byte_length(name);

			if (name_len > 0)
				fprintf(ctx->fp, " PUBLIC \"%.*s\"",
						(int) name_len, name_data);

			dom_string_unref(name);
		}

		error = dom_document_type_get_system_id(node, &name);
		if (error != DOM_NO_ERR)
			return false;

		if (name != NULL) {
			name_data = dom_string_data(name);
			name_len = dom_string_byte_length(name);

			if (name_len > 0)
				fprintf(ctx->fp, " \"%.*s\"",
						(int) name_len, name_data);

			dom_string_unref(name);
		}

		fputc('>', ctx->fp);
	} else if (type == DOM_DOCUMENT_NODE) {
		/* Do nothing */
	} else {
		LOG(("Unhandled node type: %d", type));
	}

	return true;
}
示例#29
0
svgtiny_code svgtiny_parse_path(dom_element *path,
		struct svgtiny_parse_state state)
{
	svgtiny_code err;
	dom_string *path_d_str;
	dom_exception exc;
	char *s, *path_d;
	float *p;
	unsigned int i;
	float last_x = 0, last_y = 0;
	float last_cubic_x = 0, last_cubic_y = 0;
	float last_quad_x = 0, last_quad_y = 0;

	svgtiny_setup_state_local(&state);

	svgtiny_parse_paint_attributes(path, &state);
	svgtiny_parse_transform_attributes(path, &state);

	/* read d attribute */
	exc = dom_element_get_attribute(path, state.interned_d, &path_d_str);
	if (exc != DOM_NO_ERR) {
		state.diagram->error_line = -1; /* path->line; */
		state.diagram->error_message = "path: error retrieving d attribute";
		svgtiny_cleanup_state_local(&state);
		return svgtiny_SVG_ERROR;
	}

	if (path_d_str == NULL) {
		state.diagram->error_line = -1; /* path->line; */
		state.diagram->error_message = "path: missing d attribute";
		svgtiny_cleanup_state_local(&state);
		return svgtiny_SVG_ERROR;
	}

	s = path_d = strndup(dom_string_data(path_d_str),
			     dom_string_byte_length(path_d_str));
	dom_string_unref(path_d_str);
	if (s == NULL) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}
	/* allocate space for path: it will never have more elements than d */
	p = malloc(sizeof p[0] * strlen(s));
	if (!p) {
		free(path_d);
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}

	/* parse d and build path */
	for (i = 0; s[i]; i++)
		if (s[i] == ',')
			s[i] = ' ';
	i = 0;
	while (*s) {
		char command[2];
		int plot_command;
		float x, y, x1, y1, x2, y2, rx, ry, rotation, large_arc, sweep;
		int n;

		/* moveto (M, m), lineto (L, l) (2 arguments) */
		if (sscanf(s, " %1[MmLl] %f %f %n", command, &x, &y, &n) == 3) {
			/*LOG(("moveto or lineto"));*/
			if (*command == 'M' || *command == 'm')
				plot_command = svgtiny_PATH_MOVE;
			else
				plot_command = svgtiny_PATH_LINE;
			do {
				p[i++] = plot_command;
				if ('a' <= *command) {
					x += last_x;
					y += last_y;
				}
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
				plot_command = svgtiny_PATH_LINE;
			} while (sscanf(s, "%f %f %n", &x, &y, &n) == 2);

		/* closepath (Z, z) (no arguments) */
		} else if (sscanf(s, " %1[Zz] %n", command, &n) == 1) {
			/*LOG(("closepath"));*/
			p[i++] = svgtiny_PATH_CLOSE;
			s += n;

		/* horizontal lineto (H, h) (1 argument) */
		} else if (sscanf(s, " %1[Hh] %f %n", command, &x, &n) == 2) {
			/*LOG(("horizontal lineto"));*/
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'h')
					x += last_x;
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y;
				s += n;
			} while (sscanf(s, "%f %n", &x, &n) == 1);

		/* vertical lineto (V, v) (1 argument) */
		} else if (sscanf(s, " %1[Vv] %f %n", command, &y, &n) == 2) {
			/*LOG(("vertical lineto"));*/
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'v')
					y += last_y;
				p[i++] = last_cubic_x = last_quad_x = last_x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
			} while (sscanf(s, "%f %n", &x, &n) == 1);

		/* curveto (C, c) (6 arguments) */
		} else if (sscanf(s, " %1[Cc] %f %f %f %f %f %f %n", command,
				&x1, &y1, &x2, &y2, &x, &y, &n) == 7) {
			/*LOG(("curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				if (*command == 'c') {
					x1 += last_x;
					y1 += last_y;
					x2 += last_x;
					y2 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = x1;
				p[i++] = y1;
				p[i++] = last_cubic_x = x2;
				p[i++] = last_cubic_y = y2;
				p[i++] = last_quad_x = last_x = x;
				p[i++] = last_quad_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %f %f %n",
					&x1, &y1, &x2, &y2, &x, &y, &n) == 6);

		/* shorthand/smooth curveto (S, s) (4 arguments) */
		} else if (sscanf(s, " %1[Ss] %f %f %f %f %n", command,
				&x2, &y2, &x, &y, &n) == 5) {
			/*LOG(("shorthand/smooth curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				x1 = last_x + (last_x - last_cubic_x);
				y1 = last_y + (last_y - last_cubic_y);
				if (*command == 's') {
					x2 += last_x;
					y2 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = x1;
				p[i++] = y1;
				p[i++] = last_cubic_x = x2;
				p[i++] = last_cubic_y = y2;
				p[i++] = last_quad_x = last_x = x;
				p[i++] = last_quad_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %n",
					&x2, &y2, &x, &y, &n) == 4);

		/* quadratic Bezier curveto (Q, q) (4 arguments) */
		} else if (sscanf(s, " %1[Qq] %f %f %f %f %n", command,
				&x1, &y1, &x, &y, &n) == 5) {
			/*LOG(("quadratic Bezier curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				last_quad_x = x1;
				last_quad_y = y1;
				if (*command == 'q') {
					x1 += last_x;
					y1 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = 1./3 * last_x + 2./3 * x1;
				p[i++] = 1./3 * last_y + 2./3 * y1;
				p[i++] = 2./3 * x1 + 1./3 * x;
				p[i++] = 2./3 * y1 + 1./3 * y;
				p[i++] = last_cubic_x = last_x = x;
				p[i++] = last_cubic_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %n",
					&x1, &y1, &x, &y, &n) == 4);

		/* shorthand/smooth quadratic Bezier curveto (T, t)
		   (2 arguments) */
		} else if (sscanf(s, " %1[Tt] %f %f %n", command,
				&x, &y, &n) == 3) {
			/*LOG(("shorthand/smooth quadratic Bezier curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				x1 = last_x + (last_x - last_quad_x);
				y1 = last_y + (last_y - last_quad_y);
				last_quad_x = x1;
				last_quad_y = y1;
				if (*command == 't') {
					x1 += last_x;
					y1 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = 1./3 * last_x + 2./3 * x1;
				p[i++] = 1./3 * last_y + 2./3 * y1;
				p[i++] = 2./3 * x1 + 1./3 * x;
				p[i++] = 2./3 * y1 + 1./3 * y;
				p[i++] = last_cubic_x = last_x = x;
				p[i++] = last_cubic_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %n",
					&x, &y, &n) == 2);

		/* elliptical arc (A, a) (7 arguments) */
		} else if (sscanf(s, " %1[Aa] %f %f %f %f %f %f %f %n", command,
				&rx, &ry, &rotation, &large_arc, &sweep,
				&x, &y, &n) == 8) {
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'a') {
					x += last_x;
					y += last_y;
				}
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %f %f %f %n",
				&rx, &ry, &rotation, &large_arc, &sweep,
				&x, &y, &n) == 7);

		} else {
			fprintf(stderr, "parse failed at \"%s\"\n", s);
			break;
		}
	}

	free(path_d);

	if (i <= 4) {
		/* no real segments in path */
		free(p);
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OK;
	}

	err = svgtiny_add_path(p, i, &state);

	svgtiny_cleanup_state_local(&state);

	return err;
}
示例#30
0
/**
 * Insert data into a dom string at the given location
 *
 * \param target  Pointer to string to insert into
 * \param source  Pointer to string to insert
 * \param offset  Character offset of location to insert at
 * \param result  Pointer to location to receive result
 * \return DOM_NO_ERR          on success, 
 *         DOM_NO_MEM_ERR      on memory exhaustion,
 *         DOM_INDEX_SIZE_ERR  if ::offset > len(::target).
 *
 * The returned string will have its reference count increased. The client
 * should dereference it once it has finished with it. 
 */
dom_exception dom_string_insert(dom_string *target,
		dom_string *source, off_t offset,
		dom_string **result)
{
	dom_string_internal *res;
	const uint8_t *t, *s;
	size_t tlen, slen, clen;
	off_t ins = 0;
	parserutils_error err;

	/* target string is NULL equivalent to empty. */
	if (target == NULL)
		target = (dom_string *)&empty_string;

	t = (const uint8_t *) dom_string_data(target);
	tlen = dom_string_byte_length(target);
	s = (const uint8_t *) dom_string_data(source);
	slen = dom_string_byte_length(source);

	clen = dom_string_length(target);

	if (offset > clen)
		return DOM_INDEX_SIZE_ERR;

	/* Calculate the byte index of the insertion point */
	if (offset == clen) {
		/* Optimisation for append */
		ins = tlen;
	} else {
		while (offset > 0) {
			err = parserutils_charset_utf8_next(t, tlen, 
					ins, &ins);

			if (err != PARSERUTILS_OK) {
				return DOM_NO_MEM_ERR;
			}

			offset--;
		}
	}

	/* Allocate result string */
	res = malloc(sizeof(*res));
	if (res == NULL) {
		return DOM_NO_MEM_ERR;
	}

	/* Allocate data buffer for result contents */
	res->data.cdata.ptr = malloc(tlen + slen + 1);
	if (res->data.cdata.ptr == NULL) {
		free(res);
		return DOM_NO_MEM_ERR;
	}

	/* Copy initial portion of target, if any, into result */
	if (ins > 0) {
		memcpy(res->data.cdata.ptr, t, (unsigned long)ins);
	}

	/* Copy inserted data into result */
	memcpy(res->data.cdata.ptr + ins, s, slen);

	/* Copy remainder of target, if any, into result */
	if (tlen - ins > 0) {
		memcpy(res->data.cdata.ptr + ins + slen, t + ins, (unsigned long)(tlen - ins));
	}

	res->data.cdata.ptr[tlen + slen] = '\0';

	res->data.cdata.len = tlen + slen;

	res->base.refcnt = 1;

	res->type = DOM_STRING_CDATA;

	*result = (dom_string *)res;

	return DOM_NO_ERR;
}