From 9d56448775bfce329452326dfdc5a256f9c1d8e9 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 12 Dec 2004 22:00:30 +0000 Subject: [project @ 2004-12-12 22:00:30 by bursa] xcalloc/xrealloc/xstrdup-purge week, part 2. svn path=/import/netsurf/; revision=1401 --- render/box.c | 309 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 175 insertions(+), 134 deletions(-) (limited to 'render/box.c') diff --git a/render/box.c b/render/box.c index 74dc502b6..7eb0f5774 100644 --- a/render/box.c +++ b/render/box.c @@ -140,8 +140,7 @@ static struct box_result box_button(xmlNode *n, struct box_status *status, struct css_style *style); static struct box_result box_frameset(xmlNode *n, struct box_status *status, struct css_style *style); -static void add_option(xmlNode* n, struct form_control* current_select, - const char *text); +static bool box_select_add_option(struct form_control *control, xmlNode *n); static void box_normalise_block(struct box *block, pool box_pool); static void box_normalise_table(struct box *table, pool box_pool); static void box_normalise_table_spans( struct box *table ); @@ -747,7 +746,12 @@ no_memory: /** - * Get the style for an element + * Get the style for an element. + * + * \param c content of type CONTENT_HTML that is being processed + * \param parent_style style at this point in xml tree + * \param n node in xml tree + * \return the new style, or 0 on memory exhaustion * * The style is collected from three sources: * 1. any styles for this element in the document stylesheet(s) @@ -759,18 +763,23 @@ struct css_style * box_get_style(struct content *c, struct css_style *parent_style, xmlNode *n) { - struct css_style * style = xcalloc(1, sizeof(struct css_style)); - struct css_style style_new; - char * s; + char *s; unsigned int i; - url_func_result res; - struct content **stylesheet = c->data.html.stylesheet_content; unsigned int stylesheet_count = c->data.html.stylesheet_count; + struct content **stylesheet = c->data.html.stylesheet_content; + struct css_style *style; + struct css_style style_new; + char *url; + url_func_result res; + + style = malloc(sizeof (struct css_style)); + if (!style) + return 0; memcpy(style, parent_style, sizeof(struct css_style)); memcpy(&style_new, &css_blank_style, sizeof(struct css_style)); for (i = 0; i != stylesheet_count; i++) { - if (stylesheet[i] != 0) { + if (stylesheet[i]) { assert(stylesheet[i]->type == CONTENT_CSS); css_get_style(stylesheet[i], n, &style_new); } @@ -778,20 +787,24 @@ struct css_style * box_get_style(struct content *c, css_cascade(style, &style_new); /* This property only applies to the body element, if you believe - the spec. Many browsers seem to allow it on other elements too, - so let's be generic ;) - */ - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "background")) != NULL) { - style->background_image.type = CSS_BACKGROUND_IMAGE_URI; - /**\todo This will leak memory. */ - res = url_join(s, c->data.html.base_url, &style->background_image.uri); - /* if url is equivalent to the parent's url, - * we've got infinite inclusion. stop it here. - * also bail if url_join failed. - */ - if (res != URL_FUNC_OK || - strcasecmp(style->background_image.uri, c->data.html.base_url) == 0) - style->background_image.type = CSS_BACKGROUND_IMAGE_NONE; + * the spec. Many browsers seem to allow it on other elements too, + * so let's be generic ;) */ + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "background"))) { + res = url_join(s, c->data.html.base_url, &url); + if (res == URL_FUNC_NOMEM) { + free(style); + return 0; + } else if (res == URL_FUNC_OK) { + /* if url is equivalent to the parent's url, + * we've got infinite inclusion: ignore */ + if (strcmp(url, c->data.html.base_url) == 0) + free(url); + else { + style->background_image.type = + CSS_BACKGROUND_IMAGE_URI; + style->background_image.uri = url; + } + } xmlFree(s); } @@ -818,7 +831,7 @@ struct css_style * box_get_style(struct content *c, if (value < 0 || strlen(s) == 0) { /* ignore negative values and height="" */ } else if (strrchr(s, '%')) { - /*the specification doesn't make clear what + /* the specification doesn't make clear what * percentage heights mean, so ignore them */ } else { style->height.height = CSS_HEIGHT_LENGTH; @@ -996,10 +1009,14 @@ struct box_result box_a(xmlNode *n, struct box_status *status, /* both specified and they match => ok */ id = status->id; } - else if (!status->id) + else if (!status->id) { /* only name specified */ id = squash_whitespace(s1); - else + if (!id) { + xmlFree(s1); + return (struct box_result) {0, false, true}; + } + } else /* both specified but no match */ id = 0; @@ -1012,6 +1029,9 @@ struct box_result box_a(xmlNode *n, struct box_status *status, if (id && id != status->id) free(id); + if (!box) + return (struct box_result) {0, false, true}; + return (struct box_result) {box, true, false}; } @@ -1022,7 +1042,8 @@ struct box_result box_body(xmlNode *n, struct box_status *status, status->content->data.html.background_colour = style->background_color; box = box_create(style, status->href, status->title, status->id, status->content->data.html.box_pool); - + if (!box) + return (struct box_result) {0, false, true}; return (struct box_result) {box, true, false}; } @@ -1032,6 +1053,8 @@ struct box_result box_br(xmlNode *n, struct box_status *status, struct box *box; box = box_create(style, status->href, status->title, status->id, status->content->data.html.box_pool); + if (!box) + return (struct box_result) {0, false, true}; box->type = BOX_BR; return (struct box_result) {box, false, false}; } @@ -1046,45 +1069,51 @@ struct box_result box_image(xmlNode *n, struct box_status *status, box = box_create(style, status->href, status->title, status->id, status->content->data.html.box_pool); + if (!box) + return (struct box_result) {0, false, true}; /* handle alt text */ if ((s2 = xmlGetProp(n, (const xmlChar *) "alt")) != NULL) { box->text = squash_whitespace(s2); + xmlFree(s2); + if (!box->text) + return (struct box_result) {0, false, true}; box->length = strlen(box->text); box->font = nsfont_open(status->content->data.html.fonts, style); - xmlFree(s2); } - /* img without src is an error */ - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src")) == NULL) - return (struct box_result) {box, false, false}; - /* imagemap associated with this image */ if ((map = xmlGetProp(n, (const xmlChar *) "usemap")) != NULL) { - if (map[0] == '#') { - box->usemap = xstrdup(map+1); - } - else { - box->usemap = xstrdup(map); - } + if (map[0] == '#') + box->usemap = strdup(map + 1); + else + box->usemap = strdup(map); xmlFree(map); + if (!box->usemap) { + free(box->text); + return (struct box_result) {0, false, true}; + } } + /* img without src is an error */ + if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src")) == NULL) + return (struct box_result) {box, false, false}; + /* remove leading and trailing whitespace */ s1 = strip(s); res = url_join(s1, status->content->data.html.base_url, &url); - /* if url is equivalent to the parent's url, - * we've got infinite inclusion. stop it here. - * also bail if url_join failed. - */ - if (res != URL_FUNC_OK || - strcasecmp(url, status->content->data.html.base_url) == 0) { - xmlFree(s); + xmlFree(s); + if (res == URL_FUNC_NOMEM) { + free(box->text); + return (struct box_result) {0, false, true}; + } else if (res == URL_FUNC_FAILED) { return (struct box_result) {box, false, false}; } - LOG(("image '%s'", url)); - xmlFree(s); + if (strcmp(url, status->content->data.html.base_url) == 0) + /* if url is equivalent to the parent's url, + * we've got infinite inclusion: ignore */ + return (struct box_result) {box, false, false}; /* start fetch */ html_fetch_object(status->content, url, box, image_types, @@ -1096,35 +1125,41 @@ struct box_result box_image(xmlNode *n, struct box_status *status, struct box_result box_form(xmlNode *n, struct box_status *status, struct css_style *style) { - char *s, *s2; + char *action, *method, *enctype; + form_method fmethod; struct box *box; struct form *form; box = box_create(style, status->href, status->title, status->id, status->content->data.html.box_pool); + if (!box) + return (struct box_result) {0, false, true}; - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "action")) == NULL) { + if (!(action = (char *) xmlGetProp(n, (const xmlChar *) "action"))) { /* the action attribute is required */ return (struct box_result) {box, true, false}; } - status->current_form = form = xcalloc(1, sizeof(*form)); - form->action = s; - - form->method = method_GET; - if ((s = (char *) xmlGetProp(n, (const xmlChar *) "method")) != NULL) { - if (strcasecmp(s, "post") == 0) { - form->method = method_POST_URLENC; - if ((s2 = (char *) xmlGetProp(n, (const xmlChar *) "enctype")) != NULL) { - if (strcasecmp(s2, "multipart/form-data") == 0) - form->method = method_POST_MULTIPART; - xmlFree(s2); + fmethod = method_GET; + if ((method = (char *) xmlGetProp(n, (const xmlChar *) "method"))) { + if (strcasecmp(method, "post") == 0) { + fmethod = method_POST_URLENC; + if ((enctype = (char *) xmlGetProp(n, + (const xmlChar *) "enctype"))) { + if (strcasecmp(enctype, + "multipart/form-data") == 0) + fmethod = method_POST_MULTIPART; + xmlFree(enctype); } } - xmlFree(s); + xmlFree(method); } - form->controls = form->last_control = 0; + status->current_form = form = form_new(action, fmethod); + if (!form) { + xmlFree(action); + return (struct box_result) {0, false, true}; + } return (struct box_result) {box, true, false}; } @@ -1145,29 +1180,25 @@ struct box_result box_textarea(xmlNode *n, struct box_status *status, box = box_create(style, NULL, 0, status->id, status->content->data.html.box_pool); + if (!box) + return (struct box_result) {0, false, true}; box->type = BOX_INLINE_BLOCK; box->gadget = form_new_control(GADGET_TEXTAREA); - if (!box->gadget) { - free(box); + if (!box->gadget) return (struct box_result) {0, false, true}; - } box->gadget->box = box; - if (status->current_form) - form_add_control(status->current_form, box->gadget); - else - box->gadget->form = 0; if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name")) != NULL) { box->gadget->name = strdup(s); xmlFree(s); - if (!box->gadget->name) { - box_free(box); + if (!box->gadget->name) return (struct box_result) {0, false, true}; - } } inline_container = box_create(0, 0, 0, 0, status->content->data.html.box_pool); + if (!inline_container) + return (struct box_result) {0, false, true}; inline_container->type = BOX_INLINE_CONTAINER; box_add_child(box, inline_container); @@ -1184,6 +1215,8 @@ struct box_result box_textarea(xmlNode *n, struct box_status *status, inline_box = box_create(style, 0, 0, 0, status->content->data.html.box_pool); + if (!inline_box) + return (struct box_result) {0, false, true}; inline_box->type = BOX_INLINE; inline_box->style_clone = 1; inline_box->text = s; @@ -1200,6 +1233,8 @@ struct box_result box_textarea(xmlNode *n, struct box_status *status, /* BOX_BR */ br_box = box_create(style, 0, 0, 0, status->content->data.html.box_pool); + if (!br_box) + return (struct box_result) {0, false, true}; br_box->type = BOX_BR; br_box->style_clone = 1; box_add_child(inline_container, br_box); @@ -1211,6 +1246,9 @@ struct box_result box_textarea(xmlNode *n, struct box_status *status, } xmlFree(content); + if (status->current_form) + form_add_control(status->current_form, box->gadget); + return (struct box_result) {box, false, false}; } @@ -1228,11 +1266,6 @@ struct box_result box_select(xmlNode *n, struct box_status *status, if (!gadget) return (struct box_result) {0, false, true}; - if (status->current_form) - form_add_control(status->current_form, gadget); - else - gadget->form = 0; - gadget->data.select.multiple = false; if ((s = (char *) xmlGetProp(n, (const xmlChar *) "multiple")) != NULL) { gadget->data.select.multiple = true; @@ -1244,19 +1277,16 @@ struct box_result box_select(xmlNode *n, struct box_status *status, gadget->data.select.num_items = 0; gadget->data.select.num_selected = 0; - for (c = n->children; c != 0; c = c->next) { + for (c = n->children; c; c = c->next) { if (strcmp((const char *) c->name, "option") == 0) { - xmlChar *content = xmlNodeGetContent(c); - add_option(c, gadget, content); - xmlFree(content); - gadget->data.select.num_items++; + if (!box_select_add_option(gadget, c)) + goto no_memory; } else if (strcmp((const char *) c->name, "optgroup") == 0) { for (c2 = c->children; c2; c2 = c2->next) { - if (strcmp((const char *) c2->name, "option") == 0) { - xmlChar *content = xmlNodeGetContent(c2); - add_option(c2, gadget, content); - xmlFree(content); - gadget->data.select.num_items++; + if (strcmp((const char *) c2->name, + "option") == 0) { + if (!box_select_add_option(gadget, c2)) + goto no_memory; } } } @@ -1271,22 +1301,27 @@ struct box_result box_select(xmlNode *n, struct box_status *status, if ((s = (char *) xmlGetProp(n, (const xmlChar *) "name")) != NULL) { gadget->name = strdup(s); xmlFree(s); - if (!gadget->name) { - form_free_control(gadget); - return (struct box_result) {0, false, true}; - } + if (!gadget->name) + goto no_memory; } - box = box_create(style, NULL, 0, status->id, status->content->data.html.box_pool); + box = box_create(style, NULL, 0, status->id, + status->content->data.html.box_pool); + if (!box) + goto no_memory; box->type = BOX_INLINE_BLOCK; box->gadget = gadget; gadget->box = box; inline_container = box_create(0, 0, 0, 0, status->content->data.html.box_pool); + if (!inline_container) + goto no_memory; inline_container->type = BOX_INLINE_CONTAINER; inline_box = box_create(style, 0, 0, 0, status->content->data.html.box_pool); + if (!inline_box) + goto no_memory; inline_box->type = BOX_INLINE; inline_box->style_clone = 1; box_add_child(inline_container, inline_box); @@ -1301,65 +1336,71 @@ struct box_result box_select(xmlNode *n, struct box_status *status, } if (gadget->data.select.num_selected == 0) - inline_box->text = xstrdup(messages_get("Form_None")); + inline_box->text = strdup(messages_get("Form_None")); else if (gadget->data.select.num_selected == 1) - inline_box->text = xstrdup(gadget->data.select.current->text); + inline_box->text = strdup(gadget->data.select.current->text); else - inline_box->text = xstrdup(messages_get("Form_Many")); + inline_box->text = strdup(messages_get("Form_Many")); + if (!inline_box->text) + goto no_memory; inline_box->length = strlen(inline_box->text); inline_box->font = nsfont_open(status->content->data.html.fonts, style); + if (status->current_form) + form_add_control(status->current_form, gadget); + return (struct box_result) {box, false, false}; + +no_memory: + form_free_control(gadget); + return (struct box_result) {0, false, true}; } -void add_option(xmlNode* n, struct form_control* current_select, const char *text) -{ - struct form_option *option = xcalloc(1, sizeof(struct form_option)); - char *s; - - if ((text = squash_whitespace(text)) == NULL) { - free(option); - return; - } +/** + * Add an option to a form select control. + * + * \param control select containing the option + * \param n xml element node for