From c9bd6fa9fce386526ea1327adea56128648f3355 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Mon, 9 Aug 2004 16:11:58 +0000 Subject: [project @ 2004-08-09 16:11:58 by jmb] Rework the interface of the URL handing module to allow for multiple error types. Modify save_complete URL rewriting appropriately. svn path=/import/netsurf/; revision=1206 --- content/fetch.c | 6 +- content/fetchcache.c | 5 +- css/css.c | 5 +- css/ruleset.c | 13 +-- desktop/browser.c | 27 ++++--- desktop/loginlist.c | 16 ++-- render/box.c | 67 +++++++++------- render/html.c | 11 ++- riscos/401login.c | 5 +- riscos/download.c | 3 +- riscos/hotlist.c | 10 ++- riscos/save.c | 3 +- riscos/save_complete.c | 66 +++++++++------ riscos/window.c | 5 +- utils/url.c | 214 +++++++++++++++++++++++++++---------------------- utils/url.h | 14 +++- 16 files changed, 273 insertions(+), 197 deletions(-) diff --git a/content/fetch.c b/content/fetch.c index 81f5e3a26..cb1353f98 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -227,12 +227,16 @@ struct fetch * fetch_start(char *url, char *referer, CURLcode code; CURLMcode codem; struct curl_slist *slist; + url_func_result res; fetch = malloc(sizeof (*fetch)); if (!fetch) return 0; - host = url_host(url); + res = url_host(url, &host); + /* we only fail memory exhaustion */ + if (res == URL_FUNC_NOMEM) + goto failed; LOG(("fetch %p, url '%s'", fetch, url)); diff --git a/content/fetchcache.c b/content/fetchcache.c index e22a8ae5b..02ce109b1 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -206,6 +206,7 @@ void fetchcache_callback(fetch_msg msg, void *p, const char *data, char **params; unsigned int i; union content_msg_data msg_data; + url_func_result result; switch (msg) { case FETCH_TYPE: @@ -283,8 +284,8 @@ void fetchcache_callback(fetch_msg msg, void *p, const char *data, c->fetch = 0; /* redirect URLs must be absolute by HTTP/1.1, but many sites send * relative ones: treat them as relative to requested URL */ - url = url_join(data, c->url); - if (url) { + result = url_join(data, c->url, &url); + if (result == URL_FUNC_OK) { msg_data.redirect = url; content_broadcast(c, CONTENT_MSG_REDIRECT, msg_data); free(url); diff --git a/css/css.c b/css/css.c index c4bbb8025..fa3f6f3bb 100644 --- a/css/css.c +++ b/css/css.c @@ -579,6 +579,7 @@ void css_atimport(struct content *c, struct css_node *node) unsigned int i; char **import_url; struct content **import_content; + url_func_result res; LOG(("@import rule")); @@ -666,8 +667,8 @@ void css_atimport(struct content *c, struct css_node *node) return; } - url1 = url_join(url, c->url); - if (!url1) { + res = url_join(url, c->url, &url1); + if (res != URL_FUNC_OK) { free(url); return; } diff --git a/css/ruleset.c b/css/ruleset.c index f0ab22d1c..90ca00226 100644 --- a/css/ruleset.c +++ b/css/ruleset.c @@ -621,6 +621,7 @@ bool parse_uri(const struct css_node *v, char **uri) bool string = false; const char *u; char *t, *url; + url_func_result res; switch (v->type) { case CSS_NODE_URI: @@ -650,11 +651,11 @@ bool parse_uri(const struct css_node *v, char **uri) * content is the parent HTML content */ if (v->stylesheet->type == CONTENT_HTML) - *uri = url_join(url, v->stylesheet->data.html.base_url); + res = url_join(url, v->stylesheet->data.html.base_url, uri); else - *uri = url_join(url, v->stylesheet->url); + res = url_join(url, v->stylesheet->url, uri); free(url); - if (!*uri) + if (res != URL_FUNC_OK) return false; break; case CSS_NODE_STRING: @@ -663,11 +664,11 @@ bool parse_uri(const struct css_node *v, char **uri) return false; if (v->stylesheet->type == CONTENT_HTML) - *uri = url_join(url, v->stylesheet->data.html.base_url); + res = url_join(url, v->stylesheet->data.html.base_url, uri); else - *uri = url_join(url, v->stylesheet->url); + res = url_join(url, v->stylesheet->url, uri); free(url); - if (!*uri) + if (res != URL_FUNC_OK) return false; break; default: diff --git a/desktop/browser.c b/desktop/browser.c index 6e797a97e..36b6a9245 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -149,11 +149,12 @@ void browser_window_go_post(struct browser_window *bw, const char *url, struct content *c; char *url2; char *hash; + url_func_result res; LOG(("bw %p, url %s", bw, url)); - url2 = url_normalize(url); - if (!url2) { + res = url_normalize(url, &url2); + if (res != URL_FUNC_OK) { LOG(("failed to normalize url %s", url)); return; } @@ -602,6 +603,7 @@ void browser_window_mouse_click_html(struct browser_window *bw, struct content *content = c; struct content *gadget_content = c; struct form_control *gadget = 0; + url_func_result res; /* search the box tree for a link, imagemap, or form control */ while ((box = box_at_point(box, x, y, &box_x, &box_y, &content))) { @@ -664,10 +666,10 @@ void browser_window_mouse_click_html(struct browser_window *bw, /* drop through */ case GADGET_SUBMIT: if (gadget->form) { - url = url_join(gadget->form->action, base_url); + res = url_join(gadget->form->action, base_url, &url); snprintf(status_buffer, sizeof status_buffer, messages_get("FormSubmit"), - url ? url : + (res == URL_FUNC_OK) ? url : gadget->form->action); status = status_buffer; pointer = GUI_POINTER_POINT; @@ -713,8 +715,8 @@ void browser_window_mouse_click_html(struct browser_window *bw, } } else if (href) { - url = url_join(href, base_url); - if (!url) + res = url_join(href, base_url, &url); + if (res != URL_FUNC_OK) return; if (title) { @@ -1634,6 +1636,7 @@ void browser_form_submit(struct browser_window *bw, struct form *form, { char *data = 0, *url = 0, *url1 = 0, *base; struct form_successful_control *success; + url_func_result res; assert(form); assert(bw->current_content->type == CONTENT_HTML); @@ -1659,8 +1662,8 @@ void browser_form_submit(struct browser_window *bw, struct form *form, else { sprintf(url, "%s?%s", form->action, data); } - url1 = url_join(url, base); - if (!url1) + res = url_join(url, base, &url1); + if (res != URL_FUNC_OK) break; browser_window_go(bw, url1); break; @@ -1672,15 +1675,15 @@ void browser_form_submit(struct browser_window *bw, struct form *form, warn_user("NoMemory", 0); return; } - url = url_join(form->action, base); - if (!url) + res = url_join(form->action, base, &url); + if (res != URL_FUNC_OK) break; browser_window_go_post(bw, url, data, 0, true); break; case method_POST_MULTIPART: - url = url_join(form->action, base); - if (!url) + res = url_join(form->action, base, &url); + if (res != URL_FUNC_OK) break; browser_window_go_post(bw, url, 0, success, true); break; diff --git a/desktop/loginlist.c b/desktop/loginlist.c index 1baab81ac..3161bbd11 100644 --- a/desktop/loginlist.c +++ b/desktop/loginlist.c @@ -31,10 +31,13 @@ static struct login *loginlist = &login; void login_list_add(char *host, char* logindets) { struct login *nli = xcalloc(1, sizeof(*nli)); - char *temp = url_host(host); + char *temp; char *i; + url_func_result res; - assert(temp); + res = url_host(host, &temp); + + assert(res == URL_FUNC_OK); /* Go back to the path base ie strip the document name * eg. http://www.blah.com/blah/test.htm becomes @@ -75,6 +78,7 @@ struct login *login_list_get(char *url) { char *temp, *host; char *i; int reached_scheme = 0; + url_func_result res; if (url == NULL) return NULL; @@ -83,8 +87,8 @@ struct login *login_list_get(char *url) { (strncasecmp(url, "https://", 8) != 0)) return NULL; - host = url_host(url); - if (host == 0 || strlen(host) == 0) return NULL; + res = url_host(url, &host); + if (res != URL_FUNC_OK || strlen(host) == 0) return NULL; temp = xstrdup(url); @@ -93,8 +97,8 @@ struct login *login_list_get(char *url) { */ if (strlen(host) > strlen(temp)) { xfree(temp); - temp = url_host(url); - if (temp == 0 || strlen(temp) == 0) { + res = url_host(url, &temp); + if (res != URL_FUNC_OK || strlen(temp) == 0) { xfree(host); return NULL; } diff --git a/render/box.c b/render/box.c index 32d643fb5..5776501b0 100644 --- a/render/box.c +++ b/render/box.c @@ -640,6 +640,7 @@ struct css_style * box_get_style(struct content *c, struct css_style style_new; char * s; unsigned int i; + url_func_result res; memcpy(style, parent_style, sizeof(struct css_style)); memcpy(&style_new, &css_blank_style, sizeof(struct css_style)); @@ -658,12 +659,12 @@ struct css_style * box_get_style(struct content *c, if ((s = (char *) xmlGetProp(n, (const xmlChar *) "background"))) { style->background_image.type = CSS_BACKGROUND_IMAGE_URI; /**\todo This will leak memory. */ - style->background_image.uri = url_join(s, c->data.html.base_url); + 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 (!style->background_image.uri || + if (res != URL_FUNC_OK || strcasecmp(style->background_image.uri, c->data.html.base_url) == 0) style->background_image.type = CSS_BACKGROUND_IMAGE_NONE; xmlFree(s); @@ -897,6 +898,7 @@ struct box_result box_image(xmlNode *n, struct box_status *status, struct box *box; char *s, *url, *s1, *map; xmlChar *s2; + url_func_result res; box = box_create(style, status->href, status->title, status->id, status->content->data.html.box_pool); @@ -926,12 +928,12 @@ struct box_result box_image(xmlNode *n, struct box_status *status, /* remove leading and trailing whitespace */ s1 = strip(s); - url = url_join(s1, status->content->data.html.base_url); + 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 (!url || + if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) { xmlFree(s); return (struct box_result) {box, false, false}; @@ -1224,6 +1226,7 @@ struct box_result box_input(xmlNode *n, struct box_status *status, struct box* box = NULL; struct form_control *gadget = NULL; char *s, *type, *url; + url_func_result res; type = (char *) xmlGetProp(n, (const xmlChar *) "type"); @@ -1356,12 +1359,13 @@ struct box_result box_input(xmlNode *n, struct box_status *status, gadget->box = box; gadget->type = GADGET_IMAGE; if ((s = (char *) xmlGetProp(n, (const xmlChar*) "src"))) { - url = url_join(s, status->content->data.html.base_url); + res = url_join(s, 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 (url && strcasecmp(url, status->content->data.html.base_url) != 0) + if (res == URL_FUNC_OK && + strcasecmp(url, status->content->data.html.base_url) != 0) html_fetch_object(status->content, url, box, image_types, status->content->available_width, @@ -2049,6 +2053,7 @@ struct box_result box_object(xmlNode *n, struct box_status *status, struct plugin_params* pp; char *s, *url = NULL, *map; xmlNode *c; + url_func_result res; box = box_create(style, status->href, 0, status->id, status->content->data.html.box_pool); @@ -2065,12 +2070,12 @@ struct box_result box_object(xmlNode *n, struct box_status *status, /* object data */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "data"))) { - url = url_join(s, status->content->data.html.base_url); + res = url_join(s, 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 (!url || strcasecmp(url, status->content->data.html.base_url) == 0) { + if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) { free(po); xmlFree(s); return (struct box_result) {box, true, true}; @@ -2193,6 +2198,7 @@ struct box_result box_embed(xmlNode *n, struct box_status *status, struct plugin_params *pp; char *s, *url = NULL; xmlAttr *a; + url_func_result res; box = box_create(style, status->href, 0, status->id, status->content->data.html.box_pool); @@ -2209,12 +2215,12 @@ struct box_result box_embed(xmlNode *n, struct box_status *status, /* embed src */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) { - url = url_join(s, status->content->data.html.base_url); + res = url_join(s, 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 (!url || strcasecmp(url, status->content->data.html.base_url) == 0) { + if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) { free(po); xmlFree(s); return (struct box_result) {box, false, true}; @@ -2268,6 +2274,7 @@ struct box_result box_applet(xmlNode *n, struct box_status *status, struct plugin_params *pp; char *s, *url = NULL; xmlNode *c; + url_func_result res; box = box_create(style, status->href, 0, status->id, status->content->data.html.box_pool); @@ -2284,12 +2291,12 @@ struct box_result box_applet(xmlNode *n, struct box_status *status, /* code */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "code"))) { - url = url_join(s, status->content->data.html.base_url); + res = url_join(s, 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 (!url || strcasecmp(url, status->content->data.html.base_url) == 0) { + if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) { free(po); xmlFree(s); return (struct box_result) {box, true, false}; @@ -2376,6 +2383,7 @@ struct box_result box_iframe(xmlNode *n, struct box_status *status, struct box *box; struct object_params *po; char *s, *url = NULL; + url_func_result res; box = box_create(style, status->href, 0, status->id, status->content->data.html.box_pool); @@ -2392,12 +2400,12 @@ struct box_result box_iframe(xmlNode *n, struct box_status *status, /* iframe src */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) { - url = url_join(s, status->content->data.html.base_url); + res = url_join(s, 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 (!url || strcasecmp(url, status->content->data.html.base_url) == 0) { + if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) { free(po); xmlFree(s); return (struct box_result) {box, false, true}; @@ -2430,16 +2438,17 @@ bool plugin_decode(struct content* content, char* url, struct box* box, struct object_params* po) { struct plugin_params * pp; + url_func_result res; /* Check if the codebase attribute is defined. * If it is not, set it to the codebase of the current document. */ if(po->codebase == 0) - po->codebase = url_join("./", content->data.html.base_url); + res = url_join("./", content->data.html.base_url, &po->codebase); else - po->codebase = url_join(po->codebase, content->data.html.base_url); + res = url_join(po->codebase, content->data.html.base_url, &po->codebase); - if (!po->codebase) + if (res != URL_FUNC_OK) return false; /* Set basehref */ @@ -2464,13 +2473,14 @@ bool plugin_decode(struct content* content, char* url, struct box* box, pp = pp->next); if(pp == 0) return false; - url = url_join(pp->value, po->basehref); - if (!url) + res = url_join(pp->value, po->basehref, &url); + if (res != URL_FUNC_OK) return false; /* munge the codebase */ - po->codebase = url_join("./", - content->data.html.base_url); - if (!po->codebase) + res = url_join("./", + content->data.html.base_url, + &po->codebase); + if (res != URL_FUNC_OK) return false; } else { @@ -2479,8 +2489,8 @@ bool plugin_decode(struct content* content, char* url, struct box* box, } } else { - url = url_join(po->classid, po->codebase); - if (!url) + res = url_join(po->classid, po->codebase, &url); + if (res != URL_FUNC_OK) return false; /* The java plugin doesn't need the .class extension @@ -2492,8 +2502,8 @@ bool plugin_decode(struct content* content, char* url, struct box* box, } } else { - url = url_join(po->data, po->codebase); - if (!url) + res = url_join(po->data, po->codebase, &url); + if (res != URL_FUNC_OK) return false; } @@ -2537,6 +2547,7 @@ struct box_result box_frameset(xmlNode *n, struct box_status *status, struct box_result r; struct box_multi_length *row_height = 0, *col_width = 0; xmlNode *c; + url_func_result res; box = box_create(style, 0, status->title, status->id, status->content->data.html.box_pool); @@ -2676,12 +2687,12 @@ struct box_result box_frameset(xmlNode *n, struct box_status *status, } s1 = strip(s); - url = url_join(s1, status->content->data.html.base_url); + 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 (!url || strcasecmp(url, status->content->data.html.base_url) == 0) { + if (res != URL_FUNC_OK || strcasecmp(url, status->content->data.html.base_url) == 0) { xmlFree(s); c = c->next; continue; diff --git a/render/html.c b/render/html.c index 7bda3b02a..b19e99c30 100644 --- a/render/html.c +++ b/render/html.c @@ -304,8 +304,10 @@ void html_head(struct content *c, xmlNode *head) } else if (strcmp(node->name, "base") == 0) { char *href = (char *) xmlGetProp(node, (const xmlChar *) "href"); if (href) { - char *url = url_normalize(href); - if (url) { + char *url; + url_func_result res; + res = url_normalize(href, &url); + if (res == URL_FUNC_OK) { free(c->data.html.base_url); c->data.html.base_url = url; } @@ -330,6 +332,7 @@ void html_find_stylesheets(struct content *c, xmlNode *head) unsigned int i = STYLESHEET_START; unsigned int last_active = 0; union content_msg_data msg_data; + url_func_result res; /* stylesheet 0 is the base style sheet, * stylesheet 1 is the adblocking stylesheet, @@ -414,9 +417,9 @@ void html_find_stylesheets(struct content *c, xmlNode *head) /* TODO: only the first preferred stylesheets (ie. those with a * title attribute) should be loaded (see HTML4 14.3) */ - url = url_join(href, c->data.html.base_url); + res = url_join(href, c->data.html.base_url, &url); xmlFree(href); - if (!url) + if (res != URL_FUNC_OK) continue; LOG(("linked stylesheet %i '%s'", i, url)); diff --git a/riscos/401login.c b/riscos/401login.c index 8beaac9be..9edef15a8 100644 --- a/riscos/401login.c +++ b/riscos/401login.c @@ -46,10 +46,11 @@ void ro_gui_401login_init(void) void gui_401login_open(struct browser_window *bw, struct content *c, char *realm) { char *murl, *host; + url_func_result res; murl = c->url; - host = url_host(murl); - assert(host); + res = url_host(murl, &host); + assert(res == URL_FUNC_OK); bwin = bw; ro_gui_401login_open(bw->window->window, host, realm, murl); diff --git a/riscos/download.c b/riscos/download.c index 2a6d8d583..77aa9a217 100644 --- a/riscos/download.c +++ b/riscos/download.c @@ -128,6 +128,7 @@ struct gui_download_window *gui_download_window_create(const char *url, char temp_name[40]; struct gui_download_window *dw; os_error *error; + url_func_result res; dw = malloc(sizeof *dw); if (!dw) { @@ -188,7 +189,7 @@ struct gui_download_window *gui_download_window_create(const char *url, (osspriteop_id) dw->sprite_name; strcpy(dw->path, messages_get("SaveObject")); - if ((nice = url_nice(url))) { + if ((res = url_nice(url, &nice)) == URL_FUNC_OK) { strcpy(dw->path, nice); free(nice); } diff --git a/riscos/hotlist.c b/riscos/hotlist.c index 8a2a57100..de91fbad7 100644 --- a/riscos/hotlist.c +++ b/riscos/hotlist.c @@ -906,6 +906,7 @@ struct hotlist_entry *ro_gui_hotlist_create_entry(const char *title, const char *url, int filetype, struct hotlist_entry *folder) { struct hotlist_entry *entry; + url_func_result res; /* Check we have a title or a URL */ @@ -923,7 +924,8 @@ struct hotlist_entry *ro_gui_hotlist_create_entry(const char *title, use the URL instead */ entry->url = 0; - if ((url) && ((entry->url = url_normalize(url)) == 0)) { + if ((url) && ((res = url_normalize(url, &entry->url)) != URL_FUNC_OK)) { + /** \todo use correct error message */ warn_user("NoMemory", 0); free(entry->url); free(entry); @@ -2443,6 +2445,7 @@ void ro_gui_hotlist_dialog_click(wimp_pointer *pointer) { int close_icon, ok_icon; bool folder; bool add; + url_func_result res; /* Get our data */ @@ -2502,8 +2505,9 @@ void ro_gui_hotlist_dialog_click(wimp_pointer *pointer) { if (entry == NULL) return; if (url) { old_value = entry->url; - entry->url = url_normalize(url); - if (!entry->url) { + res = url_normalize(url, &entry->url); + if (res != URL_FUNC_OK) { + /** \todo use correct error message */ warn_user("NoMemory", 0); entry->url = old_value; return; diff --git a/riscos/save.c b/riscos/save.c index 14564f727..b73f57a8d 100644 --- a/riscos/save.c +++ b/riscos/save.c @@ -84,6 +84,7 @@ void ro_gui_save_open(gui_save_type save_type, struct content *c, const char *name = ""; const char *nice; os_error *error; + url_func_result res; assert(save_type == GUI_SAVE_HOTLIST_EXPORT_HTML || c); @@ -102,7 +103,7 @@ void ro_gui_save_open(gui_save_type save_type, struct content *c, /* filename */ name = gui_save_table[save_type].name; if (c) { - if ((nice = url_nice(c->url))) + if ((res = url_nice(c->url, &nice)) == URL_FUNC_OK) name = nice; } ro_gui_set_icon_string(dialog_saveas, ICON_SAVE_PATH, name); diff --git a/riscos/save_complete.c b/riscos/save_complete.c index fad990c20..519181188 100644 --- a/riscos/save_complete.c +++ b/riscos/save_complete.c @@ -342,6 +342,7 @@ char * rewrite_stylesheet_urls(const char *source, unsigned int size, unsigned int i; unsigned int imports = 0; regmatch_t match[11]; + url_func_result result; /* count number occurences of @import to (over)estimate result size */ /* can't use strstr because source is not 0-terminated string */ @@ -399,9 +400,9 @@ char * rewrite_stylesheet_urls(const char *source, unsigned int size, free(res); return 0; } - url = url_join(url2, base); + result = url_join(url2, base, (char**)&url); free(url2); - if (!url) { + if (result == URL_FUNC_NOMEM) { free(res); return 0; } @@ -410,17 +411,25 @@ char * rewrite_stylesheet_urls(const char *source, unsigned int size, memcpy(res + *osize, source + offset, match[0].rm_so); *osize += match[0].rm_so; - content = save_complete_list_find(url); - if (content) { - /* replace import */ - snprintf(buf, sizeof buf, "@import '%x'", - (unsigned int) content); - memcpy(res + *osize, buf, strlen(buf)); - *osize += strlen(buf); - } else { + if (result == URL_FUNC_OK) { + content = save_complete_list_find(url); + if (content) { + /* replace import */ + snprintf(buf, sizeof buf, "@import '%x'", + (unsigned int) content); + memcpy(res + *osize, buf, strlen(buf)); + *osize += strlen(buf); + } else { + /* copy import */ + memcpy(res + *osize, source + offset + match[0].rm_so, + match[0].rm_eo - match[0].rm_so); + *osize += match[0].rm_eo - match[0].rm_so; + } + } + else { /* copy import */ memcpy(res + *osize, source + offset + match[0].rm_so, - match[0].rm_eo - match[0].rm_so); + match[0].rm_eo - match[0].rm_so); *osize += match[0].rm_eo - match[0].rm_so; } @@ -570,6 +579,7 @@ bool rewrite_url(xmlNode *n, const char *attr, const char *base) char *url, *data; char rel[20]; struct content *content; + url_func_result res; if (!xmlHasProp(n, (const xmlChar *) attr)) return true; @@ -578,25 +588,29 @@ bool rewrite_url(xmlNode *n, const char *attr, const char *base) if (!data) return false; - url = url_join(data, base); + res = url_join(data, base, &url); xmlFree(data); - if (!url) + if (res == URL_FUNC_NOMEM) return false; - - content = save_complete_list_find(url); - if (content) { - /* found a match */ - free(url); - snprintf(rel, sizeof rel, "%x", (unsigned int) content); - if (!xmlSetProp(n, (const xmlChar *) attr, (xmlChar *) rel)) - return false; - } else { - /* no match found */ - if (!xmlSetProp(n, (const xmlChar *) attr, (xmlChar *) url)) { + else if (res == URL_FUNC_OK) { + content = save_complete_list_find(url); + if (content) { + /* found a match */ + free(url); + snprintf(rel, sizeof rel, "%x", + (unsigned int) content); + if (!xmlSetProp(n, (const xmlChar *) attr, + (xmlChar *) rel)) + return false; + } else { + /* no match found */ + if (!xmlSetProp(n, (const xmlChar *) attr, + (xmlChar *) url)) { + free(url); + return false; + } free(url); - return false; } - free(url); } return true; diff --git a/riscos/window.c b/riscos/window.c index ab945cb0d..a0715738d 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -1235,6 +1235,7 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar) char *url; os_error *error; wimp_pointer pointer; + url_func_result res; error = xwimp_get_pointer_info(&pointer); if (error) { @@ -1361,8 +1362,8 @@ bool ro_gui_window_keypress(struct gui_window *g, int key, bool toolbar) case wimp_KEY_RETURN: if (!toolbar) break; - url = url_normalize(g->url); - if (url) { + res = url_normalize(g->url, &url); + if (res == URL_FUNC_OK) { gui_window_set_url(g, url); browser_window_go(g->bw, url); free(url); diff --git a/utils/url.c b/utils/url.c index 09c2816bf..b1da7ce28 100644 --- a/utils/url.c +++ b/utils/url.c @@ -57,20 +57,21 @@ void url_init(void) * replaced with "/". Characters are unescaped if safe. */ -char *url_normalize(const char *url) +url_func_result url_normalize(const char *url, char **result) { char c; - char *res = 0; int m; int i; int len; bool http = false; regmatch_t match[10]; + (*result) = 0; + m = regexec(&url_re, url, 10, match, 0); if (m) { LOG(("url '%s' failed to match regex", url)); - return 0; + return URL_FUNC_FAILED; } len = strlen(url); @@ -78,27 +79,27 @@ char *url_normalize(const char *url) if (match[1].rm_so == -1) { /* scheme missing: add http:// and reparse */ LOG(("scheme missing: using http")); - res = malloc(strlen(url) + 13); - if (!res) { + (*result) = malloc(strlen(url) + 13); + if (!(*result)) { LOG(("malloc failed")); - return 0; + return URL_FUNC_NOMEM; } - strcpy(res, "http://"); - strcpy(res + 7, url); - m = regexec(&url_re, res, 10, match, 0); + strcpy((*result), "http://"); + strcpy((*result) + 7, url); + m = regexec(&url_re, (*result), 10, match, 0); if (m) { - LOG(("url '%s' failed to match regex", res)); - free(res); - return 0; + LOG(("url '%s' failed to match regex", (*result))); + free((*result)); + return URL_FUNC_FAILED; } len += 7; } else { - res = malloc(len + 6); - if (!res) { + (*result) = malloc(len + 6); + if (!(*result)) { LOG(("strdup failed")); - return 0; + return URL_FUNC_FAILED; } - strcpy(res, url); + strcpy((*result), url); } /*for (unsigned int i = 0; i != 10; i++) { @@ -113,55 +114,59 @@ char *url_normalize(const char *url) /* make scheme lower-case */ if (match[2].rm_so != -1) { for (i = match[2].rm_so; i != match[2].rm_eo; i++) - res[i] = tolower(res[i]); - if (match[2].rm_eo == 4 && res[0] == 'h' && res[1] == 't' && - res[2] == 't' && res[3] == 'p') + (*result)[i] = tolower((*result)[i]); + if (match[2].rm_eo == 4 && (*result)[0] == 'h' && + (*result)[1] == 't' && (*result)[2] == 't' && + (*result)[3] == 'p') http = true; } /* make empty path into "/" */ if (match[5].rm_so != -1 && match[5].rm_so == match[5].rm_eo) { - memmove(res + match[5].rm_so + 1, res + match[5].rm_so, + memmove((*result) + match[5].rm_so + 1, + (*result) + match[5].rm_so, len - match[5].rm_so + 1); - res[match[5].rm_so] = '/'; + (*result)[match[5].rm_so] = '/'; len++; } /* make host lower-case */ if (match[4].rm_so != -1) { for (i = match[4].rm_so; i != match[4].rm_eo; i++) { - if (res[i] == ':') { - if (http && res[i + 1] == '8' && - res[i + 2] == '0' && + if ((*result)[i] == ':') { + if (http && (*result)[i + 1] == '8' && + (*result)[i + 2] == '0' && i + 3 == match[4].rm_eo) { - memmove(res + i, res + i + 3, + memmove((*result) + i, + (*result) + i + 3, len - match[4].rm_eo); len -= 3; - res[len] = '\0'; + (*result)[len] = '\0'; } else if (i + 1 == match[4].rm_eo) { - memmove(res + i, res + i + 1, + memmove((*result) + i, + (*result) + i + 1, len - match[4].rm_eo); len--; - res[len] = '\0'; + (*result)[len] = '\0'; } break; } - res[i] = tolower(res[i]); + (*result)[i] = tolower((*result)[i]); } } /* unescape non-"reserved" escaped characters */ for (i = 0; i != len; i++) { - if (res[i] != '%') + if ((*result)[i] != '%') continue; - c = tolower(res[i + 1]); + c = tolower((*result)[i + 1]); if ('0' <= c && c <= '9') m = 16 * (c - '0'); else if ('a' <= c && c <= 'f') m = 16 * (c - 'a' + 10); else continue; - c = tolower(res[i + 2]); + c = tolower((*result)[i + 2]); if ('0' <= c && c <= '9') m += c - '0'; else if ('a' <= c && c <= 'f') @@ -175,12 +180,12 @@ char *url_normalize(const char *url) continue; } - res[i] = m; - memmove(res + i + 1, res + i + 3, len - i - 2); + (*result)[i] = m; + memmove((*result) + i + 1, (*result) + i + 3, len - i - 2); len -= 2; } - return res; + return URL_FUNC_OK; } @@ -192,12 +197,11 @@ char *url_normalize(const char *url) * \return an absolute URL, allocated on the heap, or 0 on failure */ -char *url_join(const char *rel, const char *base) +url_func_result url_join(const char *rel, const char *base, char **result) { int m; int i, j; char *buf = 0; - char *res; const char *scheme = 0, *authority = 0, *path = 0, *query = 0, *fragment = 0; int scheme_len = 0, authority_len = 0, path_len = 0, query_len = 0, @@ -206,11 +210,13 @@ char *url_join(const char *rel, const char *base) regmatch_t rel_match[10]; regmatch_t up_match[3]; + (*result) = 0; + /* see RFC 2396 section 5.2 */ m = regexec(&url_re, base, 10, base_match, 0); if (m) { LOG(("base url '%s' failed to match regex", base)); - return 0; + return URL_FUNC_FAILED; } /*for (unsigned int i = 0; i != 10; i++) { if (base_match[i].rm_so == -1) @@ -221,7 +227,7 @@ char *url_join(const char *rel, const char *base) }*/ if (base_match[2].rm_so == -1) { LOG(("base url '%s' is not absolute", base)); - return 0; + return URL_FUNC_FAILED; } scheme = base + base_match[2].rm_so; scheme_len = base_match[2].rm_eo - base_match[2].rm_so; @@ -236,7 +242,7 @@ char *url_join(const char *rel, const char *base) m = regexec(&url_re, rel, 10, rel_match, 0); if (m) { LOG(("relative url '%s' failed to match regex", rel)); - return 0; + return URL_FUNC_FAILED; } /* 2) */ @@ -292,7 +298,7 @@ char *url_join(const char *rel, const char *base) buf = malloc(path_len + rel_match[5].rm_eo + 10); if (!buf) { LOG(("malloc failed")); - return 0; + return URL_FUNC_NOMEM; } /* a) */ strncpy(buf, path, path_len); @@ -334,44 +340,44 @@ char *url_join(const char *rel, const char *base) path = buf; step7: /* 7) */ - res = malloc(scheme_len + 1 + 2 + authority_len + path_len + 1 + 1 + + (*result) = malloc(scheme_len + 1 + 2 + authority_len + path_len + 1 + 1 + query_len + 1 + fragment_len + 1); - if (!res) { + if (!(*result)) { LOG(("malloc failed")); free(buf); - return 0; + return URL_FUNC_NOMEM; } - strncpy(res, scheme, scheme_len); - res[scheme_len] = ':'; + strncpy((*result), scheme, scheme_len); + (*result)[scheme_len] = ':'; i = scheme_len + 1; if (authority) { - res[i++] = '/'; - res[i++] = '/'; - strncpy(res + i, authority, authority_len); + (*result)[i++] = '/'; + (*result)[i++] = '/'; + strncpy((*result) + i, authority, authority_len); i += authority_len; } if (path_len) { - strncpy(res + i, path, path_len); + strncpy((*result) + i, path, path_len); i += path_len; } else { - res[i++] = '/'; + (*result)[i++] = '/'; } if (query) { - res[i++] = '?'; - strncpy(res + i, query, query_len); + (*result)[i++] = '?'; + strncpy((*result) + i, query, query_len); i += query_len; } if (fragment) { - res[i++] = '#'; - strncpy(res + i, fragment, fragment_len); + (*result)[i++] = '#'; + strncpy((*result) + i, fragment, fragment_len); i += fragment_len; } - res[i] = 0; + (*result)[i] = 0; free(buf); - return res; + return URL_FUNC_OK; } @@ -382,29 +388,30 @@ step7: /* 7) */ * \returns host name allocated on heap, or 0 on failure */ -char *url_host(const char *url) +url_func_result url_host(const char *url, char **result) { int m; - char *host; regmatch_t match[10]; + (*result) = 0; + m = regexec(&url_re, url, 10, match, 0); if (m) { LOG(("url '%s' failed to match regex", url)); - return 0; + return URL_FUNC_FAILED; } if (match[4].rm_so == -1) - return 0; + return URL_FUNC_FAILED; - host = malloc(match[4].rm_eo - match[4].rm_so + 1); - if (!host) { + (*result) = malloc(match[4].rm_eo - match[4].rm_so + 1); + if (!(*result)) { LOG(("malloc failed")); - return 0; + return URL_FUNC_NOMEM; } - strncpy(host, url + match[4].rm_so, match[4].rm_eo - match[4].rm_so); - host[match[4].rm_eo - match[4].rm_so] = 0; + strncpy((*result), url + match[4].rm_so, match[4].rm_eo - match[4].rm_so); + (*result)[match[4].rm_eo - match[4].rm_so] = 0; - return host; + return URL_FUNC_OK; } @@ -415,27 +422,29 @@ char *url_host(const char *url) * \returns filename allocated on heap, or 0 on memory exhaustion */ -char *url_nice(const char *url) +url_func_result url_nice(const char *url, char **result) { unsigned int i, j, k = 0, so; unsigned int len; const char *colon; char buf[40]; - char *result; char *rurl; int m; regmatch_t match[10]; - result = malloc(40); - if (!result) - return 0; + /* just in case */ + (*result) = 0; + + (*result) = malloc(40); + if (!(*result)) + return URL_FUNC_NOMEM; len = strlen(url); assert(len != 0); rurl = malloc(len + 1); if (!rurl) { - free(result); - return 0; + free((*result)); + return URL_FUNC_NOMEM; } /* reverse url into rurl */ @@ -447,11 +456,11 @@ char *url_nice(const char *url) colon = strchr(url, ':'); if (colon) url = colon + 1; - strncpy(result, url, 15); - result[15] = 0; - for (i = 0; result[i]; i++) - if (!isalnum(result[i])) - result[i] = '_'; + strncpy((*result), url, 15); + (*result)[15] = 0; + for (i = 0; (*result)[i]; i++) + if (!isalnum((*result)[i])) + (*result)[i] = '_'; /* append nice pieces */ j = 0; @@ -481,19 +490,21 @@ char *url_nice(const char *url) if (k == 0) { free(rurl); - return result; + return URL_FUNC_OK; } /* reverse back */ for (i = 0, j = k - 1; i != k; i++, j--) - result[i] = buf[j]; - result[k] = 0; + (*result)[i] = buf[j]; + (*result)[k] = 0; for (i = 0; i != k; i++) - if (result[i] != (char) 0xa0 && !isalnum(result[i])) - result[i] = '_'; + if ((*result)[i] != (char) 0xa0 && !isalnum((*result)[i])) + (*result)[i] = '_'; + + free(rurl); - return result; + return URL_FUNC_OK; } @@ -503,26 +514,35 @@ char *url_nice(const char *url) int main(int argc, char *argv[]) { int i; + url_func_result res; char *s; url_init(); - for (i = 1; i != argc; i++) { -/* printf("==> '%s'\n", argv[i]); - s = url_normalize(argv[i]); - if (s) - printf("<== '%s'\n", s);*/ +/* for (i = 1; i != argc; i++) { + printf("==> '%s'\n", argv[i]); + res = url_normalize(argv[i], &s); + if (res == URL_FUNC_OK) { + printf("<== '%s'\n", s); + free(s); + }*/ /* printf("==> '%s'\n", argv[i]); - s = url_host(argv[i]); - if (s) - printf("<== '%s'\n", s);*/ + res = url_host(argv[i], &s); + if (res == URL_FUNC_OK) { + printf("<== '%s'\n", s); + free(s); + }*/ /* if (1 != i) { - s = url_join(argv[i], argv[1]); - if (s) + res = url_join(argv[i], argv[1], &s); + if (res == URL_FUNC_OK) { printf("'%s' + '%s' \t= '%s'\n", argv[1], argv[i], s); + free(s); + } }*/ - s = url_nice(argv[i]); - if (s) + res = url_nice(argv[i], &s); + if (res == URL_FUNC_OK) { printf("'%s'\n", s); + free(s); + } } return 0; } diff --git a/utils/url.h b/utils/url.h index 96aa947f5..cc373b257 100644 --- a/utils/url.h +++ b/utils/url.h @@ -12,10 +12,16 @@ #ifndef _NETSURF_UTILS_URL_H_ #define _NETSURF_UTILS_URL_H_ +typedef enum { + URL_FUNC_OK, /**< No error */ + URL_FUNC_NOMEM, /**< Insufficient memory */ + URL_FUNC_FAILED /**< Non fatal error (eg failed to match regex) */ +} url_func_result; + void url_init(void); -char *url_normalize(const char *url); -char *url_join(const char *rel, const char *base); -char *url_host(const char *url); -char *url_nice(const char *url); +url_func_result url_normalize(const char *url, char **result); +url_func_result url_join(const char *rel, const char *base, char **result); +url_func_result url_host(const char *url, char **result); +url_func_result url_nice(const char *url, char **result); #endif -- cgit v1.2.3