Gitweb links:
...log
http://git.netsurf-browser.org/netsurf.git/shortlog/4eb06ad2cf2b702597461...
...commit
http://git.netsurf-browser.org/netsurf.git/commit/4eb06ad2cf2b7025974618b...
...tree
http://git.netsurf-browser.org/netsurf.git/tree/4eb06ad2cf2b7025974618be9...
The branch, master has been updated
via 4eb06ad2cf2b7025974618be943dea9718d09319 (commit)
via 4b0c3f0efef2239dd5d62a9e73eeec4037c056a4 (commit)
via 76eac192272acf77763d0c619cd78118650748cf (commit)
from 1176ce427113face73c48c4b2e4e5a810577b355 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=4eb06ad2cf2b7025974...
commit 4eb06ad2cf2b7025974618be943dea9718d09319
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
move the fallback text for about handler into messages handler
diff --git a/content/fetchers/about.c b/content/fetchers/about.c
index e98c6ec..02bac81 100644
--- a/content/fetchers/about.c
+++ b/content/fetchers/about.c
@@ -79,25 +79,6 @@ struct about_handlers {
bool hidden; /**< If entry should be hidden in listing */
};
-/**
- * authentication query description if messages fails to retrieve usable text
- */
-static const char *authentication_description_fallback = "The site %s is requesting
your username and password. The realm is \"%s\"";
-
-/**
- * privacy query description if messages fails to retrieve usable text
- */
-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.";
-
-/**
- * fetcherror query description if messages fails to retrieve usable text
- */
-static const char *fetcherror_description_fallback = "An error occoured when
connecting to %s";
/**
* issue fetch callbacks with locking
@@ -740,7 +721,6 @@ get_authentication_description(struct nsurl *url,
char *url_s;
size_t url_l;
char *str = NULL;
- int slen;
const char *key;
res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
@@ -755,23 +735,46 @@ get_authentication_description(struct nsurl *url,
}
str = messages_get_buff(key, url_s, realm);
- NSLOG(netsurf, INFO,
- "key:%s url:%s realm:%s str:%s", key, url_s, realm, str);
-
- if ((str != NULL) && (strcmp(key, str) != 0)) {
+ if (str != NULL) {
+ NSLOG(netsurf, INFO,
+ "key:%s url:%s realm:%s str:%s",
+ key, url_s, realm, str);
*out_str = str;
} else {
- /* no message so fallback */
- slen = snprintf(str, 0, authentication_description_fallback,
- url_s, realm) + 1;
- str = malloc(slen);
- if (str == NULL) {
- res = NSERROR_NOMEM;
- } else {
- snprintf(str, slen, authentication_description_fallback,
- url_s, realm);
- *out_str = str;
- }
+ res = NSERROR_NOMEM;
+ }
+
+ free(url_s);
+
+ return res;
+}
+
+
+/**
+ * generate a generic query description
+ */
+static nserror
+get_query_description(struct nsurl *url,
+ const char *key,
+ char **out_str)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ char *str = NULL;
+
+ /* get the host in question */
+ res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* obtain the description with the url substituted */
+ str = messages_get_buff(key, url_s);
+ if (str == NULL) {
+ res = NSERROR_NOMEM;
+ } else {
+ *out_str = str;
}
free(url_s);
@@ -949,56 +952,6 @@ fetch_about_query_auth_handler_aborted:
/**
- * generate a query description
- */
-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;
-
- /* get the host in question */
- res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
- if (res != NSERROR_OK) {
- return res;
- }
-
- /* obtain the description with the url substituted */
- str = messages_get_buff(key, url_s);
- if ((str != NULL) && (strcmp(key, str) == 0)) {
- /* the returned string was simply the key */
- free(str);
- str = NULL;
- }
- if (str == NULL) {
- /* failed to get suitable translated message text so
- * fall back to basic english.
- */
- int slen;
- slen = snprintf(str, 0, fallback, url_s) + 1;
- str = malloc(slen);
- if (str != NULL) {
- snprintf(str, slen, fallback, url_s);
- }
- }
-
- if (str == NULL) {
- res = NSERROR_NOMEM;
- } else {
- *out_str = str;
- }
- free(url_s);
-
- return res;
-}
-
-
-/**
* Handler to generate about scheme privacy query page
*
* \param ctx The fetcher context.
@@ -1064,7 +1017,6 @@ static bool fetch_about_query_privacy_handler(struct
fetch_about_context *ctx)
res = get_query_description(siteurl,
"PrivacyDescription",
- privacy_description_fallback,
&description);
if (res == NSERROR_OK) {
res = ssenddataf(ctx, "<div><p>%s</p></div>",
description);
@@ -1187,7 +1139,6 @@ static bool fetch_about_query_timeout_handler(struct
fetch_about_context *ctx)
res = get_query_description(siteurl,
"TimeoutDescription",
- timeout_description_fallback,
&description);
if (res == NSERROR_OK) {
res = ssenddataf(ctx, "<div><p>%s</p></div>",
description);
@@ -1311,7 +1262,6 @@ fetch_about_query_fetcherror_handler(struct fetch_about_context
*ctx)
res = get_query_description(siteurl,
"FetchErrorDescription",
- fetcherror_description_fallback,
&description);
if (res == NSERROR_OK) {
res = ssenddataf(ctx, "<div><p>%s</p></div>",
description);
diff --git a/resources/FatMessages b/resources/FatMessages
index 06d61c9..5ebf607 100644
--- a/resources/FatMessages
+++ b/resources/FatMessages
@@ -25,7 +25,7 @@
#
# The split-messages tool requires keys for all languages to be
# grouped together but language order is not important. If a key for a
-# specific language is ommited the default language value will be used
+# specific language is omitted the default language value will be used
# instead (currently en)
#
# If you find something tagged 'all', but it is only relevant to a specific
@@ -1099,8 +1099,8 @@ en.all.TryAgain: Try Again
# Fetch error interface
# =======================
#
-en.all.FetchErrorTitle:Error occured fetching page
-en.all.FetchErrorDescription:An error occoured when connecting to %s
+en.all.FetchErrorTitle:Error occurred fetching page
+en.all.FetchErrorDescription:An error occurred when connecting to %s
# SSL certificate viewer
diff --git a/test/messages.c b/test/messages.c
index ae82d1e..3ec770a 100644
--- a/test/messages.c
+++ b/test/messages.c
@@ -118,8 +118,7 @@ START_TEST(message_get_buff_test)
ck_assert_int_eq(res, NSERROR_OK);
buf = messages_get_buff("DefinitelyNotAKey");
- ck_assert_str_eq(buf, "DefinitelyNotAKey");
- free(buf);
+ ck_assert(buf == NULL);
buf = messages_get_buff("NoMemory");
ck_assert_str_eq(buf, "NetSurf is running out of memory. Please free some memory
and try again.");
diff --git a/utils/hashtable.c b/utils/hashtable.c
index 4935d6b..aa162cb 100644
--- a/utils/hashtable.c
+++ b/utils/hashtable.c
@@ -347,10 +347,12 @@ const char *hash_get(struct hash_table *ht, const char *key)
h = hash_string_fnv(key, &key_length);
c = h % ht->nchains;
- for (e = ht->chain[c]; e; e = e->next)
+ for (e = ht->chain[c]; e; e = e->next) {
if ((key_length == e->key_length) &&
- (memcmp(key, e->pairing, key_length) == 0))
+ (memcmp(key, e->pairing, key_length) == 0)) {
return e->pairing + key_length + 1;
+ }
+ }
return NULL;
}
diff --git a/utils/messages.c b/utils/messages.c
index 197d45e..5525e18 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -42,11 +42,69 @@
/** Messages are stored in a fixed-size hash table. */
#define HASH_SIZE 101
-/** The hash table used to store the standard Messages file for the old API */
+/**
+ * The hash table used to store the standard Messages file for the old API
+ */
static struct hash_table *messages_hash = NULL;
/**
+ * Create a message context
+ *
+ * generate a message context populated with english fallbacks for
+ * some formatted messages.
+ */
+static struct hash_table *messages_create_ctx(int hash_size)
+{
+ struct hash_table *nctx;
+ const struct {
+ const char *key;
+ const char *value;
+ } fallback[] = {
+ { "LoginDescription",
+ "The site %s is requesting your username and password. "
+ "The realm is \"%s\""},
+ { "PrivacyDescription",
+ "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)"},
+ { "TimeoutDescription",
+ "A connection to %s could not be established. The site may "
+ "be temporarily unavailable or too busy to respond."},
+ { "FetchErrorDescription",
+ "An error occurred when connecting to %s"},
+ { NULL, NULL}
+ };
+ nctx = hash_create(hash_size);
+
+ if (nctx != NULL) {
+ int floop;
+ for (floop = 0; fallback[floop].key != NULL; floop++) {
+ hash_add(nctx,
+ fallback[floop].key,
+ fallback[floop].value);
+ }
+ }
+
+ return nctx;
+}
+
+/**
+ * Free memory used by a messages hash.
+ * The context will not be valid after this function returns.
+ *
+ * \param ctx context of messages file to free
+ */
+static void messages_destroy_ctx(struct hash_table *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ hash_destroy(ctx);
+}
+
+
+/**
* Read keys and values from messages file.
*
* \param path pathname of messages file
@@ -66,7 +124,7 @@ static nserror messages_load_ctx(const char *path, struct hash_table
**ctx)
return hash_add_file(*ctx, path);
}
- nctx = hash_create(HASH_SIZE);
+ nctx = messages_create_ctx(HASH_SIZE);
if (nctx == NULL) {
NSLOG(netsurf, INFO,
"Unable to create hash table for messages file %s",
@@ -115,21 +173,6 @@ messages_get_ctx(const char *key, struct hash_table *ctx)
}
-/**
- * Free memory used by a messages hash.
- * The context will not be valid after this function returns.
- *
- * \param ctx context of messages file to free
- */
-static void messages_destroy_ctx(struct hash_table *ctx)
-{
- if (ctx == NULL)
- return;
-
- hash_destroy(ctx);
-}
-
-
/* exported interface documented in messages.h */
nserror messages_add_from_file(const char *path)
{
@@ -148,7 +191,7 @@ nserror messages_add_from_inline(const uint8_t *data, size_t size)
{
/* ensure the hash table is initialised */
if (messages_hash == NULL) {
- messages_hash = hash_create(HASH_SIZE);
+ messages_hash = messages_create_ctx(HASH_SIZE);
}
if (messages_hash == NULL) {
NSLOG(netsurf, INFO, "Unable to create hash table");
@@ -157,6 +200,7 @@ nserror messages_add_from_inline(const uint8_t *data, size_t size)
return hash_add_inline(messages_hash, data, size);
}
+
/* exported interface documented in messages.h */
char *messages_get_buff(const char *key, ...)
{
@@ -165,7 +209,17 @@ char *messages_get_buff(const char *key, ...)
int buff_len = 0;
va_list ap;
- msg_fmt = messages_get_ctx(key, messages_hash);
+ assert(key != NULL);
+
+ if (messages_hash == NULL) {
+ return NULL;
+ }
+
+ msg_fmt = hash_get(messages_hash, key);
+
+ if (msg_fmt == NULL) {
+ return NULL;
+ }
va_start(ap, key);
buff_len = vsnprintf(buff, buff_len, msg_fmt, ap);
diff --git a/utils/messages.h b/utils/messages.h
index 635d6e8..5da35e4 100644
--- a/utils/messages.h
+++ b/utils/messages.h
@@ -16,7 +16,8 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Localised message support (interface).
*
* The messages module loads a file of keys and associated strings, and
@@ -30,8 +31,8 @@
* file table. Use the _ctx versions of the functions to do this.
*/
-#ifndef _NETSURF_UTILS_MESSAGES_H_
-#define _NETSURF_UTILS_MESSAGES_H_
+#ifndef NETSURF_UTILS_MESSAGES_H_
+#define NETSURF_UTILS_MESSAGES_H_
#include <stdint.h>
@@ -90,13 +91,12 @@ const char *messages_get_sslcode(ssl_cert_err code);
/**
* Formatted message from a key in the global message hash.
*
- * \param key key of message
+ * \param key key of message
* \param ... message parameters
- * \return buffer containing formatted message text or NULL if memory
- * is unavailable. The caller owns the returned buffer and is
- * responsible for freeing it.
+ * \return buffer containing formatted message text or NULL if key is
+ * unavailable or memory allocation failed. The caller owns the
+ * returned buffer and is responsible for freeing it.
*/
-
char *messages_get_buff(const char *key, ...);
/**
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=4b0c3f0efef2239dd5d...
commit 4b0c3f0efef2239dd5d62a9e73eeec4037c056a4
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
add internal query handler for fetch errors
Any errors from the fetch which are not already handled are
reported with an internal query page instead of a modal
dialog.
This is much less invasive for the user and much more in
keeping with how this is handled by other browsers.
The handler is similar to the timeout handler but the
functionality is kept separate as it is intended timeout
handling be extended in future.
diff --git a/content/fetchers/about.c b/content/fetchers/about.c
index d8a5fa7..e98c6ec 100644
--- a/content/fetchers/about.c
+++ b/content/fetchers/about.c
@@ -95,6 +95,11 @@ static const char *privacy_description_fallback = "A privacy error
occurred whil
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.";
/**
+ * fetcherror query description if messages fails to retrieve usable text
+ */
+static const char *fetcherror_description_fallback = "An error occoured when
connecting to %s";
+
+/**
* issue fetch callbacks with locking
*/
static inline bool
@@ -1239,6 +1244,130 @@ fetch_about_query_timeout_handler_aborted:
}
+/**
+ * Handler to generate about scheme fetch error query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+static bool
+fetch_about_query_fetcherror_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_fetcherror_handler_aborted;
+ }
+
+ title = messages_get("FetchErrorTitle");
+ 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 =\"fetcherror\">\n"
+ "<h1>%s</h1>\n",
+ title, title);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = ssenddataf(ctx,
+ "<form method=\"post\""
+ " enctype=\"multipart/form-data\">");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = get_query_description(siteurl,
+ "FetchErrorDescription",
+ fetcherror_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_fetcherror_handler_aborted;
+ }
+ }
+ res = ssenddataf(ctx, "<div><p>%s</p></div>",
reason);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_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_fetcherror_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_fetcherror_handler_aborted;
+ }
+
+ res = ssenddataf(ctx, "</form></body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ nsurl_unref(siteurl);
+
+ return true;
+
+fetch_about_query_fetcherror_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);
@@ -1352,6 +1481,13 @@ struct about_handlers about_handler_list[] = {
NULL,
fetch_about_query_timeout_handler,
true
+ },
+ {
+ "query/fetcherror",
+ SLEN("query/fetcherror"),
+ NULL,
+ fetch_about_query_fetcherror_handler,
+ true
}
};
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index 5f7c2cc..807393e 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -1217,6 +1217,50 @@ browser_window__handle_timeout(struct browser_window *bw, nsurl
*url)
/**
+ * Handle non specific errors during a fetch
+ */
+static nserror
+browser_window__handle_fetcherror(struct browser_window *bw,
+ const char *reason,
+ nsurl *url)
+{
+ struct browser_fetch_parameters params;
+ nserror err;
+
+ memset(¶ms, 0, sizeof(params));
+
+ params.url = nsurl_ref(corestring_nsurl_about_query_fetcherror);
+ 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;
+ }
+
+ err = fetch_multipart_data_new_kv(¶ms.post_multipart,
+ "reason",
+ reason);
+ 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
*/
static nserror
@@ -1226,39 +1270,14 @@ browser_window__handle_error(struct browser_window *bw,
{
const char *message = event->data.errordata.errormsg;
nserror code = event->data.errordata.errorcode;
- bool do_warning = true;
nserror res;
nsurl *url = hlcache_handle_get_url(c);
/* Unexpected OK? */
assert(code != NSERROR_OK);
- switch (code) {
- case NSERROR_BAD_AUTH:
- do_warning = false;
- break;
- case NSERROR_BAD_CERTS:
- do_warning = false;
- break;
- 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);
- }
- break;
- }
-
- if (do_warning) {
- browser_window_set_status(bw, message);
- /* Only warn the user about errors in top-level windows */
- if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) {
- guit->misc->warning(message, NULL);
- }
+ if (message == NULL) {
+ message = messages_get_errorcode(code);
}
if (c == bw->loading_content) {
@@ -1274,13 +1293,17 @@ browser_window__handle_error(struct browser_window *bw,
case NSERROR_BAD_AUTH:
res = browser_window__handle_login(bw, message, url);
break;
+
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:
+ res = browser_window__handle_fetcherror(bw, message, url);
break;
}
@@ -2411,6 +2434,8 @@ is_internal_navigate_url(nsurl *url)
is_internal = true;
} else if (path == corestring_lwc_query_timeout) {
is_internal = true;
+ } else if (path == corestring_lwc_query_fetcherror) {
+ is_internal = true;
}
}
lwc_string_unref(path);
@@ -3614,6 +3639,42 @@ navigate_internal_query_timeout(struct browser_window *bw,
/**
+ * Internal navigation handler for the fetch error 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_fetcherror(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
@@ -3651,6 +3712,10 @@ browser_window__navigate_internal(struct browser_window *bw,
lwc_string_unref(path);
return navigate_internal_query_timeout(bw, params);
}
+ if (path == corestring_lwc_query_fetcherror) {
+ lwc_string_unref(path);
+ return navigate_internal_query_fetcherror(bw, params);
+ }
lwc_string_unref(path);
/* Fall through to a normal about: fetch */
diff --git a/resources/FatMessages b/resources/FatMessages
index aa2d7a2..06d61c9 100644
--- a/resources/FatMessages
+++ b/resources/FatMessages
@@ -1096,6 +1096,13 @@ en.all.Backtoprevious: Back
en.all.TryAgain: Try Again
+# Fetch error interface
+# =======================
+#
+en.all.FetchErrorTitle:Error occured fetching page
+en.all.FetchErrorDescription:An error occoured when connecting to %s
+
+
# SSL certificate viewer
# ======================
#
diff --git a/resources/internal.css b/resources/internal.css
index 14b47cf..ded56ee 100644
--- a/resources/internal.css
+++ b/resources/internal.css
@@ -381,3 +381,41 @@ body#timeout div#buttons {
body#timeout div#buttons input#back {
margin-right: 1em;
}
+
+/*
+ * fetch error query styling
+ */
+
+body#fetcherror {
+ max-width: 45em;
+}
+
+body#fetcherror 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#fetcherror 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#fetcherror form div + div {
+ margin-top: 1em;
+}
+
+body#fetcherror div#buttons {
+ text-align: right;
+ margin-right: 1em;
+}
+
+body#fetcherror div#buttons input#back {
+ margin-right: 1em;
+}
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
index e7516b1..b109545 100644
--- a/utils/corestringlist.h
+++ b/utils/corestringlist.h
@@ -149,6 +149,7 @@ 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");
+CORESTRING_LWC_VALUE(query_fetcherror, "query/fetcherror");
/* mime types */
CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
@@ -362,6 +363,7 @@ 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");
+CORESTRING_NSURL(about_query_fetcherror, "about:query/fetcherror");
#undef CORESTRING_LWC_STRING
#undef CORESTRING_DOM_STRING
commitdiff
http://git.netsurf-browser.org/netsurf.git/commit/?id=76eac192272acf77763...
commit 76eac192272acf77763d0c619cd78118650748cf
Author: Vincent Sanders <vince(a)kyllikki.org>
Commit: Vincent Sanders <vince(a)kyllikki.org>
add internal query page for request timeouts
diff --git a/content/fetchers/about.c b/content/fetchers/about.c
index df51410..d8a5fa7 100644
--- a/content/fetchers/about.c
+++ b/content/fetchers/about.c
@@ -90,6 +90,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
*/
static inline bool
@@ -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
}
};
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index a6b77b0..5f7c2cc 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -1182,6 +1182,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
*/
static nserror
@@ -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);
}
diff --git a/resources/FatMessages b/resources/FatMessages
index d1ecd9d..aa2d7a2 100644
--- a/resources/FatMessages
+++ b/resources/FatMessages
@@ -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
# ======================
#
diff --git a/resources/internal.css b/resources/internal.css
index e43d183..14b47cf 100644
--- a/resources/internal.css
+++ b/resources/internal.css
@@ -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;
+}
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
index f0d39c6..e7516b1 100644
--- a/utils/corestringlist.h
+++ b/utils/corestringlist.h
@@ -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
-----------------------------------------------------------------------
Summary of changes:
content/fetchers/about.c | 365 +++++++++++++++++++++++++++++++++++++---------
desktop/browser_window.c | 244 +++++++++++++++++++++++++------
resources/FatMessages | 18 ++-
resources/internal.css | 76 ++++++++++
test/messages.c | 3 +-
utils/corestringlist.h | 4 +
utils/hashtable.c | 6 +-
utils/messages.c | 92 +++++++++---
utils/messages.h | 16 +-
9 files changed, 681 insertions(+), 143 deletions(-)
diff --git a/content/fetchers/about.c b/content/fetchers/about.c
index df51410..02bac81 100644
--- a/content/fetchers/about.c
+++ b/content/fetchers/about.c
@@ -79,15 +79,6 @@ struct about_handlers {
bool hidden; /**< If entry should be hidden in listing */
};
-/**
- * authentication query description if messages fails to retrieve usable text
- */
-static const char *authentication_description_fallback = "The site %s is requesting
your username and password. The realm is \"%s\"";
-
-/**
- * privacy query description if messages fails to retrieve usable text
- */
-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)";
/**
* issue fetch callbacks with locking
@@ -730,7 +721,6 @@ get_authentication_description(struct nsurl *url,
char *url_s;
size_t url_l;
char *str = NULL;
- int slen;
const char *key;
res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
@@ -745,23 +735,46 @@ get_authentication_description(struct nsurl *url,
}
str = messages_get_buff(key, url_s, realm);
- NSLOG(netsurf, INFO,
- "key:%s url:%s realm:%s str:%s", key, url_s, realm, str);
-
- if ((str != NULL) && (strcmp(key, str) != 0)) {
+ if (str != NULL) {
+ NSLOG(netsurf, INFO,
+ "key:%s url:%s realm:%s str:%s",
+ key, url_s, realm, str);
*out_str = str;
} else {
- /* no message so fallback */
- slen = snprintf(str, 0, authentication_description_fallback,
- url_s, realm) + 1;
- str = malloc(slen);
- if (str == NULL) {
- res = NSERROR_NOMEM;
- } else {
- snprintf(str, slen, authentication_description_fallback,
- url_s, realm);
- *out_str = str;
- }
+ res = NSERROR_NOMEM;
+ }
+
+ free(url_s);
+
+ return res;
+}
+
+
+/**
+ * generate a generic query description
+ */
+static nserror
+get_query_description(struct nsurl *url,
+ const char *key,
+ char **out_str)
+{
+ nserror res;
+ char *url_s;
+ size_t url_l;
+ char *str = NULL;
+
+ /* get the host in question */
+ res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* obtain the description with the url substituted */
+ str = messages_get_buff(key, url_s);
+ if (str == NULL) {
+ res = NSERROR_NOMEM;
+ } else {
+ *out_str = str;
}
free(url_s);
@@ -939,59 +952,134 @@ fetch_about_query_auth_handler_aborted:
/**
- * generate the description of the privacy query
+ * Handler to generate about scheme privacy query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
*/
-static nserror get_privacy_description(struct nsurl *url, char **out_str)
+static bool fetch_about_query_privacy_handler(struct fetch_about_context *ctx)
{
nserror res;
char *url_s;
size_t url_l;
- char *str = NULL;
- const char *key = "PrivacyDescription";
+ const char *reason = "";
+ const char *title;
+ struct nsurl *siteurl = NULL;
+ char *description = NULL;
+ const struct fetch_multipart_data *curmd; /* mutipart data iterator */
- /* get the host in question */
- res = nsurl_get(url, NSURL_HOST, &url_s, &url_l);
+ /* 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_ssl_handler_aborted;
+ }
+
+ title = messages_get("PrivacyTitle");
+ 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 =\"privacy\">\n"
+ "<h1>%s</h1>\n",
+ title, title);
if (res != NSERROR_OK) {
- return res;
+ goto fetch_about_query_ssl_handler_aborted;
}
- /* obtain the description with the url substituted */
- str = messages_get_buff(key, url_s);
- if ((str != NULL) && (strcmp(key, str) == 0)) {
- /* the returned string was simply the key */
- free(str);
- str = NULL;
+ res = ssenddataf(ctx,
+ "<form method=\"post\""
+ " enctype=\"multipart/form-data\">");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
}
- if (str == NULL) {
- /* failed to get suitable translated message text so
- * fall back to basic english.
- */
- int slen;
- slen = snprintf(str, 0, privacy_description_fallback, url_s) + 1;
- str = malloc(slen);
- if (str != NULL) {
- snprintf(str, slen, privacy_description_fallback, url_s);
+
+ res = get_query_description(siteurl,
+ "PrivacyDescription",
+ &description);
+ if (res == NSERROR_OK) {
+ res = ssenddataf(ctx, "<div><p>%s</p></div>",
description);
+ free(description);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
}
}
+ res = ssenddataf(ctx, "<div><p>%s</p></div>",
reason);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
- if (str == NULL) {
- res = NSERROR_NOMEM;
- } else {
- *out_str = str;
+ res = ssenddataf(ctx,
+ "<div id=\"buttons\">"
+ "<input type=\"submit\" id=\"back\"
name=\"back\" "
+ "value=\"%s\" class=\"default-action\">"
+ "<input type=\"submit\" id=\"proceed\"
name=\"proceed\" "
+ "value=\"%s\">"
+ "</div>",
+ messages_get("Backtosafety"),
+ messages_get("Proceed"));
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_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_ssl_handler_aborted;
+ }
- return res;
+ res = ssenddataf(ctx, "</form></body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_ssl_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ nsurl_unref(siteurl);
+
+ return true;
+
+fetch_about_query_ssl_handler_aborted:
+ nsurl_unref(siteurl);
+
+ return false;
}
/**
- * Handler to generate about scheme privacy query page
+ * 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_privacy_handler(struct fetch_about_context *ctx)
+static bool fetch_about_query_timeout_handler(struct fetch_about_context *ctx)
{
nserror res;
char *url_s;
@@ -1025,54 +1113,56 @@ static bool fetch_about_query_privacy_handler(struct
fetch_about_context *ctx)
/* content type */
if (fetch_about_send_header(ctx, "Content-Type: text/html; charset=utf-8")) {
- goto fetch_about_query_ssl_handler_aborted;
+ goto fetch_about_query_timeout_handler_aborted;
}
- title = messages_get("PrivacyTitle");
+ 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 =\"privacy\">\n"
+ "<body id =\"timeout\">\n"
"<h1>%s</h1>\n",
title, title);
if (res != NSERROR_OK) {
- goto fetch_about_query_ssl_handler_aborted;
+ 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_ssl_handler_aborted;
+ goto fetch_about_query_timeout_handler_aborted;
}
- res = get_privacy_description(siteurl, &description);
+ res = get_query_description(siteurl,
+ "TimeoutDescription",
+ &description);
if (res == NSERROR_OK) {
res = ssenddataf(ctx, "<div><p>%s</p></div>",
description);
free(description);
if (res != NSERROR_OK) {
- goto fetch_about_query_ssl_handler_aborted;
+ goto fetch_about_query_timeout_handler_aborted;
}
}
res = ssenddataf(ctx, "<div><p>%s</p></div>",
reason);
if (res != NSERROR_OK) {
- goto fetch_about_query_ssl_handler_aborted;
+ 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=\"proceed\"
name=\"proceed\" "
+ "<input type=\"submit\" id=\"retry\"
name=\"retry\" "
"value=\"%s\">"
"</div>",
- messages_get("Backtosafety"),
- messages_get("Proceed"));
+ messages_get("Backtoprevious"),
+ messages_get("TryAgain"));
if (res != NSERROR_OK) {
- goto fetch_about_query_ssl_handler_aborted;
+ goto fetch_about_query_timeout_handler_aborted;
}
res = nsurl_get(siteurl, NSURL_COMPLETE, &url_s, &url_l);
@@ -1084,12 +1174,12 @@ static bool fetch_about_query_privacy_handler(struct
fetch_about_context *ctx)
url_s);
free(url_s);
if (res != NSERROR_OK) {
- goto fetch_about_query_ssl_handler_aborted;
+ goto fetch_about_query_timeout_handler_aborted;
}
res = ssenddataf(ctx, "</form></body>\n</html>\n");
if (res != NSERROR_OK) {
- goto fetch_about_query_ssl_handler_aborted;
+ goto fetch_about_query_timeout_handler_aborted;
}
fetch_about_send_finished(ctx);
@@ -1098,7 +1188,130 @@ static bool fetch_about_query_privacy_handler(struct
fetch_about_context *ctx)
return true;
-fetch_about_query_ssl_handler_aborted:
+fetch_about_query_timeout_handler_aborted:
+ nsurl_unref(siteurl);
+
+ return false;
+}
+
+
+/**
+ * Handler to generate about scheme fetch error query page
+ *
+ * \param ctx The fetcher context.
+ * \return true if handled false if aborted.
+ */
+static bool
+fetch_about_query_fetcherror_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_fetcherror_handler_aborted;
+ }
+
+ title = messages_get("FetchErrorTitle");
+ 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 =\"fetcherror\">\n"
+ "<h1>%s</h1>\n",
+ title, title);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = ssenddataf(ctx,
+ "<form method=\"post\""
+ " enctype=\"multipart/form-data\">");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ res = get_query_description(siteurl,
+ "FetchErrorDescription",
+ &description);
+ if (res == NSERROR_OK) {
+ res = ssenddataf(ctx, "<div><p>%s</p></div>",
description);
+ free(description);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+ }
+ res = ssenddataf(ctx, "<div><p>%s</p></div>",
reason);
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_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_fetcherror_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_fetcherror_handler_aborted;
+ }
+
+ res = ssenddataf(ctx, "</form></body>\n</html>\n");
+ if (res != NSERROR_OK) {
+ goto fetch_about_query_fetcherror_handler_aborted;
+ }
+
+ fetch_about_send_finished(ctx);
+
+ nsurl_unref(siteurl);
+
+ return true;
+
+fetch_about_query_fetcherror_handler_aborted:
nsurl_unref(siteurl);
return false;
@@ -1211,6 +1424,20 @@ 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
+ },
+ {
+ "query/fetcherror",
+ SLEN("query/fetcherror"),
+ NULL,
+ fetch_about_query_fetcherror_handler,
+ true
}
};
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index a6b77b0..807393e 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -1182,6 +1182,85 @@ 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 non specific errors during a fetch
+ */
+static nserror
+browser_window__handle_fetcherror(struct browser_window *bw,
+ const char *reason,
+ nsurl *url)
+{
+ struct browser_fetch_parameters params;
+ nserror err;
+
+ memset(¶ms, 0, sizeof(params));
+
+ params.url = nsurl_ref(corestring_nsurl_about_query_fetcherror);
+ 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;
+ }
+
+ err = fetch_multipart_data_new_kv(¶ms.post_multipart,
+ "reason",
+ reason);
+ 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
*/
static nserror
@@ -1191,36 +1270,14 @@ browser_window__handle_error(struct browser_window *bw,
{
const char *message = event->data.errordata.errormsg;
nserror code = event->data.errordata.errorcode;
- bool do_warning = true;
nserror res;
nsurl *url = hlcache_handle_get_url(c);
/* Unexpected OK? */
assert(code != NSERROR_OK);
- switch (code) {
- case NSERROR_BAD_AUTH:
- do_warning = false;
- break;
- case NSERROR_BAD_CERTS:
- do_warning = false;
- break;
- case NSERROR_BAD_REDIRECT:
- /* The message is already filled out */
- break;
- default:
- if (message == NULL) {
- message = messages_get_errorcode(code);
- }
- break;
- }
-
- if (do_warning) {
- browser_window_set_status(bw, message);
- /* Only warn the user about errors in top-level windows */
- if (bw->browser_window_type == BROWSER_WINDOW_NORMAL) {
- guit->misc->warning(message, NULL);
- }
+ if (message == NULL) {
+ message = messages_get_errorcode(code);
}
if (c == bw->loading_content) {
@@ -1236,10 +1293,17 @@ browser_window__handle_error(struct browser_window *bw,
case NSERROR_BAD_AUTH:
res = browser_window__handle_login(bw, message, url);
break;
+
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:
+ res = browser_window__handle_fetcherror(bw, message, url);
break;
}
@@ -2368,6 +2432,10 @@ 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;
+ } else if (path == corestring_lwc_query_fetcherror) {
+ is_internal = true;
}
}
lwc_string_unref(path);
@@ -3338,12 +3406,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 +3423,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 +3498,7 @@ browser_window__navigate_internal_real(struct browser_window *bw,
return res;
}
+
/**
* Internal navigation handler for the authentication query handler
*
@@ -3431,8 +3506,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 +3522,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 +3572,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 +3583,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 +3595,100 @@ 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);
+}
+
+
+/**
+ * Internal navigation handler for the fetch error 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_fetcherror(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 +3702,26 @@ 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);
+ }
+ if (path == corestring_lwc_query_fetcherror) {
+ lwc_string_unref(path);
+ return navigate_internal_query_fetcherror(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);
}
diff --git a/resources/FatMessages b/resources/FatMessages
index d1ecd9d..5ebf607 100644
--- a/resources/FatMessages
+++ b/resources/FatMessages
@@ -25,7 +25,7 @@
#
# The split-messages tool requires keys for all languages to be
# grouped together but language order is not important. If a key for a
-# specific language is ommited the default language value will be used
+# specific language is omitted the default language value will be used
# instead (currently en)
#
# If you find something tagged 'all', but it is only relevant to a specific
@@ -1087,6 +1087,22 @@ 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
+
+
+# Fetch error interface
+# =======================
+#
+en.all.FetchErrorTitle:Error occurred fetching page
+en.all.FetchErrorDescription:An error occurred when connecting to %s
+
+
# SSL certificate viewer
# ======================
#
diff --git a/resources/internal.css b/resources/internal.css
index e43d183..ded56ee 100644
--- a/resources/internal.css
+++ b/resources/internal.css
@@ -343,3 +343,79 @@ 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;
+}
+
+/*
+ * fetch error query styling
+ */
+
+body#fetcherror {
+ max-width: 45em;
+}
+
+body#fetcherror 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#fetcherror 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#fetcherror form div + div {
+ margin-top: 1em;
+}
+
+body#fetcherror div#buttons {
+ text-align: right;
+ margin-right: 1em;
+}
+
+body#fetcherror div#buttons input#back {
+ margin-right: 1em;
+}
diff --git a/test/messages.c b/test/messages.c
index ae82d1e..3ec770a 100644
--- a/test/messages.c
+++ b/test/messages.c
@@ -118,8 +118,7 @@ START_TEST(message_get_buff_test)
ck_assert_int_eq(res, NSERROR_OK);
buf = messages_get_buff("DefinitelyNotAKey");
- ck_assert_str_eq(buf, "DefinitelyNotAKey");
- free(buf);
+ ck_assert(buf == NULL);
buf = messages_get_buff("NoMemory");
ck_assert_str_eq(buf, "NetSurf is running out of memory. Please free some memory
and try again.");
diff --git a/utils/corestringlist.h b/utils/corestringlist.h
index f0d39c6..b109545 100644
--- a/utils/corestringlist.h
+++ b/utils/corestringlist.h
@@ -148,6 +148,8 @@ 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");
+CORESTRING_LWC_VALUE(query_fetcherror, "query/fetcherror");
/* mime types */
CORESTRING_LWC_VALUE(multipart_form_data, "multipart/form-data");
@@ -360,6 +362,8 @@ 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");
+CORESTRING_NSURL(about_query_fetcherror, "about:query/fetcherror");
#undef CORESTRING_LWC_STRING
#undef CORESTRING_DOM_STRING
diff --git a/utils/hashtable.c b/utils/hashtable.c
index 4935d6b..aa162cb 100644
--- a/utils/hashtable.c
+++ b/utils/hashtable.c
@@ -347,10 +347,12 @@ const char *hash_get(struct hash_table *ht, const char *key)
h = hash_string_fnv(key, &key_length);
c = h % ht->nchains;
- for (e = ht->chain[c]; e; e = e->next)
+ for (e = ht->chain[c]; e; e = e->next) {
if ((key_length == e->key_length) &&
- (memcmp(key, e->pairing, key_length) == 0))
+ (memcmp(key, e->pairing, key_length) == 0)) {
return e->pairing + key_length + 1;
+ }
+ }
return NULL;
}
diff --git a/utils/messages.c b/utils/messages.c
index 197d45e..5525e18 100644
--- a/utils/messages.c
+++ b/utils/messages.c
@@ -42,11 +42,69 @@
/** Messages are stored in a fixed-size hash table. */
#define HASH_SIZE 101
-/** The hash table used to store the standard Messages file for the old API */
+/**
+ * The hash table used to store the standard Messages file for the old API
+ */
static struct hash_table *messages_hash = NULL;
/**
+ * Create a message context
+ *
+ * generate a message context populated with english fallbacks for
+ * some formatted messages.
+ */
+static struct hash_table *messages_create_ctx(int hash_size)
+{
+ struct hash_table *nctx;
+ const struct {
+ const char *key;
+ const char *value;
+ } fallback[] = {
+ { "LoginDescription",
+ "The site %s is requesting your username and password. "
+ "The realm is \"%s\""},
+ { "PrivacyDescription",
+ "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)"},
+ { "TimeoutDescription",
+ "A connection to %s could not be established. The site may "
+ "be temporarily unavailable or too busy to respond."},
+ { "FetchErrorDescription",
+ "An error occurred when connecting to %s"},
+ { NULL, NULL}
+ };
+ nctx = hash_create(hash_size);
+
+ if (nctx != NULL) {
+ int floop;
+ for (floop = 0; fallback[floop].key != NULL; floop++) {
+ hash_add(nctx,
+ fallback[floop].key,
+ fallback[floop].value);
+ }
+ }
+
+ return nctx;
+}
+
+/**
+ * Free memory used by a messages hash.
+ * The context will not be valid after this function returns.
+ *
+ * \param ctx context of messages file to free
+ */
+static void messages_destroy_ctx(struct hash_table *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ hash_destroy(ctx);
+}
+
+
+/**
* Read keys and values from messages file.
*
* \param path pathname of messages file
@@ -66,7 +124,7 @@ static nserror messages_load_ctx(const char *path, struct hash_table
**ctx)
return hash_add_file(*ctx, path);
}
- nctx = hash_create(HASH_SIZE);
+ nctx = messages_create_ctx(HASH_SIZE);
if (nctx == NULL) {
NSLOG(netsurf, INFO,
"Unable to create hash table for messages file %s",
@@ -115,21 +173,6 @@ messages_get_ctx(const char *key, struct hash_table *ctx)
}
-/**
- * Free memory used by a messages hash.
- * The context will not be valid after this function returns.
- *
- * \param ctx context of messages file to free
- */
-static void messages_destroy_ctx(struct hash_table *ctx)
-{
- if (ctx == NULL)
- return;
-
- hash_destroy(ctx);
-}
-
-
/* exported interface documented in messages.h */
nserror messages_add_from_file(const char *path)
{
@@ -148,7 +191,7 @@ nserror messages_add_from_inline(const uint8_t *data, size_t size)
{
/* ensure the hash table is initialised */
if (messages_hash == NULL) {
- messages_hash = hash_create(HASH_SIZE);
+ messages_hash = messages_create_ctx(HASH_SIZE);
}
if (messages_hash == NULL) {
NSLOG(netsurf, INFO, "Unable to create hash table");
@@ -157,6 +200,7 @@ nserror messages_add_from_inline(const uint8_t *data, size_t size)
return hash_add_inline(messages_hash, data, size);
}
+
/* exported interface documented in messages.h */
char *messages_get_buff(const char *key, ...)
{
@@ -165,7 +209,17 @@ char *messages_get_buff(const char *key, ...)
int buff_len = 0;
va_list ap;
- msg_fmt = messages_get_ctx(key, messages_hash);
+ assert(key != NULL);
+
+ if (messages_hash == NULL) {
+ return NULL;
+ }
+
+ msg_fmt = hash_get(messages_hash, key);
+
+ if (msg_fmt == NULL) {
+ return NULL;
+ }
va_start(ap, key);
buff_len = vsnprintf(buff, buff_len, msg_fmt, ap);
diff --git a/utils/messages.h b/utils/messages.h
index 635d6e8..5da35e4 100644
--- a/utils/messages.h
+++ b/utils/messages.h
@@ -16,7 +16,8 @@
* along with this program. If not, see <
http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Localised message support (interface).
*
* The messages module loads a file of keys and associated strings, and
@@ -30,8 +31,8 @@
* file table. Use the _ctx versions of the functions to do this.
*/
-#ifndef _NETSURF_UTILS_MESSAGES_H_
-#define _NETSURF_UTILS_MESSAGES_H_
+#ifndef NETSURF_UTILS_MESSAGES_H_
+#define NETSURF_UTILS_MESSAGES_H_
#include <stdint.h>
@@ -90,13 +91,12 @@ const char *messages_get_sslcode(ssl_cert_err code);
/**
* Formatted message from a key in the global message hash.
*
- * \param key key of message
+ * \param key key of message
* \param ... message parameters
- * \return buffer containing formatted message text or NULL if memory
- * is unavailable. The caller owns the returned buffer and is
- * responsible for freeing it.
+ * \return buffer containing formatted message text or NULL if key is
+ * unavailable or memory allocation failed. The caller owns the
+ * returned buffer and is responsible for freeing it.
*/
-
char *messages_get_buff(const char *key, ...);
/**
--
NetSurf Browser