From b7af14b591707b28d9d99c77a7d5579e4d176c2a Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Sun, 2 Jul 2006 22:34:04 +0000 Subject: Implement component-wise URL comparison svn path=/trunk/netsurf/; revision=2697 --- content/fetchcache.c | 6 ++++- utils/url.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ utils/url.h | 2 ++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/content/fetchcache.c b/content/fetchcache.c index 7153c629b..1d0018d97 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -419,9 +419,13 @@ void fetchcache_callback(fetch_msg msg, void *p, const void *data, * destroyed in content_clean() */ c->status = CONTENT_STATUS_ERROR; if (result == URL_FUNC_OK) { + bool same; + + result = url_compare(c->url, url, &same); + /* check that we're not attempting to * redirect to the same URL */ - if (strcasecmp(c->url, url) == 0) { + if (result != URL_FUNC_OK || same) { msg_data.error = messages_get("BadRedirect"); content_broadcast(c, diff --git a/utils/url.c b/utils/url.c index 7d8b1673d..26c3295ab 100644 --- a/utils/url.c +++ b/utils/url.c @@ -823,6 +823,72 @@ url_func_result url_escape(const char *unescaped, char **result) return URL_FUNC_OK; } +/** + * Compare two absolute, normalized URLs + * + * \param url1 URL 1 + * \param url2 URL 2 + * \param result Pointer to location to store result (true if URLs match) + * \return URL_FUNC_OK on success + */ +url_func_result url_compare(const char *url1, const char *url2, bool *result) +{ + url_func_result status; + struct url_components c1, c2; + bool res = true; + + assert(url1 && url2 && result); + + /* Decompose URLs */ + status = url_get_components(url1, &c1, false); + if (status != URL_FUNC_OK) { + url_destroy_components(&c1); + return status; + } + + status = url_get_components(url2, &c2, false); + if (status != URL_FUNC_OK) { + url_destroy_components(&c2); + url_destroy_components(&c1); + return status; + } + + if (((c1.scheme && c2.scheme) || (!c1.scheme && !c2.scheme )) && + ((c1.authority && c2.authority) || + (!c1.authority && !c2.authority)) && + ((c1.path && c2.path) || (!c1.path && !c2.path)) && + ((c1.query && c2.query) || + (!c1.query && !c2.query)) && + ((c1.fragment && c2.fragment) || + (!c1.fragment && !c2.fragment))) { + + if (c1.scheme) + res &= strcasecmp(c1.scheme, c2.scheme) == 0; + + /** \todo consider each part of the authority separately */ + if (c1.authority) + res &= strcasecmp(c1.authority, c2.authority) == 0; + + if (c1.path) + res &= strcmp(c1.path, c2.path) == 0; + + if (c1.query) + res &= strcmp(c1.query, c2.query) == 0; + + if (c1.fragment) + res &= strcmp(c1.fragment, c2.fragment) == 0; + } else { + /* Can't match */ + res = false; + } + + *result = res; + + url_destroy_components(&c2); + url_destroy_components(&c1); + + return URL_FUNC_OK; +} /** * Split a URL into separate components diff --git a/utils/url.h b/utils/url.h index 275879947..58f1d1647 100644 --- a/utils/url.h +++ b/utils/url.h @@ -31,6 +31,8 @@ url_func_result url_canonical_root(const char *url, char **result); url_func_result url_strip_lqf(const char *url, char **result); url_func_result url_plq(const char *url, char **result); url_func_result url_path(const char *url, char **result); +url_func_result url_compare(const char *url1, const char *url2, + bool *result); char *path_to_url(const char *path); char *url_to_path(const char *url); -- cgit v1.2.3