mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-25 07:49:38 +03:00
add internal query page for request timeouts
This commit is contained in:
parent
1176ce4271
commit
76eac19227
@ -89,6 +89,11 @@ static const char *authentication_description_fallback = "The site %s is request
|
||||
*/
|
||||
static const char *privacy_description_fallback = "A privacy error occurred while communicating with %s this may be a site configuration error or an attempt to steal private information (passwords, messages or credit cards)";
|
||||
|
||||
/**
|
||||
* timeout query description if messages fails to retrieve usable text
|
||||
*/
|
||||
static const char *timeout_description_fallback = "A connection to %s could not be established. The site may be temporarily unavailable or too busy to respond.";
|
||||
|
||||
/**
|
||||
* issue fetch callbacks with locking
|
||||
*/
|
||||
@ -939,15 +944,18 @@ fetch_about_query_auth_handler_aborted:
|
||||
|
||||
|
||||
/**
|
||||
* generate the description of the privacy query
|
||||
* generate a query description
|
||||
*/
|
||||
static nserror get_privacy_description(struct nsurl *url, char **out_str)
|
||||
static nserror
|
||||
get_query_description(struct nsurl *url,
|
||||
const char *key,
|
||||
const char *fallback,
|
||||
char **out_str)
|
||||
{
|
||||
nserror res;
|
||||
char *url_s;
|
||||
size_t url_l;
|
||||
char *str = NULL;
|
||||
const char *key = "PrivacyDescription";
|
||||
|
||||
/* get the host in question */
|
||||
res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
|
||||
@ -967,10 +975,10 @@ static nserror get_privacy_description(struct nsurl *url, char **out_str)
|
||||
* fall back to basic english.
|
||||
*/
|
||||
int slen;
|
||||
slen = snprintf(str, 0, privacy_description_fallback, url_s) + 1;
|
||||
slen = snprintf(str, 0, fallback, url_s) + 1;
|
||||
str = malloc(slen);
|
||||
if (str != NULL) {
|
||||
snprintf(str, slen, privacy_description_fallback, url_s);
|
||||
snprintf(str, slen, fallback, url_s);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1049,7 +1057,10 @@ static bool fetch_about_query_privacy_handler(struct fetch_about_context *ctx)
|
||||
goto fetch_about_query_ssl_handler_aborted;
|
||||
}
|
||||
|
||||
res = get_privacy_description(siteurl, &description);
|
||||
res = get_query_description(siteurl,
|
||||
"PrivacyDescription",
|
||||
privacy_description_fallback,
|
||||
&description);
|
||||
if (res == NSERROR_OK) {
|
||||
res = ssenddataf(ctx, "<div><p>%s</p></div>", description);
|
||||
free(description);
|
||||
@ -1105,6 +1116,129 @@ fetch_about_query_ssl_handler_aborted:
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler to generate about scheme timeout query page
|
||||
*
|
||||
* \param ctx The fetcher context.
|
||||
* \return true if handled false if aborted.
|
||||
*/
|
||||
static bool fetch_about_query_timeout_handler(struct fetch_about_context *ctx)
|
||||
{
|
||||
nserror res;
|
||||
char *url_s;
|
||||
size_t url_l;
|
||||
const char *reason = "";
|
||||
const char *title;
|
||||
struct nsurl *siteurl = NULL;
|
||||
char *description = NULL;
|
||||
const struct fetch_multipart_data *curmd; /* mutipart data iterator */
|
||||
|
||||
/* extract parameters from multipart post data */
|
||||
curmd = ctx->multipart;
|
||||
while (curmd != NULL) {
|
||||
if (strcmp(curmd->name, "siteurl") == 0) {
|
||||
res = nsurl_create(curmd->value, &siteurl);
|
||||
if (res != NSERROR_OK) {
|
||||
return fetch_about_srverror(ctx);
|
||||
}
|
||||
} else if (strcmp(curmd->name, "reason") == 0) {
|
||||
reason = curmd->value;
|
||||
}
|
||||
curmd = curmd->next;
|
||||
}
|
||||
|
||||
if (siteurl == NULL) {
|
||||
return fetch_about_srverror(ctx);
|
||||
}
|
||||
|
||||
/* content is going to return ok */
|
||||
fetch_set_http_code(ctx->fetchh, 200);
|
||||
|
||||
/* content type */
|
||||
if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
|
||||
title = messages_get("TimeoutTitle");
|
||||
res = ssenddataf(ctx,
|
||||
"<html>\n<head>\n"
|
||||
"<title>%s</title>\n"
|
||||
"<link rel=\"stylesheet\" type=\"text/css\" "
|
||||
"href=\"resource:internal.css\">\n"
|
||||
"</head>\n"
|
||||
"<body id =\"timeout\">\n"
|
||||
"<h1>%s</h1>\n",
|
||||
title, title);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
|
||||
res = ssenddataf(ctx,
|
||||
"<form method=\"post\""
|
||||
" enctype=\"multipart/form-data\">");
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
|
||||
res = get_query_description(siteurl,
|
||||
"TimeoutDescription",
|
||||
timeout_description_fallback,
|
||||
&description);
|
||||
if (res == NSERROR_OK) {
|
||||
res = ssenddataf(ctx, "<div><p>%s</p></div>", description);
|
||||
free(description);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
}
|
||||
res = ssenddataf(ctx, "<div><p>%s</p></div>", reason);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
|
||||
res = ssenddataf(ctx,
|
||||
"<div id=\"buttons\">"
|
||||
"<input type=\"submit\" id=\"back\" name=\"back\" "
|
||||
"value=\"%s\" class=\"default-action\">"
|
||||
"<input type=\"submit\" id=\"retry\" name=\"retry\" "
|
||||
"value=\"%s\">"
|
||||
"</div>",
|
||||
messages_get("Backtoprevious"),
|
||||
messages_get("TryAgain"));
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
|
||||
res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
|
||||
if (res != NSERROR_OK) {
|
||||
url_s = strdup("");
|
||||
}
|
||||
res = ssenddataf(ctx,
|
||||
"<input type=\"hidden\" name=\"siteurl\" value=\"%s\">",
|
||||
url_s);
|
||||
free(url_s);
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
|
||||
res = ssenddataf(ctx, "</form></body>\n</html>\n");
|
||||
if (res != NSERROR_OK) {
|
||||
goto fetch_about_query_timeout_handler_aborted;
|
||||
}
|
||||
|
||||
fetch_about_send_finished(ctx);
|
||||
|
||||
nsurl_unref(siteurl);
|
||||
|
||||
return true;
|
||||
|
||||
fetch_about_query_timeout_handler_aborted:
|
||||
nsurl_unref(siteurl);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Forward declaration because this handler requires the handler table. */
|
||||
static bool fetch_about_about_handler(struct fetch_about_context *ctx);
|
||||
|
||||
@ -1211,6 +1345,13 @@ struct about_handlers about_handler_list[] = {
|
||||
NULL,
|
||||
fetch_about_query_privacy_handler,
|
||||
true
|
||||
},
|
||||
{
|
||||
"query/timeout",
|
||||
SLEN("query/timeout"),
|
||||
NULL,
|
||||
fetch_about_query_timeout_handler,
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1181,6 +1181,41 @@ browser_window__handle_bad_certs(struct browser_window *bw,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a timeout during a fetch
|
||||
*/
|
||||
static nserror
|
||||
browser_window__handle_timeout(struct browser_window *bw, nsurl *url)
|
||||
{
|
||||
struct browser_fetch_parameters params;
|
||||
nserror err;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
params.url = nsurl_ref(corestring_nsurl_about_query_timeout);
|
||||
params.referrer = nsurl_ref(url);
|
||||
params.flags = BW_NAVIGATE_HISTORY | BW_NAVIGATE_NO_TERMINAL_HISTORY_UPDATE | BW_NAVIGATE_INTERNAL;
|
||||
|
||||
err = fetch_multipart_data_new_kv(¶ms.post_multipart,
|
||||
"siteurl",
|
||||
nsurl_access(url));
|
||||
if (err != NSERROR_OK) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now we issue the fetch */
|
||||
bw->internal_nav = true;
|
||||
err = browser_window__navigate_internal(bw, ¶ms);
|
||||
if (err != NSERROR_OK) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
browser_window__free_fetch_parameters(¶ms);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle errors during content fetch
|
||||
*/
|
||||
@ -1208,6 +1243,9 @@ browser_window__handle_error(struct browser_window *bw,
|
||||
case NSERROR_BAD_REDIRECT:
|
||||
/* The message is already filled out */
|
||||
break;
|
||||
case NSERROR_TIMEOUT:
|
||||
do_warning = false;
|
||||
break;
|
||||
default:
|
||||
if (message == NULL) {
|
||||
message = messages_get_errorcode(code);
|
||||
@ -1239,6 +1277,9 @@ browser_window__handle_error(struct browser_window *bw,
|
||||
case NSERROR_BAD_CERTS:
|
||||
res = browser_window__handle_bad_certs(bw, url);
|
||||
break;
|
||||
case NSERROR_TIMEOUT:
|
||||
res = browser_window__handle_timeout(bw, url);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2368,6 +2409,8 @@ is_internal_navigate_url(nsurl *url)
|
||||
is_internal = true;
|
||||
} else if (path == corestring_lwc_query_ssl) {
|
||||
is_internal = true;
|
||||
} else if (path == corestring_lwc_query_timeout) {
|
||||
is_internal = true;
|
||||
}
|
||||
}
|
||||
lwc_string_unref(path);
|
||||
@ -3338,12 +3381,16 @@ browser_window_navigate(struct browser_window *bw,
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal navigation handler for normal fetches
|
||||
*/
|
||||
static nserror
|
||||
browser_window__navigate_internal_real(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
navigate_internal_real(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
{
|
||||
uint32_t fetch_flags = 0;
|
||||
bool fetch_is_post = (params->post_urlenc != NULL || params->post_multipart != NULL);
|
||||
bool fetch_is_post;
|
||||
llcache_post_data post;
|
||||
hlcache_child_context child;
|
||||
nserror res;
|
||||
@ -3351,6 +3398,8 @@ browser_window__navigate_internal_real(struct browser_window *bw,
|
||||
|
||||
NSLOG(netsurf, INFO, "Loading '%s'", nsurl_access(params->url));
|
||||
|
||||
fetch_is_post = (params->post_urlenc != NULL || params->post_multipart != NULL);
|
||||
|
||||
/* Clear SSL info for load */
|
||||
bw->loading_ssl_info.num = 0;
|
||||
|
||||
@ -3424,6 +3473,7 @@ browser_window__navigate_internal_real(struct browser_window *bw,
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal navigation handler for the authentication query handler
|
||||
*
|
||||
@ -3431,8 +3481,8 @@ browser_window__navigate_internal_real(struct browser_window *bw,
|
||||
* then we deal with that, otherwise we pass it on to the about: handler
|
||||
*/
|
||||
static nserror
|
||||
browser_window__navigate_internal_query_auth(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
navigate_internal_query_auth(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
{
|
||||
char *userpass = NULL;
|
||||
const char *username, *password, *realm, *siteurl;
|
||||
@ -3447,7 +3497,7 @@ browser_window__navigate_internal_query_auth(struct browser_window *bw,
|
||||
|
||||
if (!(is_login || is_cancel)) {
|
||||
/* This is a request, so pass it on */
|
||||
return browser_window__navigate_internal_real(bw, params);
|
||||
return navigate_internal_real(bw, params);
|
||||
}
|
||||
|
||||
if (is_cancel) {
|
||||
@ -3497,7 +3547,7 @@ browser_window__navigate_internal_query_auth(struct browser_window *bw,
|
||||
|
||||
/* Finally navigate to the original loading parameters */
|
||||
bw->internal_nav = false;
|
||||
return browser_window__navigate_internal_real(bw, &bw->loading_parameters);
|
||||
return navigate_internal_real(bw, &bw->loading_parameters);
|
||||
}
|
||||
|
||||
|
||||
@ -3508,8 +3558,8 @@ browser_window__navigate_internal_query_auth(struct browser_window *bw,
|
||||
* then we deal with that, otherwise we pass it on to the about: handler
|
||||
*/
|
||||
static nserror
|
||||
browser_window__navigate_internal_query_ssl(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
navigate_internal_query_ssl(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
{
|
||||
bool is_proceed = false, is_back = false;
|
||||
|
||||
@ -3520,23 +3570,64 @@ browser_window__navigate_internal_query_ssl(struct browser_window *bw,
|
||||
|
||||
if (!(is_proceed || is_back)) {
|
||||
/* This is a request, so pass it on */
|
||||
return browser_window__navigate_internal_real(bw, params);
|
||||
return navigate_internal_real(bw, params);
|
||||
}
|
||||
|
||||
return browser_window__handle_ssl_query_response(is_proceed, bw);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal navigation handler for the timeout query page.
|
||||
*
|
||||
* If the parameters indicate we're processing a *response* from the handler
|
||||
* then we deal with that, otherwise we pass it on to the about: handler
|
||||
*/
|
||||
static nserror
|
||||
navigate_internal_query_timeout(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
{
|
||||
bool is_retry = false, is_back = false;
|
||||
|
||||
NSLOG(netsurf, INFO, "bw:%p params:%p", bw, params);
|
||||
|
||||
assert(params->post_multipart != NULL);
|
||||
|
||||
is_retry = fetch_multipart_data_find(params->post_multipart, "retry") != NULL;
|
||||
is_back = fetch_multipart_data_find(params->post_multipart, "back") != NULL;
|
||||
|
||||
if (is_back) {
|
||||
/* do a rough-and-ready nav to the old 'current'
|
||||
* parameters, with any post data stripped away
|
||||
*/
|
||||
return browser_window__reload_current_parameters(bw);
|
||||
}
|
||||
|
||||
if (is_retry) {
|
||||
/* Finally navigate to the original loading parameters */
|
||||
bw->internal_nav = false;
|
||||
return navigate_internal_real(bw, &bw->loading_parameters);
|
||||
}
|
||||
|
||||
return navigate_internal_real(bw, params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dispatch to internal query handlers or normal navigation
|
||||
*
|
||||
* Here we determine if we're navigating to an internal query URI and
|
||||
* if so, what we need to do about it.
|
||||
*
|
||||
* \note these check must match those in is_internal_navigate_url()
|
||||
*
|
||||
* If we're not, then we just move on to the real navigate.
|
||||
*/
|
||||
nserror
|
||||
browser_window__navigate_internal(struct browser_window *bw,
|
||||
struct browser_fetch_parameters *params)
|
||||
{
|
||||
lwc_string *scheme, *path;
|
||||
/* Here we determine if we're navigating to an internal query URI
|
||||
* and if so, what we need to do about it.
|
||||
*
|
||||
* If we're not, then we just move on to the real navigate.
|
||||
*/
|
||||
|
||||
/* All our special URIs are in the about: scheme */
|
||||
scheme = nsurl_get_component(params->url, NSURL_SCHEME);
|
||||
@ -3550,18 +3641,22 @@ browser_window__navigate_internal(struct browser_window *bw,
|
||||
path = nsurl_get_component(params->url, NSURL_PATH);
|
||||
if (path == corestring_lwc_query_auth) {
|
||||
lwc_string_unref(path);
|
||||
return browser_window__navigate_internal_query_auth(bw, params);
|
||||
return navigate_internal_query_auth(bw, params);
|
||||
}
|
||||
if (path == corestring_lwc_query_ssl) {
|
||||
lwc_string_unref(path);
|
||||
return browser_window__navigate_internal_query_ssl(bw, params);
|
||||
return navigate_internal_query_ssl(bw, params);
|
||||
}
|
||||
if (path == corestring_lwc_query_timeout) {
|
||||
lwc_string_unref(path);
|
||||
return navigate_internal_query_timeout(bw, params);
|
||||
}
|
||||
lwc_string_unref(path);
|
||||
|
||||
/* Fall through to a normal about: fetch */
|
||||
|
||||
normal_fetch:
|
||||
return browser_window__navigate_internal_real(bw, params);
|
||||
return navigate_internal_real(bw, params);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1087,6 +1087,15 @@ en.all.SSLCertErrRevoked:The certificate has been revoked by the issuer.
|
||||
en.all.SSLCertErrHostnameMismatch:The certificate is for a different host than the server
|
||||
|
||||
|
||||
# Timeout error interface
|
||||
# =======================
|
||||
#
|
||||
en.all.TimeoutTitle:Connection timed out
|
||||
en.all.TimeoutDescription: A connection to %s could not be established. The site may be temporarily unavailable or too busy to respond.
|
||||
en.all.Backtoprevious: Back
|
||||
en.all.TryAgain: Try Again
|
||||
|
||||
|
||||
# SSL certificate viewer
|
||||
# ======================
|
||||
#
|
||||
|
@ -343,3 +343,41 @@ body#privacy div#buttons {
|
||||
body#privacy div#buttons input#back {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
/*
|
||||
* timeout query styling
|
||||
*/
|
||||
|
||||
body#timeout {
|
||||
max-width: 45em;
|
||||
}
|
||||
|
||||
body#timeout h1 {
|
||||
padding: 0.8em 0.4em 0.5em 0.4em;
|
||||
border-bottom: 0.1em solid #444;
|
||||
margin: 0 0 1.3em 0;
|
||||
background: #c55;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body#timeout form {
|
||||
/* Just to center the form on the page */
|
||||
margin: 0 auto;
|
||||
/* To see the outline of the form */
|
||||
padding: 1em;
|
||||
border: 1px solid #CCC;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
body#timeout form div + div {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
body#timeout div#buttons {
|
||||
text-align: right;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
body#timeout div#buttons input#back {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
@ -148,6 +148,7 @@ CORESTRING_LWC_VALUE(no_cache, "no-cache");
|
||||
CORESTRING_LWC_VALUE(no_store, "no-store");
|
||||
CORESTRING_LWC_VALUE(query_auth, "query/auth");
|
||||
CORESTRING_LWC_VALUE(query_ssl, "query/ssl");
|
||||
CORESTRING_LWC_VALUE(query_timeout, "query/timeout");
|
||||
|
||||
/* mime types */
|
||||
CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
|
||||
@ -360,6 +361,7 @@ CORESTRING_DOM_VALUE(html_namespace, "http://www.w3.org/1999/xhtml");
|
||||
CORESTRING_NSURL(about_blank, "about:blank");
|
||||
CORESTRING_NSURL(about_query_ssl, "about:query/ssl");
|
||||
CORESTRING_NSURL(about_query_auth, "about:query/auth");
|
||||
CORESTRING_NSURL(about_query_timeout, "about:query/timeout");
|
||||
|
||||
#undef CORESTRING_LWC_STRING
|
||||
#undef CORESTRING_DOM_STRING
|
||||
|
Loading…
Reference in New Issue
Block a user