From f1b59814f8da2f3e235d47adfb332edf8a093b31 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Fri, 26 Dec 2003 00:17:55 +0000 Subject: [project @ 2003-12-26 00:17:55 by bursa] New url_join using liburi, . svn path=/import/netsurf/; revision=441 --- content/fetch.c | 5 ++ content/fetchcache.c | 8 ++- css/css.c | 30 ++++++------ desktop/browser.c | 42 +++++++++------- desktop/gui.h | 15 +----- makefile | 5 +- render/box.c | 94 +++++++++++++++++++++++------------ render/html.c | 38 ++++++++++---- render/html.h | 1 + riscos/window.c | 37 ++++++++------ utils/utils.c | 136 +++++++++++++++++++-------------------------------- utils/utils.h | 2 +- 12 files changed, 219 insertions(+), 194 deletions(-) diff --git a/content/fetch.c b/content/fetch.c index f03cfc615..f7197a7aa 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -602,6 +602,11 @@ bool fetch_process_headers(struct fetch *f) url_path = curl_unescape(f->url + 8, (int) strlen(f->url) - 8); type = fetch_filetype(url_path); curl_free(url_path); + } else if (strncmp(f->url, "file:/", 6) == 0) { + char *url_path; + url_path = curl_unescape(f->url + 6, (int) strlen(f->url) - 6); + type = fetch_filetype(url_path); + curl_free(url_path); } } diff --git a/content/fetchcache.c b/content/fetchcache.c index 28c098034..63bd5be35 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -147,8 +147,12 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size) /* 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); - content_broadcast(c, CONTENT_MSG_REDIRECT, url); - xfree(url); + if (url) { + content_broadcast(c, CONTENT_MSG_REDIRECT, url); + xfree(url); + } else { + content_broadcast(c, CONTENT_MSG_ERROR, "Bad redirect"); + } if (c->cache) cache_destroy(c); content_destroy(c); diff --git a/css/css.c b/css/css.c index d0580a095..f719eca7c 100644 --- a/css/css.c +++ b/css/css.c @@ -129,29 +129,25 @@ int css_convert(struct content *c, unsigned int width, unsigned int height) buffer = css__scan_buffer(c->data.css.data, c->data.css.length + 2, c->data.css.css->lexer); assert(buffer); - while ((token = css_lex(c->data.css.css->lexer)) && - !param.syntax_error) { + while (token = css_lex(c->data.css.css->lexer)) { css_parser_(c->data.css.css->parser, token, xstrdup(css_get_text(c->data.css.css->lexer)), ¶m); + if (param.syntax_error) { + int line = css_get_lineno(c->data.css.css->lexer); + LOG(("syntax error near line %i", line)); + param.syntax_error = false; + } } css__delete_buffer(buffer, c->data.css.css->lexer); free(c->data.css.data); - if (!param.syntax_error) - css_parser_(c->data.css.css->parser, 0, 0, ¶m); + css_parser_(c->data.css.css->parser, 0, 0, ¶m); css_parser_Free(c->data.css.css->parser, free); - if (param.syntax_error) { - int line = css_get_lineno(c->data.css.css->lexer); - css_lex_destroy(c->data.css.css->lexer); - LOG(("syntax error near line %i", line)); - /*css_destroy(c);*/ - return 1; - } css_lex_destroy(c->data.css.css->lexer); - css_dump_stylesheet(c->data.css.css); + /*css_dump_stylesheet(c->data.css.css);*/ /* complete fetch of any imported stylesheets */ while (c->active != 0) { @@ -261,7 +257,7 @@ char *css_unquote(char *s) void css_atimport(struct content *c, struct css_node *node) { - char *s, *url; + char *s, *url, *url1; int string = 0, screen = 1; unsigned int i; @@ -322,6 +318,12 @@ void css_atimport(struct content *c, struct css_node *node) return; } + url1 = url_join(url, c->url); + if (!url1) { + free(url); + return; + } + /* start the fetch */ c->data.css.import_count++; c->data.css.import_url = xrealloc(c->data.css.import_url, @@ -330,7 +332,7 @@ void css_atimport(struct content *c, struct css_node *node) c->data.css.import_count * sizeof(*c->data.css.import_content)); i = c->data.css.import_count - 1; - c->data.css.import_url[i] = url_join(url, c->url); + c->data.css.import_url[i] = url1; c->data.css.import_content[i] = fetchcache( c->data.css.import_url[i], c->url, css_atimport_callback, c, i, c->width, c->height, true, 0, 0); diff --git a/desktop/browser.c b/desktop/browser.c index b2a9c27d6..54a91b7b8 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -251,6 +251,8 @@ void browser_window_open_location_post(struct browser_window* bw, LOG(("bw = %p, url = %s", bw, url)); assert(bw != 0 && url != 0); url1 = url_join(url, 0); + if (!url1) + return; browser_window_open_location_historical(bw, url1, post_urlenc, post_multipart); bw->history_add = true; free(url1); @@ -292,14 +294,11 @@ void browser_window_callback(content_msg msg, struct content *c, previous_safety = gui_window_set_redraw_safety(bw->window, UNSAFE); if (bw->loading_content == c) { - struct gui_message gmsg; if (bw->url != 0) xfree(bw->url); bw->url = xstrdup(c->url); - gmsg.type = msg_SET_URL; - gmsg.data.set_url.url = bw->url; - gui_window_message(bw->window, &gmsg); + gui_window_set_url(bw->window, bw->url); if (bw->current_content != NULL) { @@ -1215,26 +1214,28 @@ void browser_window_follow_link(struct browser_window* bw, continue; if (click_boxes[i].box->href != NULL) { + char *url = url_join((char*) click_boxes[i].box->href, + bw->current_content->data.html.base_url); + if (!url) + continue; + if (click_type == 1) { - char *url = url_join((char*) click_boxes[i].box->href, bw->url); browser_window_open_location(bw, url); - free(url); } else if (click_type == 2) { - char *url = url_join((char*) click_boxes[i].box->href, bw->url); struct browser_window* bw_new; bw_new = create_browser_window(browser_TITLE | browser_TOOLBAR | browser_SCROLL_X_ALWAYS | browser_SCROLL_Y_ALWAYS, 640, 480, NULL); gui_window_show(bw_new->window); browser_window_open_location(bw_new, url); - free(url); } else if (click_type == 0) { - browser_window_set_status(bw, (char*) click_boxes[i].box->href); + browser_window_set_status(bw, url); done = 1; } + free(url); break; } if (click_type == 0 && click_boxes[i].box->title != NULL) @@ -1572,37 +1573,37 @@ void browser_window_redraw_boxes(struct browser_window* bw, struct box_position* void browser_form_submit(struct browser_window *bw, struct form *form, struct form_control *submit_button) { - char *data, *url, *url1; + char *data = 0, *url = 0, *url1 = 0, *base; struct form_successful_control *success; assert(form); + assert(bw->current_content->type == CONTENT_HTML); success = form_successful_controls(form, submit_button); + base = bw->current_content->data.html.base_url; switch (form->method) { case method_GET: data = form_url_encode(success); url = xcalloc(1, strlen(form->action) + strlen(data) + 2); sprintf(url, "%s?%s", form->action, data); - url1 = url_join(url, bw->url); - free(data); - free(url); + url1 = url_join(url, base); + if (!url1) + break; browser_window_open_location(bw, url1); - free(url1); break; case method_POST_URLENC: data = form_url_encode(success); - url = url_join(form->action, bw->url); + url = url_join(form->action, base); + if (!url) + break; browser_window_open_location_post(bw, url, data, 0); - free(url); - free(data); break; case method_POST_MULTIPART: - url = url_join(form->action, bw->url); + url = url_join(form->action, base); browser_window_open_location_post(bw, url, 0, success); - free(url); break; default: @@ -1610,4 +1611,7 @@ void browser_form_submit(struct browser_window *bw, struct form *form, } form_free_successful(success); + free(data); + free(url); + free(url1); } diff --git a/desktop/gui.h b/desktop/gui.h index 5ca8e038d..72ead54b4 100644 --- a/desktop/gui.h +++ b/desktop/gui.h @@ -18,18 +18,6 @@ typedef struct gui_window gui_window; #include #include "netsurf/desktop/browser.h" -struct gui_message -{ - enum { msg_SET_URL } type; - union { - struct { - char* url; - } set_url; - } data; -}; - -typedef struct gui_message gui_message; - gui_window *gui_create_browser_window(struct browser_window *bw); gui_window *gui_create_download_window(struct content *content); void gui_window_destroy(gui_window* g); @@ -43,8 +31,7 @@ unsigned long gui_window_get_width(gui_window* g); void gui_window_set_extent(gui_window* g, unsigned long width, unsigned long height); void gui_window_set_status(gui_window* g, const char* text); void gui_window_set_title(gui_window* g, char* title); - -void gui_window_message(gui_window* g, gui_message* msg); +void gui_window_set_url(gui_window *g, char *url); void gui_download_window_update_status(gui_window *g); void gui_download_window_done(gui_window *g); diff --git a/makefile b/makefile index f3192f77f..951c48bd8 100644 --- a/makefile +++ b/makefile @@ -31,8 +31,9 @@ WARNFLAGS = -W -Wall -Wundef -Wpointer-arith -Wbad-function-cast -Wcast-qual \ CFLAGS = -std=c9x -D_BSD_SOURCE -Driscos -DBOOL_DEFINED -O $(WARNFLAGS) -I.. \ -mpoke-function-name CFLAGS_DEBUG = -std=c9x -D_BSD_SOURCE $(WARNFLAGS) -I.. -I/usr/include/libxml2 -g -LDFLAGS = -L/riscos/lib -lxml2 -lz -lcurl -lssl -lcrypto -lares -lanim -lpng -lifc -loslib -LDFLAGS_DEBUG = -L/usr/lib -lxml2 -lz -lm -lcurl -lssl -lcrypto -ldl +LDFLAGS = -L/riscos/lib -lxml2 -lz -lcurl -lssl -lcrypto -lares -lanim -lpng \ + -lifc -loslib -luri +LDFLAGS_DEBUG = -L/usr/lib -lxml2 -lz -lm -lcurl -lssl -lcrypto -ldl -luri OBJDIR = $(shell $(CC) -dumpmachine) SOURCES=$(OBJECTS:.o=.c) diff --git a/render/box.c b/render/box.c index e62fd0cd7..e565be0a6 100644 --- a/render/box.c +++ b/render/box.c @@ -706,7 +706,10 @@ struct result box_image(xmlNode *n, struct status *status, if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) return (struct result) {box, 0}; - url = url_join(s, status->content->url); + url = url_join(s, status->content->data.html.base_url); + if (!url) + return (struct result) {box, 0}; + LOG(("image '%s'", url)); xmlFree(s); @@ -1014,8 +1017,9 @@ struct result box_input(xmlNode *n, struct status *status, gadget->box = box; gadget->type = GADGET_IMAGE; if ((s = (char *) xmlGetProp(n, (const xmlChar*) "src"))) { - url = url_join(s, status->content->url); - html_fetch_object(status->content, url, box); + url = url_join(s, status->content->data.html.base_url); + if (url) + html_fetch_object(status->content, url, box); xmlFree(s); } } @@ -1673,9 +1677,13 @@ struct result box_object(xmlNode *n, struct status *status, /* object data */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "data"))) { - + url = url_join(s, status->content->data.html.base_url); + if (!url) { + free(po); + xmlFree(s); + return (struct result) {box, 1}; + } po->data = strdup(s); - url = url_join(strdup(s), status->content->url); LOG(("object '%s'", po->data)); xmlFree(s); } @@ -1797,10 +1805,14 @@ struct result box_embed(xmlNode *n, struct status *status, /* embed src */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) { - - po->data = strdup(s); - url = url_join(strdup(s), status->content->url); + url = url_join(s, status->content->data.html.base_url); + if (!url) { + free(po); + xmlFree(s); + return (struct result) {box, 0}; + } LOG(("embed '%s'", url)); + po->data = strdup(s); xmlFree(s); } @@ -1861,14 +1873,18 @@ struct result box_applet(xmlNode *n, struct status *status, po->classid = 0; po->params = 0; - /* code */ + /* code */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "code"))) { - - po->classid = strdup(s); - url = url_join(strdup(s), status->content->url); - LOG(("applet '%s'", url)); - xmlFree(s); - } + url = url_join(s, status->content->data.html.base_url); + if (!url) { + free(po); + xmlFree(s); + return (struct result) {box, 1}; + } + LOG(("applet '%s'", url)); + po->classid = strdup(s); + xmlFree(s); + } /* object codebase */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "codebase"))) { @@ -1962,12 +1978,16 @@ struct result box_iframe(xmlNode *n, struct status *status, /* iframe src */ if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) { - - po->data = strdup(s); - url = url_join(strdup(s), status->content->url); - LOG(("embed '%s'", url)); - xmlFree(s); - } + url = url_join(s, status->content->data.html.base_url); + if (!url) { + free(po); + xmlFree(s); + return (struct result) {box, 0}; + } + LOG(("embed '%s'", url)); + po->data = strdup(s); + xmlFree(s); + } box->object_params = po; @@ -1985,22 +2005,27 @@ struct result box_iframe(xmlNode *n, struct status *status, * necessary as there are multiple ways of declaring an object's attributes. * * Returns false if the object could not be handled. + * + * TODO: reformat, plug failure leaks */ bool plugin_decode(struct content* content, char* url, struct box* box, struct object_params* po) { struct plugin_params * pp; - /* Set basehref */ - po->basehref = strdup(content->url); - /* 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->url); + po->codebase = url_join("./", content->data.html.base_url); else - po->codebase = url_join(po->codebase, content->url); + po->codebase = url_join(po->codebase, content->data.html.base_url); + + if (!po->codebase) + return false; + + /* Set basehref */ + po->basehref = strdup(content->data.html.base_url); /* Check that we have some data specified. * First, check the data attribute. @@ -2019,11 +2044,16 @@ bool plugin_decode(struct content* content, char* url, struct box* box, for(pp = po->params; pp != 0 && (strcasecmp(pp->name, "movie") != 0); pp = pp->next); - if(pp != 0) - url = url_join(pp->value, po->basehref); - else return false; + if(pp == 0) + return false; + url = url_join(pp->value, po->basehref); + if (!url) + return false; /* munge the codebase */ - po->codebase = url_join("./", content->url); + po->codebase = url_join("./", + content->data.html.base_url); + if (!po->codebase) + return false; } else { LOG(("ActiveX object - n0")); @@ -2032,6 +2062,8 @@ bool plugin_decode(struct content* content, char* url, struct box* box, } else { url = url_join(po->classid, po->codebase); + if (!url) + return false; /* The java plugin doesn't need the .class extension * so we strip it. @@ -2043,6 +2075,8 @@ bool plugin_decode(struct content* content, char* url, struct box* box, } else { url = url_join(po->data, po->codebase); + if (!url) + return false; } /* Check if the declared mime type is understandable. diff --git a/render/html.c b/render/html.c index e3953597e..73bda84ed 100644 --- a/render/html.c +++ b/render/html.c @@ -23,7 +23,7 @@ static void html_convert_css_callback(content_msg msg, struct content *css, void *p1, void *p2, const char *error); -static void html_title(struct content *c, xmlNode *head); +static void html_head(struct content *c, xmlNode *head); static void html_find_stylesheets(struct content *c, xmlNode *head); static void html_object_callback(content_msg msg, struct content *object, void *p1, void *p2, const char *error); @@ -37,6 +37,7 @@ void html_create(struct content *c) c->data.html.fonts = NULL; c->data.html.length = 0; c->data.html.source = xcalloc(0, 1); + c->data.html.base_url = xstrdup(c->url); c->data.html.background_colour = TRANSPARENT; } @@ -96,7 +97,7 @@ int html_convert(struct content *c, unsigned int width, unsigned int height) } if (head != 0) - html_title(c, head); + html_head(c, head); /* get stylesheets */ html_find_stylesheets(c, head); @@ -203,19 +204,31 @@ void html_convert_css_callback(content_msg msg, struct content *css, } -void html_title(struct content *c, xmlNode *head) + +/** + * Process elements in . + */ + +void html_head(struct content *c, xmlNode *head) { xmlNode *node; - xmlChar *title; c->title = 0; for (node = head->children; node != 0; node = node->next) { - if (strcmp(node->name, "title") == 0) { - title = xmlNodeGetContent(node); + if (!c->title && strcmp(node->name, "title") == 0) { + xmlChar *title = xmlNodeGetContent(node); c->title = squash_tolat1(title); xmlFree(title); - return; + + } else if (strcmp(node->name, "base") == 0) { + char *href = (char *) xmlGetProp(node, (const xmlChar *) "href"); + if (href) { + char *url = url_join(href, 0); + if (url) + c->data.html.base_url = url; + xmlFree(href); + } } } } @@ -286,9 +299,12 @@ 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->url); - LOG(("linked stylesheet %i '%s'", i, url)); + url = url_join(href, c->data.html.base_url); xmlFree(href); + if (!url) + continue; + + LOG(("linked stylesheet %i '%s'", i, url)); /* start fetch */ c->data.html.stylesheet_content = xrealloc(c->data.html.stylesheet_content, @@ -325,7 +341,8 @@ void html_find_stylesheets(struct content *c, xmlNode *head) /* create stylesheet */ LOG(("style element")); if (c->data.html.stylesheet_content[1] == 0) { - c->data.html.stylesheet_content[1] = content_create(c->url); + c->data.html.stylesheet_content[1] = + content_create(c->data.html.base_url); content_set_type(c->data.html.stylesheet_content[1], CONTENT_CSS, "text/css"); } @@ -567,5 +584,6 @@ void html_destroy(struct content *c) xfree(c->title); if (c->data.html.source != 0) xfree(c->data.html.source); + free(c->data.html.base_url); } diff --git a/render/html.h b/render/html.h index db41f7f11..8a5047cc2 100644 --- a/render/html.h +++ b/render/html.h @@ -29,6 +29,7 @@ struct content_html_data { htmlParserCtxt *parser; char *source; int length; + char *base_url; /**< Base URL (may be a copy of content->url). */ struct box *layout; colour background_colour; unsigned int stylesheet_count; diff --git a/riscos/window.c b/riscos/window.c index e6493ef94..206205a30 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -299,21 +299,14 @@ void gui_window_set_status(gui_window* g, const char* text) } -void gui_window_message(gui_window* g, gui_message* msg) -{ - if (g == NULL || msg == NULL) - return; +/** + * Set the contents of a window's address bar. + */ - switch (msg->type) - { - case msg_SET_URL: - fprintf(stderr, "Set URL '%s'\n", msg->data.set_url.url); - strncpy(g->url, msg->data.set_url.url, 255); - wimp_set_icon_state(g->data.browser.toolbar, ICON_TOOLBAR_URL, 0, 0); - break; - default: - break; - } +void gui_window_set_url(gui_window *g, char *url) +{ + strncpy(g->url, url, 255); + wimp_set_icon_state(g->data.browser.toolbar, ICON_TOOLBAR_URL, 0, 0); } @@ -712,7 +705,21 @@ bool ro_gui_window_keypress(gui_window *g, int key, bool toolbar) browser_window_open_location(g->data.browser.bw, "file:///%3CWimp$ScrapDir%3E/WWW/NetSurf/About"); } else { - browser_window_open_location(g->data.browser.bw, g->url); + char *url = xcalloc(1, 10 + strlen(g->url)); + char *url2; + if (g->url[strspn(g->url, "abcdefghijklmnopqrstuvwxyz")] != ':') { + strcpy(url, "http://"); + strcpy(url + 7, g->url); + } else { + strcpy(url, g->url); + } + url2 = url_join(url, 0); + free(url); + if (url2) { + gui_window_set_url(g, url2); + browser_window_open_location(g->data.browser.bw, url2); + free(url2); + } } return true; diff --git a/utils/utils.c b/utils/utils.c index 004fa3fa7..1487ac1c7 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "libxml/encoding.h" #include "libxml/uri.h" #include "netsurf/utils/log.h" @@ -165,98 +166,59 @@ char *squash_tolat1(xmlChar *s) return squash; } -char *url_join(const char* new, const char* base) + +/** + * Calculate a URL from a relative and base URL. + * + * base may be 0 for a new URL, in which case the URL is cannonicalized and + * returned. Returns 0 in case of error. + */ + +char *url_join(char *rel_url, char *base_url) { - char* ret, *nn; - int i,j,k; - - LOG(("new = %s, base = %s", new, base)); - - /* deal with spaces and quotation marks in URLs etc. - also removes spaces from end of links. - There's definitely a better way to do this */ - nn = xcalloc(strlen(new) * 3 + 40, sizeof(char)); - j=0; - for(i=0;i http://www.example.com/ */ - if (ret[i] == 0) - { - ret[i] = '/'; - ret[i+1] = 0; - } - } - else - { - /* relative url */ - ret = xmlBuildURI(new, base); - } + base = uri_alloc(base_url, strlen(base_url)); + rel = uri_alloc(rel_url, strlen(rel_url)); + if (!base || !rel) + goto fail; + if (!base->scheme) + goto fail; - LOG(("ret = %s", ret)); - if (ret == NULL) - { - ret = xcalloc(strlen(new) + 10, sizeof(char)); - strcpy(ret, new); - } + abs = uri_abs_1(base, rel); + + res = xstrdup(uri_uri(abs)); + + uri_free(base); + uri_free(rel); + + LOG(("res = %s", res)); + return res; + +fail: + if (base) + uri_free(base); + if (rel) + uri_free(rel); + + LOG(("error")); - xfree(nn); - return ret; + return 0; } + + char *get_host_from_url (char *url) { diff --git a/utils/utils.h b/utils/utils.h index fb6255511..3ca3072af 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -24,7 +24,7 @@ char * squash_whitespace(const char * s); char * tolat1(xmlChar * s); char * tolat1_pre(xmlChar * s); char *squash_tolat1(xmlChar *s); -char *url_join(const char* new, const char* base); +char *url_join(char *rel_url, char *base_url); char *get_host_from_url(char* url); bool is_dir(const char *path); -- cgit v1.2.3