diff --git a/content/content.c b/content/content.c index d99d02b09..7503e9d28 100644 --- a/content/content.c +++ b/content/content.c @@ -535,6 +535,8 @@ bool content_set_type(struct content *c, content_type type, c->user_list->next->next) { /* type not shareable, and more than one user: split into * a content per user */ + const char *referer = fetch_get_referer(c->fetch); + while (c->user_list->next->next) { clone = content_create(c->url); if (!clone) { @@ -566,10 +568,11 @@ bool content_set_type(struct content *c, content_type type, } content_remove_user(c, callback, p1, p2); content_broadcast(clone, CONTENT_MSG_NEWPTR, msg_data); - fetchcache_go(clone, fetch_get_referer(c->fetch), + fetchcache_go(clone, referer, callback, p1, p2, clone->width, clone->height, - 0, 0, false); + 0, 0, false, + referer ? referer : c->url); } } diff --git a/content/fetch.c b/content/fetch.c index 4ce383397..9ec4595cf 100644 --- a/content/fetch.c +++ b/content/fetch.c @@ -69,6 +69,8 @@ struct fetch { char *url; /**< URL. */ char *referer; /**< URL for Referer header. */ bool send_referer; /**< Valid to send the referer */ + char *parent_fetch_url; /**< URL of parent fetch (not necessarily + * the same as the referer) */ void *p; /**< Private data for callback. */ struct curl_slist *headers; /**< List of request headers. */ char *host; /**< Host part of URL. */ @@ -310,7 +312,7 @@ struct fetch * fetch_start(const char *url, const char *referer, unsigned long size), void *p, bool only_2xx, const char *post_urlenc, struct form_successful_control *post_multipart, - bool verifiable, char *headers[]) + bool verifiable, const char *parent_url, char *headers[]) { char *host; struct fetch *fetch; @@ -372,6 +374,7 @@ struct fetch * fetch_start(const char *url, const char *referer, strcasecmp(ref1, ref2) == 0) fetch->send_referer = true; } + fetch->parent_fetch_url = parent_url ? strdup(parent_url) : 0; fetch->p = p; fetch->headers = 0; fetch->host = host; @@ -404,6 +407,7 @@ struct fetch * fetch_start(const char *url, const char *referer, fetch->r_next = 0; if (!fetch->url || (referer && !fetch->referer) || + (parent_url && !fetch->parent_fetch_url) || (post_urlenc && !fetch->post_urlenc) || (post_multipart && !fetch->post_multipart)) goto failed; @@ -478,6 +482,7 @@ failed: if (ref2) free(ref2); free(fetch->url); + free(fetch->parent_fetch_url); free(fetch->referer); free(fetch->post_urlenc); if (fetch->post_multipart) @@ -794,6 +799,7 @@ void fetch_free(struct fetch *f) curl_easy_cleanup(f->curl_handle); free(f->url); free(f->host); + free(f->parent_fetch_url); free(f->referer); free(f->location); free(f->cookie_string); @@ -1223,15 +1229,17 @@ size_t fetch_curl_header(char *data, size_t size, size_t nmemb, /* extract Set-Cookie header */ SKIP_ST(11); - /* If the fetch is unverifiable and there's no referer, - * err on the side of caution and do not set the cookie */ + /* If the fetch is unverifiable and there's no parent fetch + * url, err on the side of caution and do not set the + cookie */ - if (f->verifiable || f->referer) { + if (f->verifiable || f->parent_fetch_url) { /* If the transaction's verifiable, we don't require - * that the request uri and the referer domain match, - * so don't pass in the referer in this case. */ + * that the request uri and the parent domain match, + * so don't pass in the parent in this case. */ urldb_set_cookie(&data[i], f->url, - f->verifiable ? 0 : f->referer); + f->verifiable ? 0 + : f->parent_fetch_url); } } diff --git a/content/fetch.h b/content/fetch.h index c8a454816..4bf55503c 100644 --- a/content/fetch.h +++ b/content/fetch.h @@ -72,7 +72,7 @@ struct fetch * fetch_start(const char *url, const char *referer, unsigned long size), void *p, bool only_2xx, const char *post_urlenc, struct form_successful_control *post_multipart, - bool verifiable, char *headers[]); + bool verifiable, const char *parent_url, char *headers[]); void fetch_abort(struct fetch *f); void fetch_poll(void); void fetch_quit(void); diff --git a/content/fetchcache.c b/content/fetchcache.c index c6c6e3507..62d81fe15 100644 --- a/content/fetchcache.c +++ b/content/fetchcache.c @@ -204,6 +204,7 @@ struct content * fetchcache(const char *url, * \param post_urlenc url encoded post data, or 0 if none * \param post_multipart multipart post data, or 0 if none * \param verifiable this transaction is verifiable + * \param parent_url URL of fetch which spawned this one, or 0 if none * * Errors will be sent back through the callback. */ @@ -215,7 +216,7 @@ void fetchcache_go(struct content *content, const char *referer, int width, int height, char *post_urlenc, struct form_successful_control *post_multipart, - bool verifiable) + bool verifiable, const char *parent_url) { char error_message[500]; union content_msg_data msg_data; @@ -309,7 +310,7 @@ void fetchcache_go(struct content *content, const char *referer, fetchcache_callback, content, content->no_error_pages, post_urlenc, post_multipart, verifiable, - headers); + parent_url, headers); for (i = 0; headers[i]; i++) free(headers[i]); free(headers); @@ -771,7 +772,7 @@ void fetchcache_notmodified(struct content *c, const void *data) for (u = c->user_list->next; u; u = u->next) { fetchcache_go(c, referer, u->callback, u->p1, u->p2, c->width, c->height, 0, 0, - false); + false, ref ? referer : c->url); } free(referer); diff --git a/content/fetchcache.h b/content/fetchcache.h index 43a6649fe..bb57fba01 100644 --- a/content/fetchcache.h +++ b/content/fetchcache.h @@ -39,6 +39,6 @@ void fetchcache_go(struct content *content, const char *referer, int width, int height, char *post_urlenc, struct form_successful_control *post_multipart, - bool verifiable); + bool verifiable, const char *parent_url); #endif diff --git a/css/css.c b/css/css.c index 15ac9511c..ac988d321 100644 --- a/css/css.c +++ b/css/css.c @@ -877,7 +877,7 @@ void css_atimport(struct content *c, struct css_node *node) fetchcache_go(c->data.css.import_content[i], c->url, css_atimport_callback, (intptr_t) c, i, c->width, c->height, - 0, 0, false); + 0, 0, false, c->url); } free(url); @@ -949,7 +949,7 @@ void css_atimport_callback(content_msg msg, struct content *css, c->url, css_atimport_callback, (intptr_t) c, i, css->width, css->height, - 0, 0, false); + 0, 0, false, c->url); } break; diff --git a/desktop/browser.c b/desktop/browser.c index 1a54232b8..0273917bc 100644 --- a/desktop/browser.c +++ b/desktop/browser.c @@ -64,7 +64,7 @@ static void browser_window_go_post(struct browser_window *bw, const char *url, char *post_urlenc, struct form_successful_control *post_multipart, bool history_add, const char *referer, bool download, - bool verifiable); + bool verifiable, const char *parent_url); static void browser_window_callback(content_msg msg, struct content *c, intptr_t p1, intptr_t p2, union content_msg_data data); static void browser_window_refresh(void *p); @@ -175,12 +175,12 @@ struct browser_window *browser_window_create(const char *url, */ void browser_window_go(struct browser_window *bw, const char *url, - const char* referer, bool history_add) + const char *referer, bool history_add) { /* All fetches passing through here are verifiable * (i.e are the result of user action) */ browser_window_go_post(bw, url, 0, 0, history_add, referer, - false, true); + false, true, referer); } @@ -195,12 +195,12 @@ void browser_window_go(struct browser_window *bw, const char *url, */ void browser_window_go_unverifiable(struct browser_window *bw, - const char *url, const char* referer, bool history_add) + const char *url, const char *referer, bool history_add) { /* All fetches passing through here are unverifiable * (i.e are not the result of user action) */ browser_window_go_post(bw, url, 0, 0, history_add, referer, - false, false); + false, false, referer); } /** @@ -214,6 +214,8 @@ void browser_window_go_unverifiable(struct browser_window *bw, * \param referer the referring uri (copied), or 0 if none * \param download download, rather than render the uri * \param verifiable this transaction is verifiable + * \param parent_url URL of fetch which spawned this one (copied), + * or 0 if none * * Any existing fetches in the window are aborted. * @@ -227,7 +229,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, char *post_urlenc, struct form_successful_control *post_multipart, bool history_add, const char *referer, bool download, - bool verifiable) + bool verifiable, const char *parent_url) { struct content *c; char *url2; @@ -337,7 +339,7 @@ void browser_window_go_post(struct browser_window *bw, const char *url, bw->download = download; fetchcache_go(c, referer, browser_window_callback, (intptr_t) bw, 0, width, height, - post_urlenc, post_multipart, verifiable); + post_urlenc, post_multipart, verifiable, parent_url); } @@ -475,6 +477,9 @@ void browser_window_callback(content_msg msg, struct content *c, break; case CONTENT_MSG_REDIRECT: + { + const char *prev_url = bw->loading_content->url; + bw->loading_content = 0; browser_window_set_status(bw, messages_get("Redirecting")); @@ -483,7 +488,9 @@ void browser_window_callback(content_msg msg, struct content *c, * referer across the redirect */ browser_window_go_post(bw, data.redirect, 0, 0, bw->history_add, bw->referer, - bw->download, false); + bw->download, false, + bw->referer ? bw->referer : prev_url); + } break; case CONTENT_MSG_REFORMAT: @@ -789,7 +796,7 @@ void browser_window_reload(struct browser_window *bw, bool all) } bw->current_content->fresh = false; browser_window_go_post(bw, bw->current_content->url, 0, 0, - false, 0, false, true); + false, 0, false, true, 0); } @@ -1443,7 +1450,7 @@ void browser_window_mouse_action_html(struct browser_window *bw, mouse & BROWSER_MOUSE_MOD_1) { /* force download of link */ browser_window_go_post(bw, url, 0, 0, false, - c->url, true, true); + c->url, true, true, 0); } else if (mouse & BROWSER_MOUSE_CLICK_1) { bw = browser_window_find_target(bw, target); @@ -2304,14 +2311,14 @@ void browser_form_submit(struct browser_window *bw, const char *target, } browser_window_go_post(bw_form, form->action, data, 0, true, bw->current_content->url, - false, true); + false, true, 0); break; case method_POST_MULTIPART: browser_window_go_post(bw_form, form->action, 0, success, true, bw->current_content->url, - false, true); + false, true, 0); break; default: diff --git a/render/html.c b/render/html.c index 830611d54..5ea64a985 100644 --- a/render/html.c +++ b/render/html.c @@ -613,10 +613,10 @@ bool html_find_stylesheets(struct content *c, xmlNode *head) if (!c->data.html.stylesheet_content[STYLESHEET_BASE]) return false; c->active++; - fetchcache_go(c->data.html.stylesheet_content[STYLESHEET_BASE], 0, - html_convert_css_callback, (intptr_t) c, + fetchcache_go(c->data.html.stylesheet_content[STYLESHEET_BASE], + c->url, html_convert_css_callback, (intptr_t) c, STYLESHEET_BASE, c->width, c->height, - 0, 0, false); + 0, 0, false, 0); if (option_block_ads) { c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = @@ -629,9 +629,9 @@ bool html_find_stylesheets(struct content *c, xmlNode *head) c->active++; fetchcache_go(c->data.html. stylesheet_content[STYLESHEET_ADBLOCK], - 0, html_convert_css_callback, (intptr_t) c, - STYLESHEET_ADBLOCK, c->width, - c->height, 0, 0, false); + c->url, html_convert_css_callback, + (intptr_t) c, STYLESHEET_ADBLOCK, c->width, + c->height, 0, 0, false, 0); } for (node = head == 0 ? 0 : head->children; node; node = node->next) { @@ -703,7 +703,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *head) c->url, html_convert_css_callback, (intptr_t) c, i, c->width, c->height, - 0, 0, false); + 0, 0, false, c->url); free(url); i++; @@ -890,7 +890,8 @@ void html_convert_css_callback(content_msg msg, struct content *css, c->url, html_convert_css_callback, (intptr_t) c, i, css->width, - css->height, 0, 0, false); + css->height, 0, 0, false, + c->url); } break; @@ -977,7 +978,7 @@ bool html_fetch_object(struct content *c, char *url, struct box *box, fetchcache_go(c_fetch, c->url, html_object_callback, (intptr_t) c, i, available_width, available_height, - 0, 0, false); + 0, 0, false, c->url); return true; } @@ -1044,7 +1045,7 @@ bool html_replace_object(struct content *c, unsigned int i, char *url, html_object_callback, (intptr_t) c, i, c->data.html.object[i].box->width, c->data.html.object[i].box->height, - post_urlenc, post_multipart, false); + post_urlenc, post_multipart, false, c->url); return true; } @@ -1144,7 +1145,8 @@ void html_object_callback(content_msg msg, struct content *object, html_object_callback, (intptr_t) c, i, 0, 0, - 0, 0, false); + 0, 0, + false, c->url); } } break; diff --git a/riscos/plugin.c b/riscos/plugin.c index 1ac86970f..302651e26 100644 --- a/riscos/plugin.c +++ b/riscos/plugin.c @@ -1659,7 +1659,7 @@ bool plugin_start_fetch(struct plugin_stream *p, const char *url) p->c = c; fetchcache_go(c, 0, plugin_stream_callback, (intptr_t)p, 0, - 100, 100, 0, 0, false); + 100, 100, 0, 0, false, 0); return true; }