summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2005-01-01 22:05:21 +0000
committerJames Bursa <james@netsurf-browser.org>2005-01-01 22:05:21 +0000
commit7a71363d767f88f54e80e4bbe07eaef54e6fbbee (patch)
treec4a04c6cef960ad4a7cf1d510bb040c622074c18
parentff8dc1f9d60c67f60c118175e385153fbdb06fa3 (diff)
downloadnetsurf-7a71363d767f88f54e80e4bbe07eaef54e6fbbee.tar.gz
netsurf-7a71363d767f88f54e80e4bbe07eaef54e6fbbee.tar.bz2
[project @ 2005-01-01 22:05:20 by bursa]
xcalloc/xrealloc/xstrdup-purge week, part 5. Improve and simplify encoding detection. svn path=/import/netsurf/; revision=1416
-rw-r--r--!NetSurf/Resources/de/Messages5
-rw-r--r--!NetSurf/Resources/en/Messages5
-rw-r--r--!NetSurf/Resources/fr/Messages5
-rw-r--r--render/box.c24
-rw-r--r--render/html.c353
-rw-r--r--render/html.h30
-rw-r--r--riscos/menus.c32
7 files changed, 308 insertions, 146 deletions
diff --git a/!NetSurf/Resources/de/Messages b/!NetSurf/Resources/de/Messages
index c26fd02f1..701b2cd82 100644
--- a/!NetSurf/Resources/de/Messages
+++ b/!NetSurf/Resources/de/Messages
@@ -259,6 +259,11 @@ ScrollH:Ziehen der Leiste scrollt horizontal
ScrollPRight:Anklicken scrollt eine Seite nach rechts
ScrollRight:Pfeil anklicken scrollt rechts
+Encoding0:from HTTP headers
+Encoding1:detected
+Encoding2:from <meta>
+EncodingUnk:Unknown
+
# Interactive help
HelpToolbar0:Schaltet zurück auf die zuvor dargestellte Seite.|MDer Inhalt wird dabei nicht aktualisiert.
HelpToolbar1:Schaltet vorwärts auf die nächste Seite.|MDer Inhalt wird dabei nicht aktualisiert.
diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages
index 6ff639879..d375b633e 100644
--- a/!NetSurf/Resources/en/Messages
+++ b/!NetSurf/Resources/en/Messages
@@ -259,6 +259,11 @@ ScrollH:Drag the bar to scroll horizontally
ScrollPRight:Click to scroll right one page
ScrollRight:Click the arrow to scroll right
+Encoding0:from HTTP headers
+Encoding1:detected
+Encoding2:from <meta>
+EncodingUnk:Unknown
+
# Interactive help
HelpToolbar0:\Tback button.|M\Straverse back one page in the history tree.|MDoes not resubmit form information.
HelpToolbar1:\Tforward button.|M\Straverse forward one page in the history tree.|MDoes not resubmit form information.
diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages
index e2a9af949..16d20343f 100644
--- a/!NetSurf/Resources/fr/Messages
+++ b/!NetSurf/Resources/fr/Messages
@@ -259,6 +259,11 @@ ScrollH:Drag the bar to scroll horizontally
ScrollPRight:Click to scroll right one page
ScrollRight:Click the arrow to scroll right
+Encoding0:from HTTP headers
+Encoding1:detected
+Encoding2:from <meta>
+EncodingUnk:Unknown
+
# Interactive help
HelpToolbar0:\Tle bouton de retour.|M\Srevenir d'une page en arrière dans l'historique.|MNe renvoie pas l'information de formulaire.
HelpToolbar1:\Tle bouton d'avance.|M\Savancer d'une page dans l'historique.|MNe renvoie pas l'information de formulaire.
diff --git a/render/box.c b/render/box.c
index 131060dde..bf055eac4 100644
--- a/render/box.c
+++ b/render/box.c
@@ -731,8 +731,9 @@ end:
if (!url)
return false;
/* start fetch */
- html_fetch_object(content, url, box, image_types,
- content->available_width, 1000, true);
+ if (!html_fetch_object(content, url, box, image_types,
+ content->available_width, 1000, true))
+ return false;
}
return true;
@@ -1120,8 +1121,9 @@ struct box_result box_image(xmlNode *n, struct box_status *status,
return (struct box_result) {box, false, false};
/* start fetch */
- html_fetch_object(status->content, url, box, image_types,
- status->content->available_width, 1000, false);
+ if (!html_fetch_object(status->content, url, box, image_types,
+ status->content->available_width, 1000, false))
+ return (struct box_result) {0, false, true};
return (struct box_result) {box, false, false};
}
@@ -1551,10 +1553,11 @@ struct box_result box_input(xmlNode *n, struct box_status *status,
*/
if (res == URL_FUNC_OK &&
strcasecmp(url, status->content->data.html.base_url) != 0)
- html_fetch_object(status->content, url, box,
+ if (!html_fetch_object(status->content, url, box,
image_types,
status->content->available_width,
- 1000, false);
+ 1000, false))
+ goto no_memory;
xmlFree(s);
}
@@ -2942,7 +2945,8 @@ bool plugin_decode(struct content* content, char* url, struct box* box,
* handle when we fetch it (if the type was not specified or is
* different to that given in the attributes).
*/
- html_fetch_object(content, url, box, 0, 1000, 1000, false);
+ if (!html_fetch_object(content, url, box, 0, 1000, 1000, false))
+ return false;
return true;
}
@@ -3152,8 +3156,10 @@ struct box_result box_frameset(xmlNode *n, struct box_status *status,
LOG(("frame, url '%s'", url));
- html_fetch_object(status->content, url, object_box, 0,
- object_width, object_height, false);
+ if (!html_fetch_object(status->content, url,
+ object_box, 0,
+ object_width, object_height, false))
+ return (struct box_result) {0, false, true};
xmlFree(s);
c = c->next;
diff --git a/render/html.c b/render/html.c
index 9b0bbf2ee..33b2a96c2 100644
--- a/render/html.c
+++ b/render/html.c
@@ -34,10 +34,12 @@
#define CHUNK 4096
+static bool html_set_parser_encoding(struct content *c, const char *encoding);
+static const char *html_detect_encoding(const char *data, unsigned int size);
static void html_convert_css_callback(content_msg msg, struct content *css,
void *p1, void *p2, union content_msg_data data);
-static void html_head(struct content *c, xmlNode *head);
-static void html_find_stylesheets(struct content *c, xmlNode *head);
+static bool html_head(struct content *c, xmlNode *head);
+static bool html_find_stylesheets(struct content *c, xmlNode *head);
static void html_object_callback(content_msg msg, struct content *object,
void *p1, void *p2, union content_msg_data data);
static void html_object_done(struct box *box, struct content *object,
@@ -58,44 +60,11 @@ bool html_create(struct content *c, const char *params[])
unsigned int i;
struct content_html_data *html = &c->data.html;
union content_msg_data msg_data;
- xmlCharEncoding encXML = XML_CHAR_ENCODING_NONE;
- const char *encStr = NULL;
- html->encoding = NULL;
+ html->parser = 0;
+ html->encoding_handler = 0;
+ html->encoding = 0;
html->getenc = true;
-
- for (i = 0; params[i]; i += 2) {
- if (strcasecmp(params[i], "charset") == 0) {
- encXML = xmlParseCharEncoding(params[i + 1]);
- if (encXML != XML_CHAR_ENCODING_ERROR
- && encXML != XML_CHAR_ENCODING_NONE) {
- /* encoding specified - trust the server... */
- html->encoding = xstrdup(xmlGetCharEncodingName(encXML));
- html->getenc = false;
- } else {
- encStr = xstrdup(params[i + 1]);
- }
- break;
- }
- }
-
- html->parser = htmlCreatePushParserCtxt(0, 0, "", 0, 0, encXML);
- if (encStr != NULL) {
- xmlCharEncodingHandlerPtr handler;
- if ((handler = xmlFindCharEncodingHandler(encStr)) != NULL) {
- if (xmlSwitchToEncoding(html->parser, handler) == 0) {
- html->encoding = encStr;
- html->getenc = false;
- } else {
- LOG(("xmlSwitchToEncoding failed for <%s>\n", encStr));
- free((void *)encStr);
- }
- } else {
- LOG(("xmlFindCharEncodingHandler() failed for <%s>\n", encStr));
- free((void *)encStr);
- }
- }
- html->base_url = xstrdup(c->url);
html->base_url = strdup(c->url);
html->layout = 0;
html->background_colour = TRANSPARENT;
@@ -106,26 +75,43 @@ bool html_create(struct content *c, const char *params[])
html->object_count = 0;
html->object = 0;
html->imagemaps = 0;
- html->string_pool = pool_create(8000);
html->box_pool = pool_create(sizeof (struct box) * 100);
+ html->string_pool = pool_create(8000);
html->bw = 0;
- if (!html->parser || !html->base_url || !html->string_pool ||
- !html->box_pool) {
- htmlFreeParserCtxt(html->parser);
- free(html->base_url);
- if (html->string_pool)
- pool_destroy(html->string_pool);
- if (html->box_pool)
- pool_destroy(html->box_pool);
+ if (!html->base_url || !html->string_pool || !html->box_pool)
+ goto no_memory;
- msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- warn_user("NoMemory", 0);
- return false;
+ for (i = 0; params[i]; i += 2) {
+ if (strcasecmp(params[i], "charset") == 0) {
+ html->encoding = strdup(params[i + 1]);
+ if (!html->encoding)
+ goto no_memory;
+ html->encoding_source = ENCODING_SOURCE_HEADER;
+ html->getenc = false;
+ break;
+ }
+ }
+
+ html->parser = htmlCreatePushParserCtxt(0, 0, "", 0, 0,
+ XML_CHAR_ENCODING_NONE);
+ if (!html->parser)
+ goto no_memory;
+
+ if (html->encoding) {
+ /* an encoding was specified in the Content-Type header */
+ if (!html_set_parser_encoding(c, html->encoding))
+ return false;
}
return true;
+
+no_memory:
+ /* memory allocated will be freed in html_destroy() */
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return false;
}
@@ -139,16 +125,22 @@ bool html_process_data(struct content *c, char *data, unsigned int size)
{
unsigned long x;
- /* First time through, check if we need to detect the encoding
- * if so, detect it and reset the parser instance with it.
- * Do this detection only once.
- */
if (c->data.html.getenc) {
- xmlCharEncoding encoding = xmlDetectCharEncoding(data, size);
- if (encoding != XML_CHAR_ENCODING_ERROR &&
- encoding != XML_CHAR_ENCODING_NONE) {
- xmlSwitchEncoding(c->data.html.parser, encoding);
- c->data.html.encoding = xstrdup(xmlGetCharEncodingName(encoding));
+ /* No encoding was specified in the Content-Type header.
+ * Attempt to detect if the encoding is not 8-bit. If the
+ * encoding is 8-bit, leave the parser unchanged, so that it
+ * searches for a <meta http-equiv="content-type"
+ * content="text/html; charset=...">. */
+ const char *encoding;
+ encoding = html_detect_encoding(data, size);
+ if (encoding) {
+ if (!html_set_parser_encoding(c, encoding))
+ return false;
+ c->data.html.encoding = strdup(encoding);
+ if (!c->data.html.encoding)
+ return false;
+ c->data.html.encoding_source =
+ ENCODING_SOURCE_DETECTED;
}
c->data.html.getenc = false;
}
@@ -164,6 +156,80 @@ bool html_process_data(struct content *c, char *data, unsigned int size)
/**
+ * Set the HTML parser character encoding.
+ *
+ * \param c content of type CONTENT_HTML
+ * \param encoding name of encoding
+ * \return true on success, false on error and error reported
+ */
+
+bool html_set_parser_encoding(struct content *c, const char *encoding)
+{
+ struct content_html_data *html = &c->data.html;
+ xmlError *error;
+ char error_message[500];
+ union content_msg_data msg_data;
+
+ html->encoding_handler = xmlFindCharEncodingHandler(encoding);
+ if (!html->encoding_handler) {
+ /* either out of memory, or no handler available */
+ /* assume no handler available, which is not a fatal error */
+ LOG(("no encoding handler for \"%s\"", encoding));
+ /* \todo warn user and ask them to install iconv? */
+ return true;
+ }
+
+ xmlCtxtResetLastError(html->parser);
+ if (xmlSwitchToEncoding(html->parser, html->encoding_handler)) {
+ error = xmlCtxtGetLastError(html->parser);
+ snprintf(error_message, sizeof error_message,
+ "%s xmlSwitchToEncoding(): %s",
+ messages_get("MiscError"),
+ error ? error->message : "failed");
+ msg_data.error = error_message;
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Attempt to detect the encoding of some HTML data.
+ *
+ * \param data HTML source data
+ * \param size length of data
+ * \return a constant string giving the encoding, or 0 if the encoding
+ * appears to be some 8-bit encoding
+ */
+
+const char *html_detect_encoding(const char *data, unsigned int size)
+{
+ /* this detection assumes that the first two characters are <= 0xff */
+ if (size < 4)
+ return 0;
+ if (data[0] == 0xfe && data[1] == 0xff) /* BOM fe ff */
+ return "UTF-16BE";
+ else if (data[0] == 0xfe && data[1] == 0xff) /* BOM ff fe */
+ return "UTF-16LE";
+ else if (data[0] == 0x00 && data[1] != 0x00 &&
+ data[2] == 0x00 && data[3] != 0x00) /* 00 xx 00 xx */
+ return "UTF-16BE";
+ else if (data[0] != 0x00 && data[1] == 0x00 &&
+ data[2] != 0x00 && data[3] == 0x00) /* xx 00 xx 00 */
+ return "UTF-16BE";
+ else if (data[0] == 0x00 && data[1] == 0x00 &&
+ data[2] == 0x00 && data[3] != 0x00) /* 00 00 00 xx */
+ return "ISO-10646-UCS-4";
+ else if (data[0] != 0x00 && data[1] == 0x00 &&
+ data[2] == 0x00 && data[3] == 0x00) /* xx 00 00 00 */
+ return "ISO-10646-UCS-4";
+ return 0;
+}
+
+
+/**
* Convert a CONTENT_HTML for display.
*
* The following steps are carried out in order:
@@ -196,11 +262,19 @@ bool html_convert(struct content *c, int width, int height)
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
- /* Last change to pick the Content-Type charset information if the
- * server didn't send it (or we're reading the HTML from disk)
- */
- if (c->data.html.encoding == NULL && document->encoding != NULL)
- c->data.html.encoding = xstrdup(document->encoding);
+
+ if (!c->data.html.encoding && document->encoding) {
+ /* The encoding was not in headers or detected, and the parser
+ * found a <meta http-equiv="content-type"
+ * content="text/html; charset=...">. */
+ c->data.html.encoding = strdup(document->encoding);
+ if (!c->data.html.encoding) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+ c->data.html.encoding_source = ENCODING_SOURCE_META;
+ }
/* locate html and head elements */
for (html = document->children;
@@ -223,11 +297,20 @@ bool html_convert(struct content *c, int width, int height)
LOG(("head element not found"));
}
- if (head != 0)
- html_head(c, head);
+ if (head) {
+ if (!html_head(c, head)) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+ }
/* get stylesheets */
- html_find_stylesheets(c, head);
+ if (!html_find_stylesheets(c, head)) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
/* convert xml tree to box tree */
LOG(("XML to box"));
@@ -279,11 +362,12 @@ bool html_convert(struct content *c, int width, int height)
*
* \param c content structure
* \param head xml node of head element
+ * \return true on success, false on memory exhaustion
*
* The title and base href are extracted if present.
*/
-void html_head(struct content *c, xmlNode *head)
+bool html_head(struct content *c, xmlNode *head)
{
xmlNode *node;
@@ -295,7 +379,11 @@ void html_head(struct content *c, xmlNode *head)
if (!c->title && strcmp(node->name, "title") == 0) {
xmlChar *title = xmlNodeGetContent(node);
+ if (!title)
+ return false;
c->title = squash_whitespace(title);
+ if (!c->title)
+ return false;
xmlFree(title);
} else if (strcmp(node->name, "base") == 0) {
@@ -312,6 +400,7 @@ void html_head(struct content *c, xmlNode *head)
}
}
}
+ return true;
}
@@ -320,9 +409,10 @@ void html_head(struct content *c, xmlNode *head)
*
* \param c content structure
* \param head xml node of head element, or 0 if none
+ * \return true on success, false on memory exhaustion
*/
-void html_find_stylesheets(struct content *c, xmlNode *head)
+bool html_find_stylesheets(struct content *c, xmlNode *head)
{
xmlNode *node, *node2;
char *rel, *type, *media, *href, *data, *url;
@@ -330,11 +420,15 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
unsigned int last_active = 0;
union content_msg_data msg_data;
url_func_result res;
+ struct content **stylesheet_content;
/* stylesheet 0 is the base style sheet,
* stylesheet 1 is the adblocking stylesheet,
* stylesheet 2 is any <style> elements */
- c->data.html.stylesheet_content = xcalloc(STYLESHEET_START, sizeof(*c->data.html.stylesheet_content));
+ c->data.html.stylesheet_content = malloc(STYLESHEET_START *
+ sizeof *c->data.html.stylesheet_content);
+ if (!c->data.html.stylesheet_content)
+ return false;
c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = 0;
c->data.html.stylesheet_content[STYLESHEET_STYLE] = 0;
c->data.html.stylesheet_count = STYLESHEET_START;
@@ -346,27 +440,29 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
html_convert_css_callback, c,
(void *) STYLESHEET_BASE, c->width, c->height,
true, 0, 0, false);
- assert(c->data.html.stylesheet_content[STYLESHEET_BASE]);
+ 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, c,
(void *) STYLESHEET_BASE, 0, 0, false);
if (option_block_ads) {
- c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] = fetchcache(
- adblock_stylesheet_url,
- html_convert_css_callback, c,
- (void *) STYLESHEET_ADBLOCK, c->width,
- c->height, true, 0, 0, false);
- if (c->data.html.stylesheet_content[STYLESHEET_ADBLOCK]) {
- c->active++;
- fetchcache_go(c->data.html.stylesheet_content[STYLESHEET_ADBLOCK],
+ c->data.html.stylesheet_content[STYLESHEET_ADBLOCK] =
+ fetchcache(adblock_stylesheet_url,
+ html_convert_css_callback, c,
+ (void *) STYLESHEET_ADBLOCK, c->width,
+ c->height, true, 0, 0, false);
+ if (!c->data.html.stylesheet_content[STYLESHEET_ADBLOCK])
+ return false;
+ c->active++;
+ fetchcache_go(c->data.html.
+ stylesheet_content[STYLESHEET_ADBLOCK],
0, html_convert_css_callback, c,
(void *) STYLESHEET_ADBLOCK, 0, 0, false);
- }
}
- for (node = head == 0 ? 0 : head->children; node != 0; node = node->next) {
+ for (node = head == 0 ? 0 : head->children; node; node = node->next) {
if (node->type != XML_ELEMENT_NODE)
continue;
@@ -414,20 +510,25 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
LOG(("linked stylesheet %i '%s'", i, url));
/* start fetch */
- c->data.html.stylesheet_content = xrealloc(c->data.html.stylesheet_content,
- (i + 1) * sizeof(*c->data.html.stylesheet_content));
+ stylesheet_content = realloc(
+ c->data.html.stylesheet_content,
+ (i + 1) * sizeof
+ *c->data.html.stylesheet_content);
+ if (!stylesheet_content)
+ return false;
+ c->data.html.stylesheet_content = stylesheet_content;
c->data.html.stylesheet_content[i] = fetchcache(url,
html_convert_css_callback,
c, (void *) i, c->width, c->height,
true, 0, 0, false);
- if (c->data.html.stylesheet_content[i]) {
- c->active++;
- fetchcache_go(c->data.html.stylesheet_content[i],
- c->url,
- html_convert_css_callback,
- c, (void *) i,
- 0, 0, false);
- }
+ if (!c->data.html.stylesheet_content[i])
+ return false;
+ c->active++;
+ fetchcache_go(c->data.html.stylesheet_content[i],
+ c->url,
+ html_convert_css_callback,
+ c, (void *) i,
+ 0, 0, false);
free(url);
i++;
@@ -459,12 +560,14 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
content_create(c->data.html.
base_url);
if (!c->data.html.stylesheet_content[STYLESHEET_STYLE])
- return;
+ return false;
if (!content_set_type(c->data.html.
stylesheet_content[STYLESHEET_STYLE],
CONTENT_CSS, "text/css",
params))
- return;
+ /** \todo not necessarily caused by
+ * memory exhaustion */
+ return false;
}
/* can't just use xmlNodeGetContent(node), because that won't give
@@ -475,7 +578,9 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
stylesheet_content[STYLESHEET_STYLE],
data, strlen(data))) {
xmlFree(data);
- return;
+ /** \todo not necessarily caused by
+ * memory exhaustion */
+ return false;
}
xmlFree(data);
}
@@ -512,6 +617,8 @@ void html_find_stylesheets(struct content *c, xmlNode *head)
/* content_set_status(c, "Warning: some stylesheets failed to load"); */
/* content_broadcast(c, CONTENT_MSG_STATUS, msg_data); */
/* } */
+
+ return true;
}
@@ -604,34 +711,41 @@ void html_convert_css_callback(content_msg msg, struct content *css,
* \param available_width estimate of width of object
* \param available_height estimate of height of object
* \param background this is a background image
+ * \return true on success, false on memory exhaustion
*/
-void html_fetch_object(struct content *c, char *url, struct box *box,
+bool html_fetch_object(struct content *c, char *url, struct box *box,
const content_type *permitted_types,
int available_width, int available_height,
bool background)
{
unsigned int i = c->data.html.object_count;
+ struct content_html_object *object;
/* add to object list */
- c->data.html.object = xrealloc(c->data.html.object,
- (i + 1) * sizeof(*c->data.html.object));
+ object = realloc(c->data.html.object,
+ (i + 1) * sizeof *c->data.html.object);
+ if (!object)
+ return false;
+ c->data.html.object = object;
c->data.html.object[i].url = url;
c->data.html.object[i].box = box;
c->data.html.object[i].permitted_types = permitted_types;
c->data.html.object[i].background = background;
+ c->data.html.object_count++;
/* start fetch */
c->data.html.object[i].content = fetchcache(url, html_object_callback,
c, (void *) i, available_width, available_height,
true, 0, 0, false);
- if (c->data.html.object[i].content) {
- c->active++;
- fetchcache_go(c->data.html.object[i].content, c->url,
- html_object_callback, c, (void *) i,
- 0, 0, false);
- }
- c->data.html.object_count++;
+ if (!c->data.html.object[i].content)
+ return false;
+ c->active++;
+ fetchcache_go(c->data.html.object[i].content, c->url,
+ html_object_callback, c, (void *) i,
+ 0, 0, false);
+
+ return true;
}
@@ -704,17 +818,26 @@ void html_object_callback(content_msg msg, struct content *object,
case CONTENT_MSG_REDIRECT:
c->active--;
free(c->data.html.object[i].url);
- c->data.html.object[i].url = xstrdup(data.redirect);
- c->data.html.object[i].content = fetchcache(
- data.redirect, html_object_callback,
- c, (void * ) i, 0, 0, true, 0, 0,
- false);
- if (c->data.html.object[i].content) {
- c->active++;
- fetchcache_go(c->data.html.object[i].content,
- c->url, html_object_callback,
- c, (void * ) i,
+ c->data.html.object[i].url = strdup(data.redirect);
+ if (!c->data.html.object[i].url) {
+ /** \todo report oom */
+ } else {
+ c->data.html.object[i].content = fetchcache(
+ data.redirect,
+ html_object_callback,
+ c, (void * ) i, 0, 0, true,
0, 0, false);
+ if (!c->data.html.object[i].content) {
+ /** \todo report oom */
+ } else {
+ c->active++;
+ fetchcache_go(c->data.html.object[i].
+ content,
+ c->url,
+ html_object_callback,
+ c, (void * ) i,
+ 0, 0, false);
+ }
}
break;
diff --git a/render/html.h b/render/html.h
index c91f89f1f..a5b9a0fe6 100644
--- a/render/html.h
+++ b/render/html.h
@@ -36,11 +36,27 @@ struct plotters;
extern char *default_stylesheet_url;
extern char *adblock_stylesheet_url;
+/** An object (<img>, <object>, etc.) in a CONTENT_HTML document. */
+struct content_html_object {
+ char *url; /**< URL of this object. */
+ struct content *content; /**< Content, or 0. */
+ struct box *box; /**< Node in box tree containing it. */
+ /** Pointer to array of permitted content_type, terminated by
+ * CONTENT_UNKNOWN, or 0 if any type is acceptable. */
+ const content_type *permitted_types;
+ bool background; /** Is this object a background image? */
+};
+
/** Data specific to CONTENT_HTML. */
struct content_html_data {
htmlParserCtxt *parser; /**< HTML parser context. */
+ /** HTML parser encoding handler. */
+ xmlCharEncodingHandler *encoding_handler;
- const char *encoding; /**< Encoding of source. */
+ char *encoding; /**< Encoding of source, 0 if unknown. */
+ enum { ENCODING_SOURCE_HEADER, ENCODING_SOURCE_DETECTED,
+ ENCODING_SOURCE_META } encoding_source;
+ /**< Source of encoding information. */
bool getenc; /**< Need to get the encoding from the document, as it
* wasn't specified in the Content-Type header. */
@@ -60,15 +76,7 @@ struct content_html_data {
/** Number of entries in object. */
unsigned int object_count;
/** Objects. Each may be 0. */
- struct {
- char *url; /**< URL of this object. */
- struct content *content; /**< Content, or 0. */
- struct box *box; /**< Node in box tree containing it. */
- /** Pointer to array of permitted content_type, terminated by
- * CONTENT_UNKNOWN, or 0 if any type is acceptable. */
- const content_type *permitted_types;
- bool background; /** Is this object a background image? */
- } *object;
+ struct content_html_object *object;
struct imagemap **imagemaps; /**< Hashtable of imagemaps */
@@ -88,7 +96,7 @@ bool html_process_data(struct content *c, char *data, unsigned int size);
bool html_convert(struct content *c, int width, int height);
void html_reformat(struct content *c, int width, int height);
void html_destroy(struct content *c);
-void html_fetch_object(struct content *c, char *url, struct box *box,
+bool html_fetch_object(struct content *c, char *url, struct box *box,
const content_type *permitted_types,
int available_width, int available_height,
bool background);
diff --git a/riscos/menus.c b/riscos/menus.c
index 9ae2b8d8a..4ca41b989 100644
--- a/riscos/menus.c
+++ b/riscos/menus.c
@@ -450,7 +450,7 @@ wimp_menu *toolbar_menu = (wimp_menu *)&toolbar;
/* Current toolbar
-*/
+*/
struct toolbar *current_toolbar;
static struct toolbar_icon *current_toolbar_icon;
@@ -525,7 +525,7 @@ void ro_gui_menus_init(void)
translate_menu(toolbar_menu);
translate_menu(toolbar_browser_menu);
translate_menu(toolbar_hotlist_menu);
-
+
translate_menu(proxyauth_menu);
translate_menu(image_quality_menu);
@@ -794,10 +794,10 @@ void ro_gui_menu_selection(wimp_selection *selection)
height - current_toolbar->height);
/* if ((height != current_toolbar->height) &&
(current_toolbar == hotlist_toolbar)) {
- xwimp_force_redraw(hotlist_window, 0, -16384, 16384, 16384);
+ xwimp_force_redraw(hotlist_window, 0, -16384, 16384, 16384);
}
*/ ro_gui_menu_prepare_theme();
-
+
break;
case 1: /* Toolbars-> */
switch (selection->items[1]) {
@@ -1309,7 +1309,7 @@ void ro_gui_menu_browser_warning(wimp_message_menu_warning *warning)
switch (warning->selection.items[1]) {
case -1: /* View-> */
ro_gui_menu_prepare_view();
- if (current_gui->toolbar)
+ if (current_gui->toolbar)
view_menu.entries[2].icon_flags &= ~wimp_ICON_SHADED;
else
view_menu.entries[2].icon_flags |= wimp_ICON_SHADED;
@@ -1321,7 +1321,7 @@ void ro_gui_menu_browser_warning(wimp_message_menu_warning *warning)
error = xwimp_create_sub_menu((wimp_menu *) dialog_zoom,
warning->pos.x, warning->pos.y);
break;
-
+
case 1: /* Images -> */
ro_gui_menu_prepare_images();
error = xwimp_create_sub_menu(browser_image_menu,
@@ -1663,9 +1663,9 @@ static void ro_gui_menu_prepare_theme(void) {
struct toolbar_icon *icon;
struct toolbar_icon *next;
wimp_menu *sub_menu;
-
+
if (!current_toolbar) return;
-
+
/* Set the icon states
*/
if (current_toolbar->display_buttons) {
@@ -1706,7 +1706,7 @@ static void ro_gui_menu_prepare_theme(void) {
toolbar_menu->entries[2].icon_flags |= wimp_ICON_SHADED;
toolbar_menu->entries[3].icon_flags |= wimp_ICON_SHADED;
}
-
+
/* Set the toolbars submenu state
*/
if (current_gui) {
@@ -1870,6 +1870,8 @@ void ro_gui_menu_prepare_pageinfo(void)
{
struct content *c = current_gui->bw->current_content;
char icon_buf[20] = "file_xxx";
+ char enc_buf[40];
+ char enc_token[10] = "Encoding0";
const char *icon = icon_buf;
const char *title = "-";
const char *url = "-";
@@ -1888,8 +1890,16 @@ void ro_gui_menu_prepare_pageinfo(void)
sprintf(icon_buf, "file_xxx");
}
- if (c->type == CONTENT_HTML && c->data.html.encoding != NULL) {
- enc = c->data.html.encoding;
+ if (c->type == CONTENT_HTML) {
+ if (c->data.html.encoding) {
+ enc_token[8] = '0' + c->data.html.encoding_source;
+ snprintf(enc_buf, sizeof enc_buf, "%s (%s)",
+ c->data.html.encoding,
+ messages_get(enc_token));
+ enc = enc_buf;
+ } else {
+ enc = messages_get("EncodingUnk");
+ }
}
ro_gui_set_icon_string(dialog_pageinfo, ICON_PAGEINFO_ICON, icon);