/** * Case sensitively 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_isequal(const dom_string *s1, const dom_string *s2) { 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; (void) lwc_string_isequal(is1->data.intern, is2->data.intern, &match); return match; } len = dom_string_byte_length((dom_string *) is1); if (len != dom_string_byte_length((dom_string *)is2)) return false; return 0 == memcmp(dom_string_data((dom_string *) is1), dom_string_data((dom_string *)is2), len); }
static struct html_stylesheet * html_create_style_element(html_content *c, dom_node *style) { dom_string *val; dom_exception exc; struct html_stylesheet *stylesheets; /* type='text/css', or not present (invalid but common) */ exc = dom_element_get_attribute(style, corestring_dom_type, &val); if (exc == DOM_NO_ERR && val != NULL) { if (!dom_string_caseless_lwc_isequal(val, corestring_lwc_text_css)) { dom_string_unref(val); return NULL; } dom_string_unref(val); } /* media contains 'screen' or 'all' or not present */ exc = dom_element_get_attribute(style, corestring_dom_media, &val); if (exc == DOM_NO_ERR && val != NULL) { if (strcasestr(dom_string_data(val), "screen") == NULL && strcasestr(dom_string_data(val), "all") == NULL) { dom_string_unref(val); return NULL; } dom_string_unref(val); } /* Extend array */ stylesheets = realloc(c->stylesheets, sizeof(struct html_stylesheet) * (c->stylesheet_count + 1)); if (stylesheets == NULL) { content_broadcast_errorcode(&c->base, NSERROR_NOMEM); return false; } c->stylesheets = stylesheets; c->stylesheets[c->stylesheet_count].node = dom_node_ref(style); c->stylesheets[c->stylesheet_count].sheet = NULL; c->stylesheets[c->stylesheet_count].modified = false; c->stylesheet_count++; return c->stylesheets + (c->stylesheet_count - 1); }
/** * Get the index of the last occurrence of a character in a dom string * * \param str The string to search in * \param chr UCS4 value to look for * \return Character index of found character, or -1 if none found */ off_t dom_string_rindex(dom_string *str, uint32_t chr) { const uint8_t *s; size_t clen = 0, slen; uint32_t c = 0; off_t coff, index; parserutils_error err; s = (const uint8_t *) dom_string_data(str); slen = dom_string_byte_length(str); index = dom_string_length(str); while (slen > 0) { err = parserutils_charset_utf8_prev(s, slen, (off_t *) &coff); if (err == PARSERUTILS_OK) { err = parserutils_charset_utf8_to_ucs4(s + coff, slen - clen, &c, &clen); } if (err != PARSERUTILS_OK) { return (uint32_t) -1; } if (c == chr) { return index; } slen -= clen; index--; } return (uint32_t) -1; }
/** * Get the index of the first occurrence of a character in a dom string * * \param str The string to search in * \param chr UCS4 value to look for * \return Character index of found character, or -1 if none found */ off_t dom_string_index(dom_string *str, uint32_t chr) { const uint8_t *s; size_t clen, slen; uint32_t c, index; parserutils_error err; s = (const uint8_t *) dom_string_data(str); slen = dom_string_byte_length(str); index = 0; while (slen > 0) { err = parserutils_charset_utf8_to_ucs4(s, slen, &c, &clen); if (err != PARSERUTILS_OK) { return (uint32_t) -1; } if (c == chr) { return index; } s += clen; slen -= clen; index++; } return (uint32_t) -1; }
void svgtiny_parse_color(dom_string *s, svgtiny_colour *c, struct svgtiny_parse_state *state) { char *ss = strndup(dom_string_data(s), dom_string_byte_length(s)); _svgtiny_parse_color(ss, c, state); free(ss); }
static duk_ret_t dukky_html_anchor_element_target_getter(duk_context *ctx) { /* Get private data for method */ html_anchor_element_private_t *priv = NULL; duk_push_this(ctx); duk_get_prop_string(ctx, -1, dukky_magic_string_private); priv = duk_get_pointer(ctx, -1); duk_pop_2(ctx); if (priv == NULL) { return 0; /* can do? No can do. */ } #line 34 "HTMLAnchorElement.bnd" dom_exception exc; dom_string *str; exc = dom_html_anchor_element_get_target((struct dom_html_anchor_element *)((node_private_t*)priv)->node, &str); if (exc != DOM_NO_ERR) { return 0; } if (str != NULL) { duk_push_lstring(ctx, dom_string_data(str), dom_string_length(str)); dom_string_unref(str); } else { duk_push_lstring(ctx, NULL, 0); } return 1; }
void svgtiny_parse_paint_attributes(dom_element *node, struct svgtiny_parse_state *state) { dom_string *attr; dom_exception exc; exc = dom_element_get_attribute(node, state->interned_fill, &attr); if (exc == DOM_NO_ERR && attr != NULL) { svgtiny_parse_color(attr, &state->fill, state); dom_string_unref(attr); } exc = dom_element_get_attribute(node, state->interned_stroke, &attr); if (exc == DOM_NO_ERR && attr != NULL) { svgtiny_parse_color(attr, &state->stroke, state); dom_string_unref(attr); } exc = dom_element_get_attribute(node, state->interned_stroke_width, &attr); if (exc == DOM_NO_ERR && attr != NULL) { state->stroke_width = svgtiny_parse_length(attr, state->viewport_width, *state); dom_string_unref(attr); } exc = dom_element_get_attribute(node, state->interned_style, &attr); if (exc == DOM_NO_ERR && attr != NULL) { char *style = strndup(dom_string_data(attr), dom_string_byte_length(attr)); const char *s; char *value; if ((s = strstr(style, "fill:"))) { s += 5; while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); _svgtiny_parse_color(value, &state->fill, state); free(value); } if ((s = strstr(style, "stroke:"))) { s += 7; while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); _svgtiny_parse_color(value, &state->stroke, state); free(value); } if ((s = strstr(style, "stroke-width:"))) { s += 13; while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); state->stroke_width = _svgtiny_parse_length(value, state->viewport_width, *state); free(value); } free(style); dom_string_unref(attr); } }
/** * Add an imagemap to the hashtable, creating it if it doesn't exist * * \param c The containing content * \param key The name of the imagemap * \param list List of map regions * \return true on succes, false otherwise */ static bool imagemap_add(html_content *c, dom_string *key, struct mapentry *list) { struct imagemap *map; unsigned int slot; assert(c != NULL); assert(key != NULL); assert(list != NULL); if (imagemap_create(c) == false) return false; map = calloc(1, sizeof(*map)); if (map == NULL) return false; /* \todo Stop relying on NULL termination of dom_string */ map->key = strdup(dom_string_data(key)); if (map->key == NULL) { free(map); return false; } map->list = list; slot = imagemap_hash(map->key); map->next = c->imagemaps[slot]; c->imagemaps[slot] = map; return true; }
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; }
/** * Callback to determine if a node is a linking element whose target has been * visited. * * \param pw HTML document * \param node DOM node * \param match Pointer to location to receive result * \return CSS_OK. * * \post \a match will contain true if the node matches and false otherwise. */ css_error node_is_visited(void *pw, void *node, bool *match) { nscss_select_ctx *ctx = pw; nsurl *url; nserror error; const struct url_data *data; dom_exception exc; dom_node *n = node; dom_string *s = NULL; *match = false; exc = dom_node_get_node_name(n, &s); if ((exc != DOM_NO_ERR) || (s == NULL)) { return CSS_NOMEM; } if (!dom_string_caseless_lwc_isequal(s, corestring_lwc_a)) { /* Can't be visited; not ancher element */ dom_string_unref(s); return CSS_OK; } /* Finished with node name string */ dom_string_unref(s); s = NULL; exc = dom_element_get_attribute(n, corestring_dom_href, &s); if ((exc != DOM_NO_ERR) || (s == NULL)) { /* Can't be visited; not got a URL */ return CSS_OK; } /* Make href absolute */ /* TODO: this duplicates what we do for box->href * should we put the absolute URL on the dom node? */ error = nsurl_join(ctx->base_url, dom_string_data(s), &url); /* Finished with href string */ dom_string_unref(s); if (error != NSERROR_OK) { /* Couldn't make nsurl object */ return CSS_NOMEM; } data = urldb_get_url_data(url); /* Visited if in the db and has * non-zero visit count */ if (data != NULL && data->visits > 0) *match = true; nsurl_unref(url); return CSS_OK; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
/** * 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; }
/** * 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; }
/** * 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; }
/** 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; }
/** * 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); }
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; }
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); } }
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; }
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; }
/** * 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; } }
/** * 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); }
/* Exported interface, documented in box_textarea.h */ bool box_textarea_create_textarea(html_content *html, struct box *box, struct dom_node *node) { dom_string *dom_text = NULL; dom_exception err; textarea_setup ta_setup; textarea_flags ta_flags; plot_font_style_t fstyle; bool read_only = false; struct form_control *gadget = box->gadget; const char *text; assert(gadget != NULL); assert(gadget->type == GADGET_TEXTAREA || gadget->type == GADGET_TEXTBOX || gadget->type == GADGET_PASSWORD); if (gadget->type == GADGET_TEXTAREA) { dom_html_text_area_element *textarea = (dom_html_text_area_element *) node; ta_flags = TEXTAREA_MULTILINE; err = dom_html_text_area_element_get_read_only( textarea, &read_only); if (err != DOM_NO_ERR) return false; /* Get the textarea's initial content */ err = dom_html_text_area_element_get_value(textarea, &dom_text); if (err != DOM_NO_ERR) return false; } else { dom_html_input_element *input = (dom_html_input_element *) node; err = dom_html_input_element_get_read_only( input, &read_only); if (err != DOM_NO_ERR) return false; if (gadget->type == GADGET_PASSWORD) ta_flags = TEXTAREA_PASSWORD; else ta_flags = TEXTAREA_DEFAULT; /* Get initial text */ err = dom_html_input_element_get_value(input, &dom_text); if (err != DOM_NO_ERR) return false; } if (dom_text != NULL) { text = dom_string_data(dom_text); } else { /* No initial text, or failed reading it; * use a blank string */ text = ""; } if (read_only) ta_flags |= TEXTAREA_READONLY; gadget->data.text.data.gadget = gadget; font_plot_style_from_css(gadget->box->style, &fstyle); /* Reset to correct values by layout */ ta_setup.width = 200; ta_setup.height = 20; ta_setup.pad_top = 4; ta_setup.pad_right = 4; ta_setup.pad_bottom = 4; ta_setup.pad_left = 4; /* Set remaining data */ ta_setup.border_width = 0; ta_setup.border_col = 0x000000; ta_setup.text = fstyle; ta_setup.text.background = NS_TRANSPARENT; /* Make selected text either black or white, as gives greatest contrast * with background colour. */ ta_setup.selected_bg = fstyle.foreground; ta_setup.selected_text = colour_to_bw_furthest(ta_setup.selected_bg); /* Hand reference to dom text over to gadget */ gadget->data.text.initial = dom_text; gadget->data.text.ta = textarea_create(ta_flags, &ta_setup, box_textarea_callback, &gadget->data.text.data); if (gadget->data.text.ta == NULL) { return false; } if (!textarea_set_text(gadget->data.text.ta, text)) return false; return true; }
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; }
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; }