mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-22 12:12:35 +03:00
Fix parsing error when an empty HTML data is returned. Add HTTP status and other information to status bar.
svn path=/trunk/netsurf/; revision=3140
This commit is contained in:
parent
e76140557d
commit
bda01b3135
@ -450,11 +450,7 @@ Complete:Page complete (%gs)
|
|||||||
Redirecting:Redirecting...
|
Redirecting:Redirecting...
|
||||||
Processing:Processing document
|
Processing:Processing document
|
||||||
Formatting:Formatting document
|
Formatting:Formatting document
|
||||||
FetchObjs:Loading %u %s
|
|
||||||
FetchObjs2:Loading %u %s: %s
|
|
||||||
Done:Document done
|
Done:Document done
|
||||||
FetchStyle:Loading %u %s
|
|
||||||
FetchStyle2:Loading %u %s: %s
|
|
||||||
|
|
||||||
# Fetch warning/error messages - displayed in status bar
|
# Fetch warning/error messages - displayed in status bar
|
||||||
#
|
#
|
||||||
@ -471,6 +467,47 @@ PNGError:PNG library error.
|
|||||||
MNGError:MNG library error.
|
MNGError:MNG library error.
|
||||||
BadSprite:Invalid or corrupt Sprite data.
|
BadSprite:Invalid or corrupt Sprite data.
|
||||||
|
|
||||||
|
# HTTP status codes
|
||||||
|
#
|
||||||
|
HTTP0:OK
|
||||||
|
HTTP200:OK
|
||||||
|
HTTP201:Created
|
||||||
|
HTTP202:Accepted
|
||||||
|
HTTP203:Non-authoritative information
|
||||||
|
HTTP204:No content
|
||||||
|
HTTP205:Reset content
|
||||||
|
HTTP206:Partial content
|
||||||
|
HTTP300:Multiple choices
|
||||||
|
HTTP301:Moved permanently
|
||||||
|
HTTP302:Found
|
||||||
|
HTTP303:See other
|
||||||
|
HTTP304:Not modified
|
||||||
|
HTTP305:Use proxy
|
||||||
|
HTTP307:Temporary redirect
|
||||||
|
HTTP400:Bad request
|
||||||
|
HTTP401:Unauthorized
|
||||||
|
HTTP402:Payment required
|
||||||
|
HTTP403:Forbidden
|
||||||
|
HTTP404:Not found
|
||||||
|
HTTP405:Method not allowed
|
||||||
|
HTTP406:Not acceptable
|
||||||
|
HTTP407:Proxy authentication required
|
||||||
|
HTTP408:Request timeout
|
||||||
|
HTTP409:Conflict
|
||||||
|
HTTP410:Gone
|
||||||
|
HTTP411:Length required
|
||||||
|
HTTP412:Precondition failed
|
||||||
|
HTTP413:Request entity too large
|
||||||
|
HTTP414:Request-URI too long
|
||||||
|
HTTP415:Unsupported media type
|
||||||
|
HTTP416:Requested range not satisfiable
|
||||||
|
HTTP417:Expectation failed
|
||||||
|
HTTP500:Internal server error
|
||||||
|
HTTP501:Not implemented
|
||||||
|
HTTP502:Bad gateway
|
||||||
|
HTTP503:Service unavailable
|
||||||
|
HTTP504:Gateway timeout
|
||||||
|
HTTP505:HTTP version not supported
|
||||||
|
|
||||||
# User interface
|
# User interface
|
||||||
# ==============
|
# ==============
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* This file is part of NetSurf, http://netsurf-browser.org/
|
* This file is part of NetSurf, http://netsurf-browser.org/
|
||||||
* Licensed under the GNU General Public License,
|
* Licensed under the GNU General Public License,
|
||||||
* http://www.opensource.org/licenses/gpl-license
|
* http://www.opensource.org/licenses/gpl-license
|
||||||
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
|
* Copyright 2005-2007 James Bursa <bursa@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
@ -18,6 +18,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include "netsurf/utils/config.h"
|
#include "netsurf/utils/config.h"
|
||||||
#include "netsurf/content/content.h"
|
#include "netsurf/content/content.h"
|
||||||
#include "netsurf/content/fetch.h"
|
#include "netsurf/content/fetch.h"
|
||||||
@ -304,6 +305,7 @@ static const struct handler_entry handler_map[] = {
|
|||||||
#define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0]))
|
#define HANDLER_MAP_COUNT (sizeof(handler_map) / sizeof(handler_map[0]))
|
||||||
|
|
||||||
|
|
||||||
|
static void content_update_status(struct content *c);
|
||||||
static void content_destroy(struct content *c);
|
static void content_destroy(struct content *c);
|
||||||
static void content_stop_check(struct content *c);
|
static void content_stop_check(struct content *c);
|
||||||
|
|
||||||
@ -373,6 +375,7 @@ struct content * content_create(const char *url)
|
|||||||
c->refresh = 0;
|
c->refresh = 0;
|
||||||
c->bitmap = 0;
|
c->bitmap = 0;
|
||||||
c->fresh = false;
|
c->fresh = false;
|
||||||
|
c->time = clock();
|
||||||
c->size = 0;
|
c->size = 0;
|
||||||
c->title = 0;
|
c->title = 0;
|
||||||
c->active = 0;
|
c->active = 0;
|
||||||
@ -380,13 +383,14 @@ struct content * content_create(const char *url)
|
|||||||
user_sentinel->p1 = user_sentinel->p2 = 0;
|
user_sentinel->p1 = user_sentinel->p2 = 0;
|
||||||
user_sentinel->next = 0;
|
user_sentinel->next = 0;
|
||||||
c->user_list = user_sentinel;
|
c->user_list = user_sentinel;
|
||||||
content_set_status(c, messages_get("Loading"));
|
c->sub_status[0] = 0;
|
||||||
c->locked = false;
|
c->locked = false;
|
||||||
c->fetch = 0;
|
c->fetch = 0;
|
||||||
c->source_data = 0;
|
c->source_data = 0;
|
||||||
c->source_size = 0;
|
c->source_size = 0;
|
||||||
c->source_allocated = 0;
|
c->source_allocated = 0;
|
||||||
c->total_size = 0;
|
c->total_size = 0;
|
||||||
|
c->http_code = 0;
|
||||||
c->no_error_pages = false;
|
c->no_error_pages = false;
|
||||||
c->download = false;
|
c->download = false;
|
||||||
c->error_count = 0;
|
c->error_count = 0;
|
||||||
@ -400,6 +404,8 @@ struct content * content_create(const char *url)
|
|||||||
c->cache_data->etag = 0;
|
c->cache_data->etag = 0;
|
||||||
c->cache_data->last_modified = 0;
|
c->cache_data->last_modified = 0;
|
||||||
|
|
||||||
|
content_set_status(c, messages_get("Loading"));
|
||||||
|
|
||||||
c->prev = 0;
|
c->prev = 0;
|
||||||
c->next = content_list;
|
c->next = content_list;
|
||||||
if (content_list)
|
if (content_list)
|
||||||
@ -592,11 +598,38 @@ void content_set_status(struct content *c, const char *status_message, ...)
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
va_start(ap, status_message);
|
va_start(ap, status_message);
|
||||||
if ((len = vsnprintf(c->status_message, sizeof (c->status_message),
|
if ((len = vsnprintf(c->sub_status, sizeof (c->sub_status),
|
||||||
status_message, ap)) < 0 ||
|
status_message, ap)) < 0 ||
|
||||||
(int)sizeof (c->status_message) <= len)
|
(int)sizeof (c->sub_status) <= len)
|
||||||
c->status_message[sizeof (c->status_message) - 1] = '\0';
|
c->sub_status[sizeof (c->sub_status) - 1] = '\0';
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
content_update_status(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void content_update_status(struct content *c)
|
||||||
|
{
|
||||||
|
char token[20];
|
||||||
|
const char *status;
|
||||||
|
clock_t time;
|
||||||
|
|
||||||
|
snprintf(token, sizeof token, "HTTP%li", c->http_code);
|
||||||
|
status = messages_get(token);
|
||||||
|
if (status == token)
|
||||||
|
status = token + 4;
|
||||||
|
|
||||||
|
if (c->status == CONTENT_STATUS_TYPE_UNKNOWN ||
|
||||||
|
c->status == CONTENT_STATUS_LOADING ||
|
||||||
|
c->status == CONTENT_STATUS_READY)
|
||||||
|
time = clock() - c->time;
|
||||||
|
else
|
||||||
|
time = c->time;
|
||||||
|
|
||||||
|
snprintf(c->status_message, sizeof (c->status_message),
|
||||||
|
"%s (%.1fs) %s", status,
|
||||||
|
(float) time / CLOCKS_PER_SEC, c->sub_status);
|
||||||
|
/* LOG(("%s", c->status_message)); */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -704,7 +737,22 @@ void content_convert(struct content *c, int width, int height)
|
|||||||
c->status == CONTENT_STATUS_DONE);
|
c->status == CONTENT_STATUS_DONE);
|
||||||
content_broadcast(c, CONTENT_MSG_READY, msg_data);
|
content_broadcast(c, CONTENT_MSG_READY, msg_data);
|
||||||
if (c->status == CONTENT_STATUS_DONE)
|
if (c->status == CONTENT_STATUS_DONE)
|
||||||
content_broadcast(c, CONTENT_MSG_DONE, msg_data);
|
content_set_done(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put a content in status CONTENT_STATUS_DONE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void content_set_done(struct content *c)
|
||||||
|
{
|
||||||
|
union content_msg_data msg_data;
|
||||||
|
|
||||||
|
c->status = CONTENT_STATUS_DONE;
|
||||||
|
c->time = clock() - c->time;
|
||||||
|
content_update_status(c);
|
||||||
|
content_broadcast(c, CONTENT_MSG_DONE, msg_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* This file is part of NetSurf, http://netsurf-browser.org/
|
* This file is part of NetSurf, http://netsurf-browser.org/
|
||||||
* Licensed under the GNU General Public License,
|
* Licensed under the GNU General Public License,
|
||||||
* http://www.opensource.org/licenses/gpl-license
|
* http://www.opensource.org/licenses/gpl-license
|
||||||
* Copyright 2005 James Bursa <bursa@users.sourceforge.net>
|
* Copyright 2005-2007 James Bursa <bursa@users.sourceforge.net>
|
||||||
* Copyright 2003 Philip Pemberton <philpem@users.sourceforge.net>
|
* Copyright 2003 Philip Pemberton <philpem@users.sourceforge.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#define _NETSURF_DESKTOP_CONTENT_H_
|
#define _NETSURF_DESKTOP_CONTENT_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
#include "netsurf/utils/config.h"
|
#include "netsurf/utils/config.h"
|
||||||
#include "netsurf/content/content_type.h"
|
#include "netsurf/content/content_type.h"
|
||||||
#include "netsurf/css/css.h"
|
#include "netsurf/css/css.h"
|
||||||
@ -178,6 +179,9 @@ struct content {
|
|||||||
* shared between users. */
|
* shared between users. */
|
||||||
bool fresh;
|
bool fresh;
|
||||||
struct cache_data *cache_data; /**< Cache control data */
|
struct cache_data *cache_data; /**< Cache control data */
|
||||||
|
clock_t time; /**< Creation time, if TYPE_UNKNOWN,
|
||||||
|
LOADING or READY,
|
||||||
|
otherwise total time. */
|
||||||
|
|
||||||
unsigned int size; /**< Estimated size of all data
|
unsigned int size; /**< Estimated size of all data
|
||||||
associated with this content, except
|
associated with this content, except
|
||||||
@ -186,7 +190,8 @@ struct content {
|
|||||||
unsigned int active; /**< Number of child fetches or
|
unsigned int active; /**< Number of child fetches or
|
||||||
conversions currently in progress. */
|
conversions currently in progress. */
|
||||||
struct content_user *user_list; /**< List of users. */
|
struct content_user *user_list; /**< List of users. */
|
||||||
char status_message[80]; /**< Text for status bar. */
|
char status_message[120]; /**< Full text for status bar. */
|
||||||
|
char sub_status[80]; /**< Status of content. */
|
||||||
/** Content is being processed: data structures may be inconsistent
|
/** Content is being processed: data structures may be inconsistent
|
||||||
* and content must not be redrawn or modified. */
|
* and content must not be redrawn or modified. */
|
||||||
bool locked;
|
bool locked;
|
||||||
@ -196,6 +201,7 @@ struct content {
|
|||||||
unsigned long source_size; /**< Amount of data fetched so far. */
|
unsigned long source_size; /**< Amount of data fetched so far. */
|
||||||
unsigned long source_allocated; /**< Amount of space allocated so far. */
|
unsigned long source_allocated; /**< Amount of space allocated so far. */
|
||||||
unsigned long total_size; /**< Total data size, 0 if unknown. */
|
unsigned long total_size; /**< Total data size, 0 if unknown. */
|
||||||
|
long http_code; /**< HTTP status code, 0 if not HTTP. */
|
||||||
|
|
||||||
bool no_error_pages; /**< Used by fetchcache(). */
|
bool no_error_pages; /**< Used by fetchcache(). */
|
||||||
bool download; /**< Used by fetchcache(). */
|
bool download; /**< Used by fetchcache(). */
|
||||||
@ -226,6 +232,7 @@ void content_set_status(struct content *c, const char *status_message, ...);
|
|||||||
bool content_process_data(struct content *c, const char *data,
|
bool content_process_data(struct content *c, const char *data,
|
||||||
unsigned int size);
|
unsigned int size);
|
||||||
void content_convert(struct content *c, int width, int height);
|
void content_convert(struct content *c, int width, int height);
|
||||||
|
void content_set_done(struct content *c);
|
||||||
void content_reformat(struct content *c, int width, int height);
|
void content_reformat(struct content *c, int width, int height);
|
||||||
void content_clean(void);
|
void content_clean(void);
|
||||||
void content_reset(struct content *c);
|
void content_reset(struct content *c);
|
||||||
|
@ -376,6 +376,7 @@ void fetchcache_callback(fetch_msg msg, void *p, const void *data,
|
|||||||
switch (msg) {
|
switch (msg) {
|
||||||
case FETCH_TYPE:
|
case FETCH_TYPE:
|
||||||
c->total_size = size;
|
c->total_size = size;
|
||||||
|
c->http_code = fetch_http_code(c->fetch);
|
||||||
mime_type = fetchcache_parse_type(data, ¶ms);
|
mime_type = fetchcache_parse_type(data, ¶ms);
|
||||||
if (!mime_type) {
|
if (!mime_type) {
|
||||||
msg_data.error = messages_get("NoMemory");
|
msg_data.error = messages_get("NoMemory");
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
|
||||||
#include "curl/curl.h"
|
#include "curl/curl.h"
|
||||||
#include "netsurf/utils/config.h"
|
#include "netsurf/utils/config.h"
|
||||||
#include "netsurf/content/fetch.h"
|
#include "netsurf/content/fetch.h"
|
||||||
@ -286,7 +285,6 @@ void browser_window_go_post(struct browser_window *bw, const char *url,
|
|||||||
|
|
||||||
browser_window_set_status(bw, messages_get("Loading"));
|
browser_window_set_status(bw, messages_get("Loading"));
|
||||||
bw->history_add = history_add;
|
bw->history_add = history_add;
|
||||||
bw->time0 = clock();
|
|
||||||
c = fetchcache(url2, browser_window_callback, (intptr_t) bw, 0,
|
c = fetchcache(url2, browser_window_callback, (intptr_t) bw, 0,
|
||||||
width, height, false,
|
width, height, false,
|
||||||
post_urlenc, post_multipart, true, download);
|
post_urlenc, post_multipart, true, download);
|
||||||
@ -347,6 +345,7 @@ void browser_window_callback(content_msg msg, struct content *c,
|
|||||||
url[sizeof url - 1] = 0;
|
url[sizeof url - 1] = 0;
|
||||||
gui_window_set_url(bw->window, url);
|
gui_window_set_url(bw->window, url);
|
||||||
bw->refresh_interval = -1;
|
bw->refresh_interval = -1;
|
||||||
|
browser_window_set_status(bw, c->status_message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -414,10 +413,7 @@ void browser_window_callback(content_msg msg, struct content *c,
|
|||||||
assert(bw->current_content == c);
|
assert(bw->current_content == c);
|
||||||
|
|
||||||
browser_window_update(bw, false);
|
browser_window_update(bw, false);
|
||||||
sprintf(status, messages_get("Complete"),
|
browser_window_set_status(bw, c->status_message);
|
||||||
((float) (clock() - bw->time0)) /
|
|
||||||
CLOCKS_PER_SEC);
|
|
||||||
browser_window_set_status(bw, status);
|
|
||||||
browser_window_stop_throbber(bw);
|
browser_window_stop_throbber(bw);
|
||||||
history_update(bw->history, c);
|
history_update(bw->history, c);
|
||||||
hotlist_visited(c);
|
hotlist_visited(c);
|
||||||
|
@ -74,8 +74,6 @@ struct browser_window {
|
|||||||
bool throbbing;
|
bool throbbing;
|
||||||
/** Add loading_content to the window history when it loads. */
|
/** Add loading_content to the window history when it loads. */
|
||||||
bool history_add;
|
bool history_add;
|
||||||
/** Start time of fetching loading_content. */
|
|
||||||
clock_t time0;
|
|
||||||
|
|
||||||
/** Fragment identifier for current_content. */
|
/** Fragment identifier for current_content. */
|
||||||
char *frag_id;
|
char *frag_id;
|
||||||
|
222
render/html.c
222
render/html.c
@ -55,6 +55,20 @@ static bool html_object_type_permitted(const content_type type,
|
|||||||
static void html_object_refresh(void *p);
|
static void html_object_refresh(void *p);
|
||||||
static void html_destroy_frameset(struct content_html_frames *frameset);
|
static void html_destroy_frameset(struct content_html_frames *frameset);
|
||||||
static void html_destroy_iframe(struct content_html_iframe *iframe);
|
static void html_destroy_iframe(struct content_html_iframe *iframe);
|
||||||
|
static void html_set_status(struct content *c, const char *extra);
|
||||||
|
|
||||||
|
static const char empty_document[] =
|
||||||
|
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
|
||||||
|
" \"http://www.w3.org/TR/html4/strict.dtd\">"
|
||||||
|
"<html>"
|
||||||
|
"<head>"
|
||||||
|
"<title>Empty document</title>"
|
||||||
|
"</head>"
|
||||||
|
"<body>"
|
||||||
|
"<h1>Empty document</h1>"
|
||||||
|
"<p>The document sent by the server is empty.</p>"
|
||||||
|
"</body>"
|
||||||
|
"</html>";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,11 +278,15 @@ bool html_convert(struct content *c, int width, int height)
|
|||||||
union content_msg_data msg_data;
|
union content_msg_data msg_data;
|
||||||
|
|
||||||
/* finish parsing */
|
/* finish parsing */
|
||||||
|
if (c->source_size == 0)
|
||||||
|
htmlParseChunk(c->data.html.parser, empty_document,
|
||||||
|
sizeof empty_document, 0);
|
||||||
htmlParseChunk(c->data.html.parser, "", 0, 1);
|
htmlParseChunk(c->data.html.parser, "", 0, 1);
|
||||||
document = c->data.html.parser->myDoc;
|
document = c->data.html.parser->myDoc;
|
||||||
/*xmlDebugDumpDocument(stderr, c->data.html.parser->myDoc);*/
|
/*xmlDebugDumpDocument(stderr, c->data.html.parser->myDoc);*/
|
||||||
htmlFreeParserCtxt(c->data.html.parser);
|
htmlFreeParserCtxt(c->data.html.parser);
|
||||||
c->data.html.parser = 0;
|
c->data.html.parser = 0;
|
||||||
|
|
||||||
if (!document) {
|
if (!document) {
|
||||||
LOG(("Parsing failed"));
|
LOG(("Parsing failed"));
|
||||||
msg_data.error = messages_get("ParsingFail");
|
msg_data.error = messages_get("ParsingFail");
|
||||||
@ -353,24 +371,92 @@ bool html_convert(struct content *c, int width, int height)
|
|||||||
xmlFreeDoc(document);
|
xmlFreeDoc(document);
|
||||||
|
|
||||||
/* layout the box tree */
|
/* layout the box tree */
|
||||||
content_set_status(c, messages_get("Formatting"));
|
html_set_status(c, messages_get("Formatting"));
|
||||||
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
|
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
|
||||||
LOG(("Layout document"));
|
LOG(("Layout document"));
|
||||||
html_reformat(c, width, height);
|
html_reformat(c, width, height);
|
||||||
/*box_dump(c->data.html.layout->children, 0);*/
|
/*box_dump(c->data.html.layout->children, 0);*/
|
||||||
|
|
||||||
if (c->active == 0) {
|
if (c->active == 0)
|
||||||
c->status = CONTENT_STATUS_DONE;
|
c->status = CONTENT_STATUS_DONE;
|
||||||
content_set_status(c, messages_get("Done"));
|
else
|
||||||
} else {
|
|
||||||
c->status = CONTENT_STATUS_READY;
|
c->status = CONTENT_STATUS_READY;
|
||||||
content_set_status(c, messages_get("FetchObjs"), c->active,
|
html_set_status(c, "");
|
||||||
messages_get((c->active == 1) ? "obj" : "objs"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process elements in <head>.
|
||||||
|
*
|
||||||
|
* \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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool html_head(struct content *c, xmlNode *head)
|
||||||
|
{
|
||||||
|
xmlNode *node;
|
||||||
|
xmlChar *s;
|
||||||
|
|
||||||
|
c->title = 0;
|
||||||
|
|
||||||
|
for (node = head->children; node != 0; node = node->next) {
|
||||||
|
if (node->type != XML_ELEMENT_NODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LOG(("Node: %s", node->name));
|
||||||
|
if (!c->title && strcmp(node->name, "title") == 0) {
|
||||||
|
xmlChar *title = xmlNodeGetContent(node);
|
||||||
|
if (!title)
|
||||||
|
return false;
|
||||||
|
char *title2 = squash_whitespace(title);
|
||||||
|
xmlFree(title);
|
||||||
|
if (!title2)
|
||||||
|
return false;
|
||||||
|
c->title = talloc_strdup(c, title2);
|
||||||
|
free(title2);
|
||||||
|
if (!c->title)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (strcmp(node->name, "base") == 0) {
|
||||||
|
char *href = (char *) xmlGetProp(node,
|
||||||
|
(const xmlChar *) "href");
|
||||||
|
if (href) {
|
||||||
|
char *url;
|
||||||
|
url_func_result res;
|
||||||
|
res = url_normalize(href, &url);
|
||||||
|
if (res == URL_FUNC_OK) {
|
||||||
|
c->data.html.base_url =
|
||||||
|
talloc_strdup(c, url);
|
||||||
|
free(url);
|
||||||
|
}
|
||||||
|
xmlFree(href);
|
||||||
|
}
|
||||||
|
/* don't use the central values to ease freeing later on */
|
||||||
|
if ((s = xmlGetProp(node, (const xmlChar *) "target"))) {
|
||||||
|
if ((!strcasecmp(s, "_blank")) || (!strcasecmp(s, "_top")) ||
|
||||||
|
(!strcasecmp(s, "_parent")) ||
|
||||||
|
(!strcasecmp(s, "_self")) ||
|
||||||
|
('a' <= s[0] && s[0] <= 'z') ||
|
||||||
|
('A' <= s[0] && s[0] <= 'Z')) { /* [6.16] */
|
||||||
|
c->data.html.base_target = talloc_strdup(c, s);
|
||||||
|
if (!c->data.html.base_target) {
|
||||||
|
xmlFree(s);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for meta refresh
|
* Search for meta refresh
|
||||||
*
|
*
|
||||||
@ -483,75 +569,6 @@ bool html_meta_refresh(struct content *c, xmlNode *head)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Process elements in <head>.
|
|
||||||
*
|
|
||||||
* \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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool html_head(struct content *c, xmlNode *head)
|
|
||||||
{
|
|
||||||
xmlNode *node;
|
|
||||||
xmlChar *s;
|
|
||||||
|
|
||||||
c->title = 0;
|
|
||||||
|
|
||||||
for (node = head->children; node != 0; node = node->next) {
|
|
||||||
if (node->type != XML_ELEMENT_NODE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
LOG(("Node: %s", node->name));
|
|
||||||
if (!c->title && strcmp(node->name, "title") == 0) {
|
|
||||||
xmlChar *title = xmlNodeGetContent(node);
|
|
||||||
if (!title)
|
|
||||||
return false;
|
|
||||||
char *title2 = squash_whitespace(title);
|
|
||||||
xmlFree(title);
|
|
||||||
if (!title2)
|
|
||||||
return false;
|
|
||||||
c->title = talloc_strdup(c, title2);
|
|
||||||
free(title2);
|
|
||||||
if (!c->title)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else if (strcmp(node->name, "base") == 0) {
|
|
||||||
char *href = (char *) xmlGetProp(node,
|
|
||||||
(const xmlChar *) "href");
|
|
||||||
if (href) {
|
|
||||||
char *url;
|
|
||||||
url_func_result res;
|
|
||||||
res = url_normalize(href, &url);
|
|
||||||
if (res == URL_FUNC_OK) {
|
|
||||||
c->data.html.base_url =
|
|
||||||
talloc_strdup(c, url);
|
|
||||||
free(url);
|
|
||||||
}
|
|
||||||
xmlFree(href);
|
|
||||||
}
|
|
||||||
/* don't use the central values to ease freeing later on */
|
|
||||||
if ((s = xmlGetProp(node, (const xmlChar *) "target"))) {
|
|
||||||
if ((!strcasecmp(s, "_blank")) || (!strcasecmp(s, "_top")) ||
|
|
||||||
(!strcasecmp(s, "_parent")) ||
|
|
||||||
(!strcasecmp(s, "_self")) ||
|
|
||||||
('a' <= s[0] && s[0] <= 'z') ||
|
|
||||||
('A' <= s[0] && s[0] <= 'Z')) { /* [6.16] */
|
|
||||||
c->data.html.base_target = talloc_strdup(c, s);
|
|
||||||
if (!c->data.html.base_target) {
|
|
||||||
xmlFree(s);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlFree(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process inline stylesheets and fetch linked stylesheets.
|
* Process inline stylesheets and fetch linked stylesheets.
|
||||||
@ -762,9 +779,7 @@ bool html_find_stylesheets(struct content *c, xmlNode *head)
|
|||||||
/* complete the fetches */
|
/* complete the fetches */
|
||||||
while (c->active != 0) {
|
while (c->active != 0) {
|
||||||
if (c->active != last_active) {
|
if (c->active != last_active) {
|
||||||
content_set_status(c, messages_get("FetchStyle"),
|
html_set_status(c, "");
|
||||||
c->active,
|
|
||||||
messages_get((c->active == 1) ? "styl" : "styls"));
|
|
||||||
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
|
content_broadcast(c, CONTENT_MSG_STATUS, msg_data);
|
||||||
last_active = c->active;
|
last_active = c->active;
|
||||||
}
|
}
|
||||||
@ -820,7 +835,7 @@ void html_convert_css_callback(content_msg msg, struct content *css,
|
|||||||
c->data.html.stylesheet_content[i] = 0;
|
c->data.html.stylesheet_content[i] = 0;
|
||||||
c->active--;
|
c->active--;
|
||||||
content_add_error(c, "NotCSS", 0);
|
content_add_error(c, "NotCSS", 0);
|
||||||
content_set_status(c, messages_get("NotCSS"));
|
html_set_status(c, messages_get("NotCSS"));
|
||||||
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
||||||
content_remove_user(css,
|
content_remove_user(css,
|
||||||
html_convert_css_callback,
|
html_convert_css_callback,
|
||||||
@ -854,10 +869,7 @@ void html_convert_css_callback(content_msg msg, struct content *css,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CONTENT_MSG_STATUS:
|
case CONTENT_MSG_STATUS:
|
||||||
content_set_status(c, messages_get("FetchStyle2"),
|
html_set_status(c, css->status_message);
|
||||||
c->active,
|
|
||||||
messages_get((c->active == 1) ? "styl" : "styls"),
|
|
||||||
css->status_message);
|
|
||||||
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1063,7 +1075,7 @@ void html_object_callback(content_msg msg, struct content *object,
|
|||||||
c->data.html.object[i].content = 0;
|
c->data.html.object[i].content = 0;
|
||||||
c->active--;
|
c->active--;
|
||||||
content_add_error(c, "?", 0);
|
content_add_error(c, "?", 0);
|
||||||
content_set_status(c, messages_get("BadObject"));
|
html_set_status(c, messages_get("BadObject"));
|
||||||
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
||||||
content_remove_user(object, html_object_callback,
|
content_remove_user(object, html_object_callback,
|
||||||
(intptr_t) c, i);
|
(intptr_t) c, i);
|
||||||
@ -1094,18 +1106,14 @@ void html_object_callback(content_msg msg, struct content *object,
|
|||||||
c->data.html.object[i].content = 0;
|
c->data.html.object[i].content = 0;
|
||||||
c->active--;
|
c->active--;
|
||||||
content_add_error(c, "?", 0);
|
content_add_error(c, "?", 0);
|
||||||
content_set_status(c, messages_get("ObjError"),
|
html_set_status(c, data.error);
|
||||||
data.error);
|
|
||||||
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
content_broadcast(c, CONTENT_MSG_STATUS, data);
|
||||||
html_object_failed(box, c,
|
html_object_failed(box, c,
|
||||||
c->data.html.object[i].background);
|
c->data.html.object[i].background);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONTENT_MSG_STATUS:
|
case CONTENT_MSG_STATUS:
|
||||||
content_set_status(c, messages_get("FetchObjs2"),
|
html_set_status(c, object->status_message);
|
||||||
c->active,
|
|
||||||
messages_get((c->active == 1) ? "obj" : "objs"),
|
|
||||||
object->status_message);
|
|
||||||
/* content_broadcast(c, CONTENT_MSG_STATUS, 0); */
|
/* content_broadcast(c, CONTENT_MSG_STATUS, 0); */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1202,13 +1210,11 @@ void html_object_callback(content_msg msg, struct content *object,
|
|||||||
msg == CONTENT_MSG_AUTH)) {
|
msg == CONTENT_MSG_AUTH)) {
|
||||||
/* all objects have arrived */
|
/* all objects have arrived */
|
||||||
content_reformat(c, c->available_width, c->height);
|
content_reformat(c, c->available_width, c->height);
|
||||||
c->status = CONTENT_STATUS_DONE;
|
html_set_status(c, "");
|
||||||
content_set_status(c, messages_get("Done"));
|
content_set_done(c);
|
||||||
content_broadcast(c, CONTENT_MSG_DONE, data);
|
|
||||||
}
|
}
|
||||||
if (c->status == CONTENT_STATUS_READY)
|
if (c->status == CONTENT_STATUS_READY)
|
||||||
content_set_status(c, messages_get("FetchObjs"), c->active,
|
html_set_status(c, "");
|
||||||
messages_get((c->active == 1) ? "obj" : "objs"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1536,6 +1542,30 @@ void html_destroy_iframe(struct content_html_iframe *iframe) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the content status.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void html_set_status(struct content *c, const char *extra)
|
||||||
|
{
|
||||||
|
unsigned int stylesheets = 0, objects = 0;
|
||||||
|
if (c->data.html.object_count == 0)
|
||||||
|
stylesheets = c->data.html.stylesheet_count - c->active;
|
||||||
|
else {
|
||||||
|
stylesheets = c->data.html.stylesheet_count;
|
||||||
|
objects = c->data.html.object_count - c->active;
|
||||||
|
}
|
||||||
|
content_set_status(c, "%u/%u %s %u/%u %s %s",
|
||||||
|
stylesheets, c->data.html.stylesheet_count,
|
||||||
|
messages_get((c->data.html.stylesheet_count == 1) ?
|
||||||
|
"styl" : "styls"),
|
||||||
|
objects, c->data.html.object_count,
|
||||||
|
messages_get((c->data.html.object_count == 1) ?
|
||||||
|
"obj" : "objs"),
|
||||||
|
extra);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a window containing a CONTENT_HTML being opened.
|
* Handle a window containing a CONTENT_HTML being opened.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user