mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-22 22:41:30 +03:00
Add url_fragment to extract fragment from URL
Optionally allow url_compare to ignore fragments in comparison Fix handling of url_compare result in a few places Fix redirects which contain fragments in the Location header svn path=/trunk/netsurf/; revision=3826
This commit is contained in:
parent
eb2c2e3f63
commit
ad6fcea6b0
@ -608,6 +608,7 @@ bool content_set_type(struct content *c, content_type type,
|
||||
return false;
|
||||
}
|
||||
content_remove_user(c, callback, p1, p2);
|
||||
msg_data.new_url = NULL;
|
||||
content_broadcast(clone, CONTENT_MSG_NEWPTR, msg_data);
|
||||
fetchcache_go(clone, referer,
|
||||
callback, p1, p2,
|
||||
|
@ -84,7 +84,7 @@ typedef enum {
|
||||
CONTENT_MSG_STATUS, /**< new status string */
|
||||
CONTENT_MSG_REFORMAT, /**< content_reformat done */
|
||||
CONTENT_MSG_REDRAW, /**< needs redraw (eg. new animation frame) */
|
||||
CONTENT_MSG_NEWPTR, /**< address of structure has changed */
|
||||
CONTENT_MSG_NEWPTR, /**< structure has been replaced */
|
||||
CONTENT_MSG_REFRESH, /**< wants refresh */
|
||||
#ifdef WITH_AUTH
|
||||
CONTENT_MSG_AUTH, /**< authentication required */
|
||||
@ -97,7 +97,8 @@ typedef enum {
|
||||
/** Extra data for some content_msg messages. */
|
||||
union content_msg_data {
|
||||
const char *error; /**< Error message, for CONTENT_MSG_ERROR. */
|
||||
char *redirect; /**< Redirect URL, for CONTENT_MSG_REDIRECT. */
|
||||
const char *new_url; /**< Replacement URL (or NULL if the same
|
||||
* as previous), for CONTENT_MSG_NEWPTR. */
|
||||
/** Area of content which needs redrawing, for CONTENT_MSG_REDRAW. */
|
||||
struct {
|
||||
float x, y, width, height;
|
||||
|
@ -689,6 +689,8 @@ void fetchcache_notmodified(struct content *c, const void *data)
|
||||
}
|
||||
|
||||
content_remove_user(c, callback, p1, p2);
|
||||
|
||||
msg_data.new_url = NULL;
|
||||
callback(CONTENT_MSG_NEWPTR, fb, p1, p2, msg_data);
|
||||
|
||||
/* and catch user up with fallback's state */
|
||||
@ -786,25 +788,26 @@ void fetchcache_redirect(struct content *c, const void *data,
|
||||
{
|
||||
char *url, *url1;
|
||||
char *referer, *parent_url;
|
||||
long http_code = fetch_http_code(c->fetch);
|
||||
const char *ref = fetch_get_referer(c->fetch);
|
||||
const char *parent = fetch_get_parent_url(c->fetch);
|
||||
long http_code;
|
||||
const char *ref;
|
||||
const char *parent;
|
||||
union content_msg_data msg_data;
|
||||
url_func_result result;
|
||||
|
||||
/* Preconditions */
|
||||
assert(c && data);
|
||||
assert(c->status == CONTENT_STATUS_TYPE_UNKNOWN);
|
||||
/* Ensure a redirect happened */
|
||||
assert(300 <= http_code && http_code <= 399);
|
||||
/* 304 is handled by fetch_notmodified() */
|
||||
assert(http_code != 304);
|
||||
|
||||
/* Extract fetch details */
|
||||
http_code = fetch_http_code(c->fetch);
|
||||
ref = fetch_get_referer(c->fetch);
|
||||
parent = fetch_get_parent_url(c->fetch);
|
||||
|
||||
/* Ensure a redirect happened */
|
||||
assert(300 <= http_code && http_code <= 399);
|
||||
/* 304 is handled by fetch_notmodified() */
|
||||
assert(http_code != 304);
|
||||
|
||||
/* Clone referer and parent url
|
||||
* originals are destroyed in fetch_abort() */
|
||||
referer = ref ? strdup(ref) : NULL;
|
||||
@ -941,6 +944,7 @@ void fetchcache_redirect(struct content *c, const void *data,
|
||||
replacement->redirect_count = c->redirect_count + 1;
|
||||
|
||||
/* Notify user that content has changed */
|
||||
msg_data.new_url = url;
|
||||
callback(CONTENT_MSG_NEWPTR, replacement, p1, p2, msg_data);
|
||||
|
||||
/* Start fetching the replacement content */
|
||||
|
@ -262,7 +262,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
|
||||
{
|
||||
struct content *c;
|
||||
char *url2;
|
||||
char *hash;
|
||||
char *fragment;
|
||||
url_func_result res;
|
||||
char url_buf[256];
|
||||
int depth = 0;
|
||||
@ -296,38 +296,38 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
|
||||
if (!download)
|
||||
gui_window_set_url(bw->window, url2);
|
||||
|
||||
free(bw->frag_id);
|
||||
bw->frag_id = NULL;
|
||||
|
||||
/* find any fragment identifier on end of URL */
|
||||
hash = strchr(url2, '#');
|
||||
if (bw->frag_id) {
|
||||
free(bw->frag_id);
|
||||
bw->frag_id = 0;
|
||||
}
|
||||
if (hash) {
|
||||
char *frag = curl_unescape(hash+1, strlen(hash + 1));
|
||||
if (!frag) {
|
||||
free(url2);
|
||||
warn_user("NoMemory", 0);
|
||||
return;
|
||||
}
|
||||
res = url_fragment(url2, &fragment);
|
||||
if (res == URL_FUNC_NOMEM) {
|
||||
free(url2);
|
||||
warn_user("NoMemory", 0);
|
||||
return;
|
||||
} else if (res == URL_FUNC_OK) {
|
||||
bool same_url = false;
|
||||
|
||||
bw->frag_id = strdup(frag);
|
||||
curl_free(frag);
|
||||
bw->frag_id = fragment;
|
||||
|
||||
if (!bw->frag_id) {
|
||||
free(url2);
|
||||
warn_user("NoMemory", 0);
|
||||
return;
|
||||
/* Compare new URL with existing one (ignoring fragments) */
|
||||
if (bw->current_content && bw->current_content->url) {
|
||||
res = url_compare(bw->current_content->url, url2,
|
||||
true, &same_url);
|
||||
if (res == URL_FUNC_NOMEM) {
|
||||
free(url2);
|
||||
warn_user("NoMemory", 0);
|
||||
return;
|
||||
} else if (res == URL_FUNC_FAILED) {
|
||||
same_url = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we're simply moving to another ID on the same page,
|
||||
* don't bother to fetch, just update the window.
|
||||
*/
|
||||
if (!post_urlenc && !post_multipart && !strchr(url2, '?') &&
|
||||
bw->current_content && bw->current_content->url &&
|
||||
strncasecmp(bw->current_content->url,
|
||||
url2, hash - url2) == 0 &&
|
||||
strlen(bw->current_content->url) ==
|
||||
(unsigned int)(hash - url2)) {
|
||||
if (same_url && !post_urlenc && !post_multipart &&
|
||||
!strchr(url2, '?')) {
|
||||
free(url2);
|
||||
browser_window_update(bw, false);
|
||||
snprintf(url_buf, sizeof url_buf, "%s#%s",
|
||||
@ -532,6 +532,27 @@ void browser_window_callback(content_msg msg, struct content *c,
|
||||
|
||||
case CONTENT_MSG_NEWPTR:
|
||||
bw->loading_content = c;
|
||||
if (data.new_url) {
|
||||
/* Replacement URL too, so check for new fragment */
|
||||
char *fragment;
|
||||
url_func_result res;
|
||||
|
||||
/* Remove any existing fragment */
|
||||
free(bw->frag_id);
|
||||
bw->frag_id = NULL;
|
||||
|
||||
/* Extract new one, if any */
|
||||
res = url_fragment(data.new_url, &fragment);
|
||||
if (res == URL_FUNC_OK) {
|
||||
/* Save for later use */
|
||||
bw->frag_id = fragment;
|
||||
}
|
||||
/* Ignore memory exhaustion here -- it'll simply result
|
||||
* in the window being scrolled to the top rather than
|
||||
* to the fragment. That's acceptable, given that it's
|
||||
* likely that more important things will complain
|
||||
* about memory shortage. */
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef WITH_AUTH
|
||||
|
@ -96,8 +96,8 @@ bool directory_convert(struct content *c, int width, int height) {
|
||||
|
||||
res = url_parent(c->url, &up);
|
||||
if (res == URL_FUNC_OK) {
|
||||
res = url_compare(c->url, up, &compare);
|
||||
if (!compare) {
|
||||
res = url_compare(c->url, up, false, &compare);
|
||||
if ((res == URL_FUNC_OK) && !compare) {
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"<a href=\"..\">[..]</a>\n");
|
||||
htmlParseChunk(c->data.html.parser, buffer,
|
||||
|
@ -1989,8 +1989,10 @@ void ro_gui_menu_prepare_action(wimp_w owner, menu_action action,
|
||||
if (result) {
|
||||
res = url_parent(c->url, &parent);
|
||||
if (res == URL_FUNC_OK) {
|
||||
res = url_compare(c->url, parent, &compare);
|
||||
result = !compare;
|
||||
res = url_compare(c->url, parent,
|
||||
false, &compare);
|
||||
if (res == URL_FUNC_OK)
|
||||
result = !compare;
|
||||
free(parent);
|
||||
} else {
|
||||
result = false;
|
||||
|
@ -3329,8 +3329,8 @@ bool ro_gui_window_navigate_up(struct gui_window *g, const char *url) {
|
||||
|
||||
res = url_parent(url, &parent);
|
||||
if (res == URL_FUNC_OK) {
|
||||
res = url_compare(url, parent, &compare);
|
||||
if (!compare && (res == URL_FUNC_OK))
|
||||
res = url_compare(url, parent, false, &compare);
|
||||
if ((res == URL_FUNC_OK) && !compare)
|
||||
browser_window_go(g->bw, parent, 0, true);
|
||||
free(parent);
|
||||
}
|
||||
|
53
utils/url.c
53
utils/url.c
@ -30,6 +30,7 @@
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#include "curl/curl.h"
|
||||
#include "utils/log.h"
|
||||
#include "utils/url.h"
|
||||
#include "utils/utils.h"
|
||||
@ -718,6 +719,44 @@ url_func_result url_leafname(const char *url, char **result)
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract fragment from an URL
|
||||
* This will unescape any %xx entities in the fragment
|
||||
*
|
||||
* \param url an absolute URL
|
||||
* \param result pointer to pointer to buffer to hold result
|
||||
* \return URL_FUNC_OK on success
|
||||
*/
|
||||
|
||||
url_func_result url_fragment(const char *url, char **result)
|
||||
{
|
||||
url_func_result status;
|
||||
struct url_components components;
|
||||
|
||||
assert(url);
|
||||
|
||||
status = url_get_components(url, &components);
|
||||
if (status == URL_FUNC_OK) {
|
||||
if (!components.fragment) {
|
||||
status = URL_FUNC_FAILED;
|
||||
} else {
|
||||
char *frag = curl_unescape(components.fragment,
|
||||
strlen(components.fragment));
|
||||
if (!frag) {
|
||||
status = URL_FUNC_NOMEM;
|
||||
} else {
|
||||
*result = strdup(frag);
|
||||
if (!(*result))
|
||||
status = URL_FUNC_NOMEM;
|
||||
curl_free(frag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
url_destroy_components(&components);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to find a nice filename for a URL.
|
||||
*
|
||||
@ -897,12 +936,14 @@ url_func_result url_escape(const char *unescaped, bool sptoplus,
|
||||
/**
|
||||
* 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)
|
||||
* \param url1 URL 1
|
||||
* \param url2 URL 2
|
||||
* \param nofrag Ignore fragment part in comparison
|
||||
* \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 url_compare(const char *url1, const char *url2,
|
||||
bool nofrag, bool *result)
|
||||
{
|
||||
url_func_result status;
|
||||
struct url_components c1, c2;
|
||||
@ -930,7 +971,7 @@ url_func_result url_compare(const char *url1, const char *url2, bool *result)
|
||||
((c1.path && c2.path) || (!c1.path && !c2.path)) &&
|
||||
((c1.query && c2.query) ||
|
||||
(!c1.query && !c2.query)) &&
|
||||
((c1.fragment && c2.fragment) ||
|
||||
(nofrag || (c1.fragment && c2.fragment) ||
|
||||
(!c1.fragment && !c2.fragment))) {
|
||||
|
||||
if (c1.scheme)
|
||||
@ -946,7 +987,7 @@ url_func_result url_compare(const char *url1, const char *url2, bool *result)
|
||||
if (c1.query)
|
||||
res &= strcmp(c1.query, c2.query) == 0;
|
||||
|
||||
if (c1.fragment)
|
||||
if (!nofrag && c1.fragment)
|
||||
res &= strcmp(c1.fragment, c2.fragment) == 0;
|
||||
} else {
|
||||
/* Can't match */
|
||||
|
@ -54,8 +54,9 @@ url_func_result url_parent(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_leafname(const char *url, char **result);
|
||||
url_func_result url_fragment(const char *url, char **result);
|
||||
url_func_result url_compare(const char *url1, const char *url2,
|
||||
bool *result);
|
||||
bool nofrag, bool *result);
|
||||
|
||||
url_func_result url_get_components(const char *url,
|
||||
struct url_components *result);
|
||||
|
Loading…
Reference in New Issue
Block a user