2003-06-30 16:44:03 +04:00
|
|
|
/*
|
2007-05-06 04:41:12 +04:00
|
|
|
* Copyright 2007 James Bursa <bursa@users.sourceforge.net>
|
2010-06-04 13:35:08 +04:00
|
|
|
* Copyright 2010 Michael Drake <tlsa@netsurf-browser.org>
|
2007-08-08 20:16:03 +04:00
|
|
|
*
|
|
|
|
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
|
|
|
*
|
|
|
|
* NetSurf is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; version 2 of the License.
|
|
|
|
*
|
|
|
|
* NetSurf is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2004-02-20 03:43:17 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* Content for text/html (implementation).
|
2003-02-09 15:58:15 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
2004-07-06 00:19:52 +04:00
|
|
|
#include <ctype.h>
|
2005-08-21 16:04:18 +04:00
|
|
|
#include <stdint.h>
|
2003-02-09 15:58:15 +03:00
|
|
|
#include <string.h>
|
2003-04-06 01:38:06 +04:00
|
|
|
#include <strings.h>
|
2003-02-09 15:58:15 +03:00
|
|
|
#include <stdlib.h>
|
2012-03-24 21:11:17 +04:00
|
|
|
|
2012-03-25 00:43:19 +04:00
|
|
|
#include <dom/dom.h>
|
|
|
|
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "utils/config.h"
|
2010-03-28 16:56:39 +04:00
|
|
|
#include "content/content_protected.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "content/fetch.h"
|
2010-03-28 16:56:39 +04:00
|
|
|
#include "content/hlcache.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "desktop/browser.h"
|
|
|
|
#include "desktop/options.h"
|
2011-07-01 15:16:43 +04:00
|
|
|
#include "desktop/selection.h"
|
2011-11-29 21:47:29 +04:00
|
|
|
#include "desktop/scrollbar.h"
|
2008-10-14 04:12:31 +04:00
|
|
|
#include "image/bitmap.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "render/box.h"
|
|
|
|
#include "render/font.h"
|
2009-02-20 14:39:25 +03:00
|
|
|
#include "render/form.h"
|
2011-05-07 00:40:09 +04:00
|
|
|
#include "render/html_internal.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "render/imagemap.h"
|
|
|
|
#include "render/layout.h"
|
2011-08-24 16:29:30 +04:00
|
|
|
#include "render/search.h"
|
2010-03-28 16:56:39 +04:00
|
|
|
#include "utils/http.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "utils/log.h"
|
|
|
|
#include "utils/messages.h"
|
2011-03-14 01:50:54 +03:00
|
|
|
#include "utils/schedule.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "utils/talloc.h"
|
|
|
|
#include "utils/url.h"
|
2011-12-02 01:49:57 +04:00
|
|
|
#include "utils/utf8.h"
|
2007-05-31 02:39:54 +04:00
|
|
|
#include "utils/utils.h"
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
#define CHUNK 4096
|
|
|
|
|
2008-10-10 14:56:34 +04:00
|
|
|
/* Change these to 1 to cause a dump to stderr of the frameset or box
|
|
|
|
* when the trees have been built.
|
|
|
|
*/
|
|
|
|
#define ALWAYS_DUMP_FRAMESET 0
|
|
|
|
#define ALWAYS_DUMP_BOX 0
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2007-01-13 03:21:15 +03:00
|
|
|
static const char empty_document[] =
|
|
|
|
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\""
|
2007-04-01 20:41:22 +04:00
|
|
|
" \"http://www.w3.org/TR/html4/strict.dtd\">"
|
2007-01-13 03:21:15 +03:00
|
|
|
"<html>"
|
|
|
|
"<head>"
|
|
|
|
"<title>Empty document</title>"
|
|
|
|
"</head>"
|
|
|
|
"<body>"
|
|
|
|
"<h1>Empty document</h1>"
|
|
|
|
"<p>The document sent by the server is empty.</p>"
|
|
|
|
"</body>"
|
|
|
|
"</html>";
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
static const char *html_types[] = {
|
|
|
|
"application/xhtml+xml",
|
|
|
|
"text/html"
|
|
|
|
};
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* forward declared functions */
|
|
|
|
static void html_object_refresh(void *p);
|
|
|
|
|
|
|
|
/* pre-interned character set */
|
2011-07-08 12:38:17 +04:00
|
|
|
static lwc_string *html_charset;
|
2011-05-07 00:40:09 +04:00
|
|
|
|
2011-10-05 12:32:52 +04:00
|
|
|
static nsurl *html_default_stylesheet_url;
|
|
|
|
static nsurl *html_adblock_stylesheet_url;
|
|
|
|
static nsurl *html_quirks_stylesheet_url;
|
2012-03-06 21:44:24 +04:00
|
|
|
static nsurl *html_user_stylesheet_url;
|
2011-10-05 12:32:52 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* pre-interned dom strings */
|
|
|
|
static dom_string *html_dom_string_html;
|
|
|
|
static dom_string *html_dom_string_head;
|
|
|
|
static dom_string *html_dom_string_rel;
|
2012-03-25 19:07:08 +04:00
|
|
|
dom_string *html_dom_string_href;
|
2012-03-24 21:11:17 +04:00
|
|
|
static dom_string *html_dom_string_hreflang;
|
|
|
|
static dom_string *html_dom_string_type;
|
|
|
|
static dom_string *html_dom_string_media;
|
|
|
|
static dom_string *html_dom_string_sizes;
|
|
|
|
static dom_string *html_dom_string_title;
|
|
|
|
static dom_string *html_dom_string_base;
|
|
|
|
static dom_string *html_dom_string_link;
|
2012-03-25 19:07:08 +04:00
|
|
|
dom_string *html_dom_string_target;
|
2012-03-24 23:35:59 +04:00
|
|
|
static dom_string *html_dom_string__parent;
|
|
|
|
static dom_string *html_dom_string__self;
|
|
|
|
static dom_string *html_dom_string__blank;
|
|
|
|
static dom_string *html_dom_string__top;
|
2012-03-25 02:08:13 +04:00
|
|
|
static dom_string *html_dom_string_http_equiv;
|
|
|
|
static dom_string *html_dom_string_content;
|
2012-03-25 19:07:08 +04:00
|
|
|
dom_string *html_dom_string_map;
|
|
|
|
dom_string *html_dom_string_id;
|
|
|
|
dom_string *html_dom_string_name;
|
|
|
|
dom_string *html_dom_string_area;
|
|
|
|
dom_string *html_dom_string_a;
|
|
|
|
dom_string *html_dom_string_nohref;
|
|
|
|
dom_string *html_dom_string_shape;
|
|
|
|
dom_string *html_dom_string_default;
|
|
|
|
dom_string *html_dom_string_rect;
|
|
|
|
dom_string *html_dom_string_rectangle;
|
|
|
|
dom_string *html_dom_string_coords;
|
|
|
|
dom_string *html_dom_string_circle;
|
|
|
|
dom_string *html_dom_string_poly;
|
|
|
|
dom_string *html_dom_string_polygon;
|
2012-03-24 21:11:17 +04:00
|
|
|
|
|
|
|
static nserror
|
|
|
|
html_create_html_data(html_content *c, const http_parameter *params)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
2011-07-08 12:38:17 +04:00
|
|
|
lwc_string *charset;
|
2004-06-11 00:41:26 +04:00
|
|
|
union content_msg_data msg_data;
|
2008-11-09 22:04:30 +03:00
|
|
|
binding_error error;
|
2010-03-28 16:56:39 +04:00
|
|
|
nserror nerror;
|
2004-02-20 03:43:17 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
c->parser_binding = NULL;
|
|
|
|
c->document = NULL;
|
|
|
|
c->quirks = BINDING_QUIRKS_MODE_NONE;
|
|
|
|
c->encoding = NULL;
|
2011-12-04 18:55:23 +04:00
|
|
|
c->base_url = nsurl_ref(content_get_url(&c->base));
|
2011-05-07 00:40:09 +04:00
|
|
|
c->base_target = NULL;
|
2011-07-20 00:23:59 +04:00
|
|
|
c->aborted = false;
|
2011-05-07 00:40:09 +04:00
|
|
|
c->layout = NULL;
|
|
|
|
c->background_colour = NS_TRANSPARENT;
|
|
|
|
c->stylesheet_count = 0;
|
|
|
|
c->stylesheets = NULL;
|
|
|
|
c->select_ctx = NULL;
|
2011-10-08 04:21:59 +04:00
|
|
|
c->universal = NULL;
|
2011-05-07 00:40:09 +04:00
|
|
|
c->num_objects = 0;
|
|
|
|
c->object_list = NULL;
|
|
|
|
c->forms = NULL;
|
|
|
|
c->imagemaps = NULL;
|
|
|
|
c->bw = NULL;
|
|
|
|
c->frameset = NULL;
|
|
|
|
c->iframe = NULL;
|
|
|
|
c->page = NULL;
|
|
|
|
c->box = NULL;
|
|
|
|
c->font_func = &nsfont;
|
2011-06-28 02:21:15 +04:00
|
|
|
c->scrollbar = NULL;
|
2004-06-11 00:41:26 +04:00
|
|
|
|
2011-10-08 04:21:59 +04:00
|
|
|
if (lwc_intern_string("*", SLEN("*"), &c->universal) != lwc_error_ok) {
|
|
|
|
error = BINDING_NOMEM;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2011-07-26 17:53:42 +04:00
|
|
|
selection_prepare(&c->sel, (struct content *)c, true);
|
2011-07-13 17:20:26 +04:00
|
|
|
|
2011-07-08 12:38:17 +04:00
|
|
|
nerror = http_parameter_list_find_item(params, html_charset, &charset);
|
2010-03-28 16:56:39 +04:00
|
|
|
if (nerror == NSERROR_OK) {
|
2011-07-08 12:38:17 +04:00
|
|
|
c->encoding = talloc_strdup(c, lwc_string_data(charset));
|
|
|
|
|
|
|
|
lwc_string_unref(charset);
|
|
|
|
|
|
|
|
if (c->encoding == NULL) {
|
2010-03-28 16:56:39 +04:00
|
|
|
error = BINDING_NOMEM;
|
|
|
|
goto error;
|
2005-01-02 01:05:21 +03:00
|
|
|
}
|
2011-05-07 00:40:09 +04:00
|
|
|
c->encoding_source = ENCODING_SOURCE_HEADER;
|
2005-01-02 01:05:21 +03:00
|
|
|
}
|
|
|
|
|
2008-09-23 06:19:50 +04:00
|
|
|
/* Create the parser binding */
|
2011-05-07 00:40:09 +04:00
|
|
|
error = binding_create_tree(c, c->encoding, &c->parser_binding);
|
|
|
|
if (error == BINDING_BADENCODING && c->encoding != NULL) {
|
2009-01-07 01:06:14 +03:00
|
|
|
/* Ok, we don't support the declared encoding. Bailing out
|
|
|
|
* isn't exactly user-friendly, so fall back to autodetect */
|
2011-05-07 00:40:09 +04:00
|
|
|
talloc_free(c->encoding);
|
|
|
|
c->encoding = NULL;
|
2009-01-07 01:06:14 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
error = binding_create_tree(c, c->encoding, &c->parser_binding);
|
2009-01-07 01:06:14 +03:00
|
|
|
}
|
|
|
|
|
2008-11-09 22:04:30 +03:00
|
|
|
if (error != BINDING_OK)
|
|
|
|
goto error;
|
2004-06-11 00:41:26 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return NSERROR_OK;
|
2005-01-02 01:05:21 +03:00
|
|
|
|
2008-11-09 22:04:30 +03:00
|
|
|
error:
|
2008-11-09 22:17:36 +03:00
|
|
|
if (error == BINDING_BADENCODING) {
|
2011-05-07 00:40:09 +04:00
|
|
|
LOG(("Bad encoding: %s", c->encoding ? c->encoding : ""));
|
2008-11-09 22:17:36 +03:00
|
|
|
msg_data.error = messages_get("ParsingFail");
|
2011-05-07 00:40:09 +04:00
|
|
|
nerror = NSERROR_BAD_ENCODING;
|
|
|
|
} else {
|
2008-11-09 22:04:30 +03:00
|
|
|
msg_data.error = messages_get("NoMemory");
|
2011-05-07 00:40:09 +04:00
|
|
|
nerror = NSERROR_NOMEM;
|
|
|
|
}
|
2008-11-09 22:04:30 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
|
2011-10-08 04:21:59 +04:00
|
|
|
if (c->universal != NULL) {
|
|
|
|
lwc_string_unref(c->universal);
|
|
|
|
c->universal = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c->base_url != NULL) {
|
|
|
|
nsurl_unref(c->base_url);
|
|
|
|
c->base_url = NULL;
|
|
|
|
}
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return nerror;
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/**
|
|
|
|
* Create a CONTENT_HTML.
|
|
|
|
*
|
|
|
|
* The content_html_data structure is initialized and the HTML parser is
|
|
|
|
* created.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static nserror
|
|
|
|
html_create(const content_handler *handler,
|
|
|
|
lwc_string *imime_type,
|
|
|
|
const http_parameter *params,
|
|
|
|
llcache_handle *llcache,
|
|
|
|
const char *fallback_charset,
|
|
|
|
bool quirks,
|
|
|
|
struct content **c)
|
|
|
|
{
|
|
|
|
html_content *html;
|
|
|
|
nserror error;
|
|
|
|
|
|
|
|
html = talloc_zero(0, html_content);
|
|
|
|
if (html == NULL)
|
|
|
|
return NSERROR_NOMEM;
|
|
|
|
|
|
|
|
error = content__init(&html->base, handler, imime_type, params,
|
|
|
|
llcache, fallback_charset, quirks);
|
|
|
|
if (error != NSERROR_OK) {
|
|
|
|
talloc_free(html);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = html_create_html_data(html, params);
|
|
|
|
if (error != NSERROR_OK) {
|
|
|
|
talloc_free(html);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
*c = (struct content *) html;
|
|
|
|
|
|
|
|
return NSERROR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
/**
|
|
|
|
* Process data for CONTENT_HTML.
|
|
|
|
*/
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool
|
|
|
|
html_process_data(struct content *c, const char *data, unsigned int size)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *html = (html_content *) c;
|
2008-09-23 06:19:50 +04:00
|
|
|
binding_error err;
|
2008-09-26 03:33:13 +04:00
|
|
|
const char *encoding;
|
2004-04-17 20:00:16 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
err = binding_parse_chunk(html->parser_binding,
|
2011-09-21 04:25:09 +04:00
|
|
|
(const uint8_t *) data, size);
|
2008-09-23 06:19:50 +04:00
|
|
|
if (err == BINDING_ENCODINGCHANGE) {
|
Merged revisions 4859-5013,5016-5018 via svnmerge from
svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub
........
r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines
A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong.
........
r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines
Fix segfault caused by mismatched struct layout expectations.
Fix warnings, too.
........
r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines
Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap.
........
r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines
Remove deugging printf()s, add Aliases file, add script { display: none; } block.
........
r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix a segfault bug.
........
r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines
Add gtk/res/Aliases as a symlink to the one in !NS/Resources
........
r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix symlink.
........
r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines
Make multiple parallel parser instances work correctly.
........
r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line
Don't display contents of STYLE.
........
r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines
Fix reparent_children to actually work
Make get_parent_node pay attention to the element_only flag
Fixup node referencing when appending a text child
Make clone_node clone attributes and namespace information in the non-deep case
........
r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines
Fix debug target
........
r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines
Use talloc to allocate space for Hubbub.
........
r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines
Stub out the encoding change callback so NS-hubbub compiles again.
........
r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines
Tell Hubbub the encoding that HTTP gives us, if we have one.
........
r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines
First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on.
........
r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix (I hope) a 64-bit compiler warning.
........
r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.)
........
r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines
Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb)
........
r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines
Pedantic typo fix.
Make Hubbub YES when building for RISC OS.
Make Hubbub AUTO when building for GTK
Ignore the presence of Hubbub on other platforms.
Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016)
Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO)
........
svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
|
|
|
goto encoding_change;
|
2009-04-15 15:28:07 +04:00
|
|
|
} else if (err != BINDING_OK) {
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
|
|
|
|
return false;
|
Merged revisions 4859-5013,5016-5018 via svnmerge from
svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub
........
r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines
A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong.
........
r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines
Fix segfault caused by mismatched struct layout expectations.
Fix warnings, too.
........
r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines
Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap.
........
r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines
Remove deugging printf()s, add Aliases file, add script { display: none; } block.
........
r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix a segfault bug.
........
r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines
Add gtk/res/Aliases as a symlink to the one in !NS/Resources
........
r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix symlink.
........
r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines
Make multiple parallel parser instances work correctly.
........
r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line
Don't display contents of STYLE.
........
r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines
Fix reparent_children to actually work
Make get_parent_node pay attention to the element_only flag
Fixup node referencing when appending a text child
Make clone_node clone attributes and namespace information in the non-deep case
........
r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines
Fix debug target
........
r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines
Use talloc to allocate space for Hubbub.
........
r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines
Stub out the encoding change callback so NS-hubbub compiles again.
........
r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines
Tell Hubbub the encoding that HTTP gives us, if we have one.
........
r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines
First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on.
........
r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix (I hope) a 64-bit compiler warning.
........
r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.)
........
r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines
Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb)
........
r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines
Pedantic typo fix.
Make Hubbub YES when building for RISC OS.
Make Hubbub AUTO when building for GTK
Ignore the presence of Hubbub on other platforms.
Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016)
Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO)
........
svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
|
|
|
}
|
2007-02-11 00:34:22 +03:00
|
|
|
|
2004-06-11 00:41:26 +04:00
|
|
|
return true;
|
Merged revisions 4859-5013,5016-5018 via svnmerge from
svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub
........
r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines
A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong.
........
r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines
Fix segfault caused by mismatched struct layout expectations.
Fix warnings, too.
........
r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines
Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap.
........
r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines
Remove deugging printf()s, add Aliases file, add script { display: none; } block.
........
r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix a segfault bug.
........
r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines
Add gtk/res/Aliases as a symlink to the one in !NS/Resources
........
r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix symlink.
........
r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines
Make multiple parallel parser instances work correctly.
........
r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line
Don't display contents of STYLE.
........
r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines
Fix reparent_children to actually work
Make get_parent_node pay attention to the element_only flag
Fixup node referencing when appending a text child
Make clone_node clone attributes and namespace information in the non-deep case
........
r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines
Fix debug target
........
r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines
Use talloc to allocate space for Hubbub.
........
r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines
Stub out the encoding change callback so NS-hubbub compiles again.
........
r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines
Tell Hubbub the encoding that HTTP gives us, if we have one.
........
r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines
First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on.
........
r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix (I hope) a 64-bit compiler warning.
........
r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.)
........
r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines
Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb)
........
r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines
Pedantic typo fix.
Make Hubbub YES when building for RISC OS.
Make Hubbub AUTO when building for GTK
Ignore the presence of Hubbub on other platforms.
Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016)
Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO)
........
svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
|
|
|
|
|
|
|
encoding_change:
|
|
|
|
|
2008-09-23 06:19:50 +04:00
|
|
|
/* Retrieve new encoding */
|
2008-09-26 03:33:13 +04:00
|
|
|
encoding = binding_get_encoding(
|
2011-05-07 00:40:09 +04:00
|
|
|
html->parser_binding,
|
|
|
|
&html->encoding_source);
|
Merged revisions 4859-5013,5016-5018 via svnmerge from
svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub
........
r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines
A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong.
........
r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines
Fix segfault caused by mismatched struct layout expectations.
Fix warnings, too.
........
r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines
Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap.
........
r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines
Remove deugging printf()s, add Aliases file, add script { display: none; } block.
........
r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix a segfault bug.
........
r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines
Add gtk/res/Aliases as a symlink to the one in !NS/Resources
........
r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix symlink.
........
r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines
Make multiple parallel parser instances work correctly.
........
r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line
Don't display contents of STYLE.
........
r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines
Fix reparent_children to actually work
Make get_parent_node pay attention to the element_only flag
Fixup node referencing when appending a text child
Make clone_node clone attributes and namespace information in the non-deep case
........
r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines
Fix debug target
........
r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines
Use talloc to allocate space for Hubbub.
........
r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines
Stub out the encoding change callback so NS-hubbub compiles again.
........
r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines
Tell Hubbub the encoding that HTTP gives us, if we have one.
........
r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines
First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on.
........
r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix (I hope) a 64-bit compiler warning.
........
r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.)
........
r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines
Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb)
........
r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines
Pedantic typo fix.
Make Hubbub YES when building for RISC OS.
Make Hubbub AUTO when building for GTK
Ignore the presence of Hubbub on other platforms.
Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016)
Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO)
........
svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
if (html->encoding != NULL)
|
|
|
|
talloc_free(html->encoding);
|
2009-01-06 20:52:47 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
html->encoding = talloc_strdup(c, encoding);
|
|
|
|
if (html->encoding == NULL) {
|
Merged revisions 4859-5013,5016-5018 via svnmerge from
svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub
........
r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines
A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong.
........
r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines
Fix segfault caused by mismatched struct layout expectations.
Fix warnings, too.
........
r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines
Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap.
........
r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines
Remove deugging printf()s, add Aliases file, add script { display: none; } block.
........
r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix a segfault bug.
........
r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines
Add gtk/res/Aliases as a symlink to the one in !NS/Resources
........
r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix symlink.
........
r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines
Make multiple parallel parser instances work correctly.
........
r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line
Don't display contents of STYLE.
........
r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines
Fix reparent_children to actually work
Make get_parent_node pay attention to the element_only flag
Fixup node referencing when appending a text child
Make clone_node clone attributes and namespace information in the non-deep case
........
r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines
Fix debug target
........
r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines
Use talloc to allocate space for Hubbub.
........
r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines
Stub out the encoding change callback so NS-hubbub compiles again.
........
r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines
Tell Hubbub the encoding that HTTP gives us, if we have one.
........
r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines
First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on.
........
r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix (I hope) a 64-bit compiler warning.
........
r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.)
........
r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines
Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb)
........
r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines
Pedantic typo fix.
Make Hubbub YES when building for RISC OS.
Make Hubbub AUTO when building for GTK
Ignore the presence of Hubbub on other platforms.
Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016)
Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO)
........
svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
|
|
|
union content_msg_data msg_data;
|
|
|
|
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-09-23 06:19:50 +04:00
|
|
|
/* Destroy binding */
|
2011-05-07 00:40:09 +04:00
|
|
|
binding_destroy_tree(html->parser_binding);
|
2008-08-11 12:40:58 +04:00
|
|
|
|
2008-09-23 06:19:50 +04:00
|
|
|
/* Create new binding, using the new encoding */
|
2011-05-07 00:40:09 +04:00
|
|
|
err = binding_create_tree(html, html->encoding, &html->parser_binding);
|
2009-01-07 01:06:14 +03:00
|
|
|
if (err == BINDING_BADENCODING) {
|
|
|
|
/* Ok, we don't support the declared encoding. Bailing out
|
|
|
|
* isn't exactly user-friendly, so fall back to Windows-1252 */
|
2011-05-07 00:40:09 +04:00
|
|
|
talloc_free(html->encoding);
|
|
|
|
html->encoding = talloc_strdup(c, "Windows-1252");
|
|
|
|
if (html->encoding == NULL) {
|
2009-01-07 01:06:14 +03:00
|
|
|
union content_msg_data msg_data;
|
|
|
|
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
err = binding_create_tree(html, html->encoding,
|
|
|
|
&html->parser_binding);
|
2009-01-07 01:06:14 +03:00
|
|
|
}
|
|
|
|
|
2008-11-09 22:04:30 +03:00
|
|
|
if (err != BINDING_OK) {
|
2008-09-23 06:19:50 +04:00
|
|
|
union content_msg_data msg_data;
|
2005-01-02 01:05:21 +03:00
|
|
|
|
2008-11-09 22:17:36 +03:00
|
|
|
if (err == BINDING_BADENCODING) {
|
2011-05-07 00:40:09 +04:00
|
|
|
LOG(("Bad encoding: %s", html->encoding
|
|
|
|
? html->encoding : ""));
|
2008-11-09 22:17:36 +03:00
|
|
|
msg_data.error = messages_get("ParsingFail");
|
|
|
|
} else
|
2008-11-09 22:04:30 +03:00
|
|
|
msg_data.error = messages_get("NoMemory");
|
2005-01-02 01:05:21 +03:00
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
{
|
|
|
|
const char *source_data;
|
|
|
|
unsigned long source_size;
|
|
|
|
|
|
|
|
source_data = content__get_source_data(c, &source_size);
|
|
|
|
|
2011-09-21 04:25:09 +04:00
|
|
|
/* Recurse to reprocess all the data. This is safe because
|
|
|
|
* the encoding is now specified at parser start which means
|
2010-03-28 16:56:39 +04:00
|
|
|
* it cannot be changed again. */
|
2010-04-03 20:37:36 +04:00
|
|
|
return html_process_data(c, source_data, source_size);
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
2005-01-02 01:05:21 +03:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/** process link node */
|
|
|
|
static bool html_process_link(html_content *c, dom_node *node)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
2012-03-24 21:11:17 +04:00
|
|
|
struct content_rfc5988_link link; /* the link added to the content */
|
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
dom_string *atr_string;
|
|
|
|
nserror error;
|
2008-11-20 17:47:36 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
memset(&link, 0, sizeof(struct content_rfc5988_link));
|
2008-11-20 17:47:36 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* check that the relation exists - w3c spec says must be present */
|
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_rel, &atr_string);
|
|
|
|
if ((exc != DOM_NO_ERR) || (atr_string == NULL)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
/* get a lwc string containing the link relation */
|
|
|
|
exc = dom_string_intern(atr_string, &link.rel);
|
|
|
|
dom_string_unref(atr_string);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check that the href exists - w3c spec says must be present */
|
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_href, &atr_string);
|
|
|
|
if ((exc != DOM_NO_ERR) || (atr_string == NULL)) {
|
|
|
|
lwc_string_unref(link.rel);
|
|
|
|
return false;
|
|
|
|
}
|
2008-11-20 17:47:36 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* get nsurl */
|
|
|
|
error = nsurl_join(c->base_url, dom_string_data(atr_string), &link.href);
|
|
|
|
dom_string_unref(atr_string);
|
|
|
|
if (error != NSERROR_OK) {
|
|
|
|
lwc_string_unref(link.rel);
|
|
|
|
return false;
|
2008-09-23 06:19:50 +04:00
|
|
|
}
|
Merged revisions 4859-5013,5016-5018 via svnmerge from
svn://source.netsurf-browser.org/branches/takkaria/netsurf-hubbub
........
r4860 | takkaria | 2008-08-02 03:51:35 +0100 (Sat, 02 Aug 2008) | 2 lines
A really horribly rough first go at integrating hubbub with NetSurf. Segfaults, but I'm not sure what I've done wrong.
........
r4861 | jmb | 2008-08-02 05:01:19 +0100 (Sat, 02 Aug 2008) | 3 lines
Fix segfault caused by mismatched struct layout expectations.
Fix warnings, too.
........
r4862 | jmb | 2008-08-02 05:11:02 +0100 (Sat, 02 Aug 2008) | 2 lines
Destroy parser as soon as it's no longer needed, and flag this so that html_destroy doesn't cause things to trample all over the heap.
........
r4863 | takkaria | 2008-08-02 15:30:34 +0100 (Sat, 02 Aug 2008) | 2 lines
Remove deugging printf()s, add Aliases file, add script { display: none; } block.
........
r4868 | takkaria | 2008-08-02 22:14:55 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix a segfault bug.
........
r4869 | takkaria | 2008-08-02 22:17:58 +0100 (Sat, 02 Aug 2008) | 2 lines
Add gtk/res/Aliases as a symlink to the one in !NS/Resources
........
r4870 | takkaria | 2008-08-02 22:26:31 +0100 (Sat, 02 Aug 2008) | 2 lines
Fix symlink.
........
r4885 | jmb | 2008-08-03 23:26:54 +0100 (Sun, 03 Aug 2008) | 2 lines
Make multiple parallel parser instances work correctly.
........
r4886 | tlsa | 2008-08-04 00:21:29 +0100 (Mon, 04 Aug 2008) | 1 line
Don't display contents of STYLE.
........
r4891 | jmb | 2008-08-04 01:18:07 +0100 (Mon, 04 Aug 2008) | 5 lines
Fix reparent_children to actually work
Make get_parent_node pay attention to the element_only flag
Fixup node referencing when appending a text child
Make clone_node clone attributes and namespace information in the non-deep case
........
r4918 | jmb | 2008-08-05 15:27:03 +0100 (Tue, 05 Aug 2008) | 2 lines
Fix debug target
........
r4944 | takkaria | 2008-08-07 12:56:50 +0100 (Thu, 07 Aug 2008) | 2 lines
Use talloc to allocate space for Hubbub.
........
r4993 | takkaria | 2008-08-10 17:49:47 +0100 (Sun, 10 Aug 2008) | 2 lines
Stub out the encoding change callback so NS-hubbub compiles again.
........
r4994 | takkaria | 2008-08-10 18:02:33 +0100 (Sun, 10 Aug 2008) | 2 lines
Tell Hubbub the encoding that HTTP gives us, if we have one.
........
r5001 | takkaria | 2008-08-11 02:53:24 +0100 (Mon, 11 Aug 2008) | 2 lines
First go at implementing proper <meta charset> support in NetSurf, amongst some refactoring. Probably works, but I have no pages around to test it on.
........
r5002 | takkaria | 2008-08-11 02:56:35 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix (I hope) a 64-bit compiler warning.
........
r5012 | takkaria | 2008-08-11 08:40:28 +0100 (Mon, 11 Aug 2008) | 2 lines
Fix some nits from jmb. (Remove const from html->encoding, set encoding_source to something about right.)
........
r5013 | takkaria | 2008-08-11 08:48:50 +0100 (Mon, 11 Aug 2008) | 2 lines
Properly fix <meta charset> handling, by passing in the right thing as the context. No idea how this worked before. :) (credit: jmb)
........
r5017 | jmb | 2008-08-11 09:13:22 +0100 (Mon, 11 Aug 2008) | 7 lines
Pedantic typo fix.
Make Hubbub YES when building for RISC OS.
Make Hubbub AUTO when building for GTK
Ignore the presence of Hubbub on other platforms.
Remove the explicit libparserutils pkg-config stuff from the makefile (see r5016)
Add some logic that means Hubbub gets enabled correctly when building on RISC OS and when cross-compiling for it. (This is ugly and will go away when pkg-config is available on RO)
........
svn path=/trunk/netsurf/; revision=5019
2008-08-11 12:17:48 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* look for optional properties -- we don't care if internment fails */
|
2009-04-15 15:28:07 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_hreflang, &atr_string);
|
|
|
|
if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
|
|
|
|
/* get a lwc string containing the href lang */
|
|
|
|
exc = dom_string_intern(atr_string, &link.hreflang);
|
|
|
|
dom_string_unref(atr_string);
|
|
|
|
}
|
2009-04-15 15:28:07 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_type, &atr_string);
|
|
|
|
if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
|
|
|
|
/* get a lwc string containing the type */
|
|
|
|
exc = dom_string_intern(atr_string, &link.type);
|
|
|
|
dom_string_unref(atr_string);
|
2009-04-15 15:28:07 +04:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_media, &atr_string);
|
|
|
|
if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
|
|
|
|
/* get a lwc string containing the media */
|
|
|
|
exc = dom_string_intern(atr_string, &link.media);
|
|
|
|
dom_string_unref(atr_string);
|
|
|
|
}
|
2008-09-23 06:19:50 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_sizes, &atr_string);
|
|
|
|
if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
|
|
|
|
/* get a lwc string containing the sizes */
|
|
|
|
exc = dom_string_intern(atr_string, &link.sizes);
|
|
|
|
dom_string_unref(atr_string);
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
2005-01-02 01:05:21 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* add to content */
|
|
|
|
content__add_rfc5988_link(&c->base, &link);
|
2009-02-20 15:50:34 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (link.sizes != NULL)
|
|
|
|
lwc_string_unref(link.sizes);
|
|
|
|
if (link.media != NULL)
|
|
|
|
lwc_string_unref(link.media);
|
|
|
|
if (link.type != NULL)
|
|
|
|
lwc_string_unref(link.type);
|
|
|
|
if (link.hreflang != NULL)
|
|
|
|
lwc_string_unref(link.hreflang);
|
2009-02-20 15:50:34 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
nsurl_unref(link.href);
|
|
|
|
lwc_string_unref(link.rel);
|
2011-07-20 00:23:59 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** process title node */
|
|
|
|
static bool html_process_title(html_content *c, dom_node *node)
|
|
|
|
{
|
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
dom_string *title;
|
|
|
|
char *title_str;
|
|
|
|
bool success;
|
|
|
|
|
|
|
|
if (c->base.title != NULL)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
exc = dom_node_get_text_content(node, &title);
|
|
|
|
if ((exc != DOM_NO_ERR) || (title == NULL)) {
|
2004-06-11 00:41:26 +04:00
|
|
|
return false;
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
2003-04-11 01:44:45 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
title_str = squash_whitespace(dom_string_data(title));
|
|
|
|
dom_string_unref(title);
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (title_str == NULL) {
|
|
|
|
return false;
|
2005-01-02 01:05:21 +03:00
|
|
|
}
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
success = content__set_title(&c->base, title_str);
|
2011-02-25 22:56:28 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
free(title_str);
|
2009-02-20 14:39:25 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
return success;
|
|
|
|
}
|
2009-02-20 15:50:34 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool html_process_base(html_content *c, dom_node *node)
|
|
|
|
{
|
2012-03-24 23:35:59 +04:00
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
dom_string *atr_string;
|
|
|
|
|
|
|
|
/* get href attribute if present */
|
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_href, &atr_string);
|
|
|
|
if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
|
2012-03-24 21:11:17 +04:00
|
|
|
nsurl *url;
|
|
|
|
nserror error;
|
2012-03-24 23:35:59 +04:00
|
|
|
|
|
|
|
/* get url from string */
|
|
|
|
error = nsurl_create(dom_string_data(atr_string), &url);
|
|
|
|
dom_string_unref(atr_string);
|
2012-03-24 21:11:17 +04:00
|
|
|
if (error == NSERROR_OK) {
|
|
|
|
if (c->base_url != NULL)
|
|
|
|
nsurl_unref(c->base_url);
|
|
|
|
c->base_url = url;
|
|
|
|
}
|
2012-03-24 23:35:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* get target attribute if present and not already set */
|
|
|
|
if (c->base_target != NULL) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
exc = dom_element_get_attribute(node, html_dom_string_target, &atr_string);
|
|
|
|
if ((exc == DOM_NO_ERR) && (atr_string != NULL)) {
|
|
|
|
/* Validation rules from the HTML5 spec for the base element:
|
|
|
|
* The target must be one of _blank, _self, _parent, or
|
|
|
|
* _top or any identifier which does not begin with an
|
|
|
|
* underscore
|
|
|
|
*/
|
|
|
|
if (*dom_string_data(atr_string) != '_' ||
|
|
|
|
dom_string_caseless_isequal(atr_string, html_dom_string__blank) ||
|
|
|
|
dom_string_caseless_isequal(atr_string, html_dom_string__self) ||
|
|
|
|
dom_string_caseless_isequal(atr_string, html_dom_string__parent) ||
|
|
|
|
dom_string_caseless_isequal(atr_string, html_dom_string__top)) {
|
|
|
|
c->base_target = strdup(dom_string_data(atr_string));
|
2009-02-20 15:50:34 +03:00
|
|
|
}
|
2012-03-24 23:35:59 +04:00
|
|
|
dom_string_unref(atr_string);
|
2009-02-20 14:39:25 +03:00
|
|
|
}
|
2012-03-24 23:35:59 +04:00
|
|
|
|
|
|
|
return true;
|
2010-04-11 14:52:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-03-24 21:11:17 +04:00
|
|
|
* 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.
|
2010-04-11 14:52:18 +04:00
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool html_head(html_content *c, dom_node *head)
|
|
|
|
{
|
|
|
|
dom_node *node;
|
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
dom_string *node_name;
|
|
|
|
dom_node_type node_type;
|
|
|
|
dom_node *next_node;
|
|
|
|
|
|
|
|
exc = dom_node_get_first_child(head, &node);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
return false;
|
2010-04-11 14:52:18 +04:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
while (node != NULL) {
|
|
|
|
exc = dom_node_get_node_type(head, &node_type);
|
2010-04-11 14:52:18 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if ((exc == DOM_NO_ERR) && (node_type == DOM_ELEMENT_NODE)) {
|
|
|
|
exc = dom_node_get_node_name(head, &node_name);
|
2010-04-11 14:52:18 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if ((exc == DOM_NO_ERR) || (node_name != NULL)) {
|
|
|
|
if (!dom_string_caseless_isequal(node_name,
|
|
|
|
html_dom_string_title)) {
|
|
|
|
html_process_title(c, node);
|
|
|
|
} else if (!dom_string_caseless_isequal(node_name,
|
|
|
|
html_dom_string_base)) {
|
|
|
|
html_process_base(c, node);
|
|
|
|
} else if (!dom_string_caseless_isequal(node_name,
|
|
|
|
html_dom_string_link)) {
|
|
|
|
html_process_link(c, node);
|
|
|
|
}
|
|
|
|
}
|
2010-04-11 14:52:18 +04:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* move to next node */
|
|
|
|
exc = dom_node_get_next_sibling(node, &next_node);
|
|
|
|
dom_node_unref(node);
|
|
|
|
if (exc == DOM_NO_ERR) {
|
|
|
|
node = next_node;
|
|
|
|
} else {
|
|
|
|
node = NULL;
|
2010-04-11 14:52:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
return true;
|
2011-09-29 23:15:54 +04:00
|
|
|
}
|
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
static bool html_meta_refresh_process_element(html_content *c, dom_node *n)
|
2011-09-29 23:15:54 +04:00
|
|
|
{
|
|
|
|
union content_msg_data msg_data;
|
2012-03-25 02:08:13 +04:00
|
|
|
const char *url, *end, *refresh = NULL;
|
|
|
|
char *new_url;
|
|
|
|
char quote = '\0';
|
|
|
|
dom_string *equiv, *content;
|
|
|
|
dom_exception exc;
|
2012-03-24 21:11:17 +04:00
|
|
|
nsurl *nsurl;
|
|
|
|
nserror error;
|
2011-09-29 23:15:54 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
exc = dom_element_get_attribute(n, html_dom_string_http_equiv, &equiv);
|
|
|
|
if (exc != DOM_NO_ERR)
|
|
|
|
return false;
|
2011-09-29 23:15:54 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
if (equiv == NULL)
|
|
|
|
return true;
|
2011-09-29 23:15:54 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
if (strcasecmp(dom_string_data(equiv), "refresh") != 0) {
|
|
|
|
dom_string_unref(equiv);
|
|
|
|
return true;
|
|
|
|
}
|
2011-09-29 23:15:54 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
dom_string_unref(equiv);
|
2003-04-12 01:06:51 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
exc = dom_element_get_attribute(n, html_dom_string_content, &content);
|
|
|
|
if (exc != DOM_NO_ERR)
|
|
|
|
return false;
|
2004-03-27 01:16:31 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
if (content == NULL)
|
|
|
|
return true;
|
2009-02-20 14:39:25 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
end = dom_string_data(content) + dom_string_byte_length(content);
|
2010-04-11 14:52:18 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* content := *LWS intpart fracpart? *LWS [';' *LWS *1url *LWS]
|
|
|
|
* intpart := 1*DIGIT
|
|
|
|
* fracpart := 1*('.' | DIGIT)
|
|
|
|
* url := "url" *LWS '=' *LWS (url-nq | url-sq | url-dq)
|
|
|
|
* url-nq := *urlchar
|
|
|
|
* url-sq := "'" *(urlchar | '"') "'"
|
|
|
|
* url-dq := '"' *(urlchar | "'") '"'
|
|
|
|
* urlchar := [#x9#x21#x23-#x26#x28-#x7E] | nonascii
|
|
|
|
* nonascii := [#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
|
|
|
|
*/
|
2008-07-30 04:51:26 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
url = dom_string_data(content);
|
2011-11-05 22:36:21 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* *LWS */
|
|
|
|
while (url < end && isspace(*url)) {
|
|
|
|
url++;
|
|
|
|
}
|
2011-11-05 22:36:21 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* intpart */
|
|
|
|
if (url == end || (*url < '0' || '9' < *url)) {
|
|
|
|
/* Empty content, or invalid timeval */
|
|
|
|
dom_string_unref(content);
|
|
|
|
return true;
|
|
|
|
}
|
2011-11-05 22:36:21 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
msg_data.delay = (int) strtol(url, &new_url, 10);
|
|
|
|
/* a very small delay and self-referencing URL can cause a loop
|
|
|
|
* that grinds machines to a halt. To prevent this we set a
|
|
|
|
* minimum refresh delay of 1s. */
|
|
|
|
if (msg_data.delay < 1)
|
|
|
|
msg_data.delay = 1;
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
url = new_url;
|
2008-12-30 18:46:06 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* fracpart? (ignored, as delay is integer only) */
|
|
|
|
while (url < end && (('0' <= *url && *url <= '9') ||
|
|
|
|
*url == '.')) {
|
|
|
|
url++;
|
|
|
|
}
|
2008-07-30 04:51:26 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* *LWS */
|
|
|
|
while (url < end && isspace(*url)) {
|
|
|
|
url++;
|
|
|
|
}
|
2008-07-30 04:51:26 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* ';' */
|
|
|
|
if (url < end && *url == ';')
|
|
|
|
url++;
|
2008-07-30 04:51:26 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* *LWS */
|
|
|
|
while (url < end && isspace(*url)) {
|
|
|
|
url++;
|
|
|
|
}
|
2006-01-28 19:01:19 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
if (url == end) {
|
|
|
|
/* Just delay specified, so refresh current page */
|
|
|
|
dom_string_unref(content);
|
2006-01-28 19:01:19 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
c->base.refresh = nsurl_ref(
|
|
|
|
content_get_url(&c->base));
|
2006-09-17 01:33:55 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
content_broadcast(&c->base, CONTENT_MSG_REFRESH,
|
|
|
|
msg_data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* "url" */
|
|
|
|
if (url <= end - 3) {
|
|
|
|
if (strncasecmp(url, "url", 3) == 0) {
|
|
|
|
url += 3;
|
2008-07-30 04:51:26 +04:00
|
|
|
} else {
|
2012-03-25 02:08:13 +04:00
|
|
|
/* Unexpected input, ignore this header */
|
|
|
|
dom_string_unref(content);
|
|
|
|
return true;
|
2006-01-25 09:52:38 +03:00
|
|
|
}
|
2012-03-25 02:08:13 +04:00
|
|
|
} else {
|
|
|
|
/* Insufficient input, ignore this header */
|
|
|
|
dom_string_unref(content);
|
|
|
|
return true;
|
|
|
|
}
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* *LWS */
|
|
|
|
while (url < end && isspace(*url)) {
|
|
|
|
url++;
|
|
|
|
}
|
2008-07-30 04:51:26 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* '=' */
|
|
|
|
if (url < end) {
|
|
|
|
if (*url == '=') {
|
|
|
|
url++;
|
2008-07-30 04:51:26 +04:00
|
|
|
} else {
|
2012-03-25 02:08:13 +04:00
|
|
|
/* Unexpected input, ignore this header */
|
|
|
|
dom_string_unref(content);
|
|
|
|
return true;
|
2006-07-18 03:57:42 +04:00
|
|
|
}
|
2012-03-25 02:08:13 +04:00
|
|
|
} else {
|
|
|
|
/* Insufficient input, ignore this header */
|
|
|
|
dom_string_unref(content);
|
|
|
|
return true;
|
|
|
|
}
|
2006-09-17 01:33:55 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* *LWS */
|
|
|
|
while (url < end && isspace(*url)) {
|
|
|
|
url++;
|
|
|
|
}
|
2007-04-01 20:41:22 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* '"' or "'" */
|
|
|
|
if (url < end && (*url == '"' || *url == '\'')) {
|
|
|
|
quote = *url;
|
|
|
|
url++;
|
|
|
|
}
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* Start of URL */
|
|
|
|
refresh = url;
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
if (quote != 0) {
|
|
|
|
/* url-sq | url-dq */
|
|
|
|
while (url < end && *url != quote)
|
|
|
|
url++;
|
|
|
|
} else {
|
|
|
|
/* url-nq */
|
|
|
|
while (url < end && !isspace(*url))
|
|
|
|
url++;
|
|
|
|
}
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
/* '"' or "'" or *LWS (we don't care) */
|
|
|
|
if (url < end) {
|
|
|
|
new_url = strndup(refresh, url - refresh);
|
|
|
|
if (new_url == NULL) {
|
|
|
|
dom_string_unref(content);
|
|
|
|
return false;
|
|
|
|
}
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
error = nsurl_join(c->base_url, new_url, &nsurl);
|
2011-10-03 19:56:47 +04:00
|
|
|
if (error != NSERROR_OK) {
|
2012-03-25 02:08:13 +04:00
|
|
|
free(new_url);
|
|
|
|
|
|
|
|
dom_string_unref(content);
|
2011-11-05 22:36:21 +04:00
|
|
|
|
2008-07-30 04:51:26 +04:00
|
|
|
msg_data.error = messages_get("NoMemory");
|
2011-05-07 00:40:09 +04:00
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR,
|
|
|
|
msg_data);
|
2011-11-05 22:36:21 +04:00
|
|
|
|
2008-07-30 04:51:26 +04:00
|
|
|
return false;
|
2006-01-25 09:52:38 +03:00
|
|
|
}
|
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
free(new_url);
|
2008-07-30 04:51:26 +04:00
|
|
|
|
2011-10-03 19:56:47 +04:00
|
|
|
c->base.refresh = nsurl;
|
2008-07-30 04:51:26 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
content_broadcast(&c->base, CONTENT_MSG_REFRESH, msg_data);
|
2006-01-25 09:52:38 +03:00
|
|
|
}
|
2012-03-25 02:08:13 +04:00
|
|
|
|
|
|
|
dom_string_unref(content);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Search for meta refresh
|
|
|
|
*
|
|
|
|
* http://wp.netscape.com/assist/net_sites/pushpull.html
|
|
|
|
*
|
|
|
|
* \param c content structure
|
|
|
|
* \param head xml node of head element
|
|
|
|
* \return true on success, false otherwise (error reported)
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool html_meta_refresh(html_content *c, dom_node *head)
|
|
|
|
{
|
|
|
|
dom_node *n, *next;
|
|
|
|
dom_exception exc;
|
|
|
|
|
|
|
|
if (head == NULL)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
exc = dom_node_get_first_child(head, &n);
|
|
|
|
if (exc != DOM_NO_ERR)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
while (n != NULL) {
|
|
|
|
dom_node_type type;
|
|
|
|
|
|
|
|
exc = dom_node_get_node_type(n, &type);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(n);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-03-25 02:36:22 +04:00
|
|
|
if (type == DOM_ELEMENT_NODE) {
|
2012-03-25 02:08:13 +04:00
|
|
|
dom_string *name;
|
|
|
|
|
|
|
|
exc = dom_node_get_node_name(n, &name);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(n);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Recurse into noscript elements */
|
|
|
|
if (strcmp(dom_string_data(name), "noscript") == 0) {
|
|
|
|
if (html_meta_refresh(c, n) == false) {
|
|
|
|
/* Some error occurred */
|
|
|
|
dom_node_unref(n);
|
|
|
|
return false;
|
|
|
|
} else if (c->base.refresh) {
|
|
|
|
/* Meta refresh found - stop */
|
|
|
|
dom_node_unref(n);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else if (strcmp(dom_string_data(name), "meta") == 0) {
|
|
|
|
if (html_meta_refresh_process_element(c,
|
|
|
|
n) == false) {
|
|
|
|
/* Some error occurred */
|
|
|
|
dom_node_unref(n);
|
|
|
|
return false;
|
|
|
|
} else if (c->base.refresh != NULL) {
|
|
|
|
/* Meta refresh found - stop */
|
|
|
|
dom_node_unref(n);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
exc = dom_node_get_next_sibling(n, &next);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(n);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom_node_unref(n);
|
|
|
|
n = next;
|
|
|
|
}
|
|
|
|
|
2006-01-25 09:52:38 +03:00
|
|
|
return true;
|
|
|
|
}
|
2003-02-09 15:58:15 +03:00
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
/**
|
2012-03-24 21:11:17 +04:00
|
|
|
* Update a box whose content has completed rendering.
|
2004-02-20 03:43:17 +03:00
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void
|
|
|
|
html_object_done(struct box *box,
|
|
|
|
hlcache_handle *object,
|
|
|
|
bool background)
|
2003-04-06 01:38:06 +04:00
|
|
|
{
|
2012-03-24 21:11:17 +04:00
|
|
|
struct box *b;
|
2003-04-15 21:53:00 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (background) {
|
|
|
|
box->background = object;
|
|
|
|
return;
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
box->object = object;
|
2004-07-31 03:40:01 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (!(box->flags & REPLACE_DIM)) {
|
|
|
|
/* invalidate parent min, max widths */
|
|
|
|
for (b = box; b; b = b->parent)
|
|
|
|
b->max_width = UNKNOWN_MAX_WIDTH;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* delete any clones of this box */
|
|
|
|
while (box->next && (box->next->flags & CLONE)) {
|
|
|
|
/* box_free_box(box->next); */
|
|
|
|
box->next = box->next->next;
|
|
|
|
}
|
2009-07-24 03:05:34 +04:00
|
|
|
}
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
2009-07-24 03:05:34 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/**
|
|
|
|
* Handle object fetching or loading failure.
|
|
|
|
*
|
|
|
|
* \param box box containing object which failed to load
|
|
|
|
* \param content document of type CONTENT_HTML
|
|
|
|
* \param background the object was the background image for the box
|
|
|
|
*/
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void
|
|
|
|
html_object_failed(struct box *box, html_content *content, bool background)
|
|
|
|
{
|
|
|
|
/* Nothing to do */
|
|
|
|
return;
|
|
|
|
}
|
2003-04-06 01:38:06 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/**
|
|
|
|
* Callback for hlcache_handle_retrieve() for objects.
|
|
|
|
*/
|
2012-03-06 21:44:24 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static nserror
|
|
|
|
html_object_callback(hlcache_handle *object,
|
|
|
|
const hlcache_event *event,
|
|
|
|
void *pw)
|
|
|
|
{
|
|
|
|
struct content_html_object *o = pw;
|
|
|
|
html_content *c = (html_content *) o->parent;
|
|
|
|
int x, y;
|
|
|
|
struct box *box;
|
2012-03-06 21:44:24 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
assert(c->base.status != CONTENT_STATUS_ERROR);
|
2008-09-23 14:44:10 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
box = o->box;
|
|
|
|
|
|
|
|
switch (event->type) {
|
|
|
|
case CONTENT_MSG_LOADING:
|
|
|
|
if (c->base.status != CONTENT_STATUS_LOADING && c->bw != NULL)
|
|
|
|
content_open(object,
|
|
|
|
c->bw, &c->base,
|
|
|
|
box,
|
|
|
|
box->object_params);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_MSG_READY:
|
|
|
|
if (content_get_type(object) == CONTENT_HTML) {
|
|
|
|
html_object_done(box, object, o->background);
|
|
|
|
if (c->base.status == CONTENT_STATUS_READY ||
|
|
|
|
c->base.status == CONTENT_STATUS_DONE)
|
|
|
|
content__reformat(&c->base, false,
|
|
|
|
c->base.available_width,
|
|
|
|
c->base.height);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_MSG_DONE:
|
|
|
|
c->base.active--;
|
|
|
|
html_object_done(box, object, o->background);
|
|
|
|
|
|
|
|
if (c->base.status != CONTENT_STATUS_LOADING &&
|
|
|
|
box->flags & REPLACE_DIM) {
|
|
|
|
union content_msg_data data;
|
|
|
|
|
|
|
|
if (!box_visible(box))
|
2008-09-23 14:44:10 +04:00
|
|
|
break;
|
2012-03-24 21:11:17 +04:00
|
|
|
|
|
|
|
box_coords(box, &x, &y);
|
|
|
|
|
|
|
|
data.redraw.x = x + box->padding[LEFT];
|
|
|
|
data.redraw.y = y + box->padding[TOP];
|
|
|
|
data.redraw.width = box->width;
|
|
|
|
data.redraw.height = box->height;
|
|
|
|
data.redraw.full_redraw = true;
|
|
|
|
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
|
2008-09-23 14:44:10 +04:00
|
|
|
}
|
2012-03-24 21:11:17 +04:00
|
|
|
break;
|
2008-09-23 14:44:10 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
case CONTENT_MSG_ERROR:
|
|
|
|
hlcache_handle_release(object);
|
2008-09-23 14:44:10 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
o->content = NULL;
|
2004-02-20 03:43:17 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
c->base.active--;
|
2003-04-06 01:38:06 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
content_add_error(&c->base, "?", 0);
|
|
|
|
html_set_status(c, event->data.error);
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_STATUS, event->data);
|
|
|
|
html_object_failed(box, c, o->background);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_MSG_STATUS:
|
|
|
|
html_set_status(c, content_get_status_message(object));
|
|
|
|
/* content_broadcast(&c->base, CONTENT_MSG_STATUS, 0); */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_MSG_REFORMAT:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_MSG_REDRAW:
|
|
|
|
if (c->base.status != CONTENT_STATUS_LOADING) {
|
|
|
|
union content_msg_data data = event->data;
|
|
|
|
|
|
|
|
if (!box_visible(box))
|
|
|
|
break;
|
|
|
|
|
|
|
|
box_coords(box, &x, &y);
|
|
|
|
|
|
|
|
if (hlcache_handle_get_content(object) ==
|
|
|
|
event->data.redraw.object) {
|
|
|
|
data.redraw.x = data.redraw.x *
|
|
|
|
box->width / content_get_width(object);
|
|
|
|
data.redraw.y = data.redraw.y *
|
|
|
|
box->height /
|
|
|
|
content_get_height(object);
|
|
|
|
data.redraw.width = data.redraw.width *
|
|
|
|
box->width / content_get_width(object);
|
|
|
|
data.redraw.height = data.redraw.height *
|
|
|
|
box->height /
|
|
|
|
content_get_height(object);
|
|
|
|
data.redraw.object_width = box->width;
|
|
|
|
data.redraw.object_height = box->height;
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
2003-04-06 01:38:06 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
data.redraw.x += x + box->padding[LEFT];
|
|
|
|
data.redraw.y += y + box->padding[TOP];
|
|
|
|
data.redraw.object_x += x + box->padding[LEFT];
|
|
|
|
data.redraw.object_y += y + box->padding[TOP];
|
|
|
|
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_MSG_REFRESH:
|
|
|
|
if (content_get_type(object) == CONTENT_HTML) {
|
|
|
|
/* only for HTML objects */
|
|
|
|
schedule(event->data.delay * 100,
|
|
|
|
html_object_refresh, o);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONTENT_MSG_LINK:
|
|
|
|
/* Don't care about favicons */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c->base.status == CONTENT_STATUS_READY && c->base.active == 0 &&
|
|
|
|
(event->type == CONTENT_MSG_LOADING ||
|
|
|
|
event->type == CONTENT_MSG_DONE ||
|
|
|
|
event->type == CONTENT_MSG_ERROR)) {
|
|
|
|
/* all objects have arrived */
|
|
|
|
content__reformat(&c->base, false, c->base.available_width,
|
|
|
|
c->base.height);
|
|
|
|
html_set_status(c, "");
|
|
|
|
content_set_done(&c->base);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If 1) the configuration option to reflow pages while objects are
|
|
|
|
* fetched is set
|
|
|
|
* 2) an object is newly fetched & converted,
|
|
|
|
* 3) the box's dimensions need to change due to being replaced
|
|
|
|
* 4) the object's parent HTML is ready for reformat,
|
|
|
|
* 5) the time since the previous reformat is more than the
|
|
|
|
* configured minimum time between reformats
|
|
|
|
* then reformat the page to display newly fetched objects */
|
|
|
|
else if (nsoption_bool(incremental_reflow) &&
|
|
|
|
event->type == CONTENT_MSG_DONE &&
|
|
|
|
!(box->flags & REPLACE_DIM) &&
|
|
|
|
(c->base.status == CONTENT_STATUS_READY ||
|
|
|
|
c->base.status == CONTENT_STATUS_DONE) &&
|
|
|
|
(wallclock() > c->base.reformat_time)) {
|
|
|
|
content__reformat(&c->base, false, c->base.available_width,
|
|
|
|
c->base.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NSERROR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Start a fetch for an object required by a page, replacing an existing object.
|
|
|
|
*
|
|
|
|
* \param object Object to replace
|
|
|
|
* \param url URL of object to fetch (copied)
|
|
|
|
* \return true on success, false on memory exhaustion
|
|
|
|
*/
|
|
|
|
|
|
|
|
static bool html_replace_object(struct content_html_object *object, nsurl *url)
|
|
|
|
{
|
|
|
|
html_content *c;
|
|
|
|
hlcache_child_context child;
|
|
|
|
html_content *page;
|
|
|
|
nserror error;
|
|
|
|
|
|
|
|
assert(object != NULL);
|
|
|
|
|
|
|
|
c = (html_content *) object->parent;
|
|
|
|
|
|
|
|
child.charset = c->encoding;
|
|
|
|
child.quirks = c->base.quirks;
|
|
|
|
|
|
|
|
if (object->content != NULL) {
|
|
|
|
/* remove existing object */
|
|
|
|
if (content_get_status(object->content) != CONTENT_STATUS_DONE)
|
|
|
|
c->base.active--;
|
|
|
|
|
|
|
|
hlcache_handle_release(object->content);
|
|
|
|
object->content = NULL;
|
|
|
|
|
|
|
|
object->box->object = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialise fetch */
|
|
|
|
error = hlcache_handle_retrieve(url, HLCACHE_RETRIEVE_SNIFF_TYPE,
|
|
|
|
content_get_url(&c->base), NULL,
|
|
|
|
html_object_callback, object, &child,
|
|
|
|
object->permitted_types,
|
|
|
|
&object->content);
|
|
|
|
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (page = c; page != NULL; page = page->page) {
|
|
|
|
page->base.active++;
|
|
|
|
page->base.status = CONTENT_STATUS_READY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* schedule() callback for object refresh
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void html_object_refresh(void *p)
|
|
|
|
{
|
|
|
|
struct content_html_object *object = p;
|
|
|
|
nsurl *refresh_url;
|
|
|
|
|
|
|
|
assert(content_get_type(object->content) == CONTENT_HTML);
|
|
|
|
|
|
|
|
refresh_url = content_get_refresh_url(object->content);
|
|
|
|
|
|
|
|
/* Ignore if refresh URL has gone
|
|
|
|
* (may happen if fetch errored) */
|
|
|
|
if (refresh_url == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
content_invalidate_reuse_data(object->content);
|
|
|
|
|
|
|
|
if (!html_replace_object(object, refresh_url)) {
|
|
|
|
/** \todo handle memory exhaustion */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void html_destroy_objects(html_content *html)
|
|
|
|
{
|
|
|
|
while (html->object_list != NULL) {
|
|
|
|
struct content_html_object *victim = html->object_list;
|
|
|
|
|
|
|
|
if (victim->content != NULL) {
|
|
|
|
LOG(("object %p", victim->content));
|
|
|
|
|
|
|
|
if (content_get_type(victim->content) == CONTENT_HTML)
|
|
|
|
schedule_remove(html_object_refresh, victim);
|
|
|
|
|
|
|
|
hlcache_handle_release(victim->content);
|
|
|
|
}
|
|
|
|
|
|
|
|
html->object_list = victim->next;
|
|
|
|
talloc_free(victim);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform post-box-creation conversion of a document
|
|
|
|
*
|
|
|
|
* \param c HTML content to complete conversion of
|
|
|
|
* \param success Whether box tree construction was successful
|
|
|
|
*/
|
|
|
|
static void html_box_convert_done(html_content *c, bool success)
|
|
|
|
{
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
dom_node *html;
|
|
|
|
|
|
|
|
LOG(("Done XML to box (%p)", c));
|
|
|
|
|
|
|
|
/* Clean up and report error if unsuccessful or aborted */
|
|
|
|
if ((success == false) || c->aborted) {
|
|
|
|
html_destroy_objects(c);
|
|
|
|
if (success == false)
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
else
|
|
|
|
msg_data.error = messages_get("Stopped");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ALWAYS_DUMP_BOX
|
|
|
|
box_dump(stderr, c->layout->children, 0);
|
|
|
|
#endif
|
|
|
|
#if ALWAYS_DUMP_FRAMESET
|
|
|
|
if (c->frameset)
|
|
|
|
html_dump_frameset(c->frameset, 0);
|
|
|
|
#endif
|
|
|
|
|
2012-03-25 02:26:44 +04:00
|
|
|
exc = dom_document_get_document_element(c->document, (void *) &html);
|
2012-03-24 21:11:17 +04:00
|
|
|
if ((exc != DOM_NO_ERR) || (html == NULL)) {
|
|
|
|
LOG(("error retrieving html element from dom"));
|
|
|
|
msg_data.error = messages_get("ParsingFail");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* extract image maps - can't do this sensibly in xml_to_box */
|
2012-03-25 19:07:08 +04:00
|
|
|
if (imagemap_extract(c) == false) {
|
2012-03-24 21:11:17 +04:00
|
|
|
LOG(("imagemap extraction failed"));
|
|
|
|
html_destroy_objects(c);
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*imagemap_dump(c);*/
|
|
|
|
|
|
|
|
/* Destroy the parser binding */
|
|
|
|
binding_destroy_tree(c->parser_binding);
|
|
|
|
c->parser_binding = NULL;
|
|
|
|
|
|
|
|
content_set_ready(&c->base);
|
|
|
|
|
|
|
|
if (c->base.active == 0)
|
|
|
|
content_set_done(&c->base);
|
|
|
|
|
|
|
|
html_set_status(c, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Complete conversion of an HTML document
|
|
|
|
*
|
|
|
|
* \param c Content to convert
|
|
|
|
*/
|
|
|
|
static void html_finish_conversion(html_content *c)
|
|
|
|
{
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
dom_node *html;
|
|
|
|
uint32_t i;
|
|
|
|
css_error error;
|
|
|
|
|
|
|
|
/* Bail out if we've been aborted */
|
|
|
|
if (c->aborted) {
|
|
|
|
msg_data.error = messages_get("Stopped");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check that the base stylesheet loaded; layout fails without it */
|
|
|
|
if (c->stylesheets[STYLESHEET_BASE].data.external == NULL) {
|
|
|
|
msg_data.error = "Base stylesheet failed to load";
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create selection context */
|
|
|
|
error = css_select_ctx_create(ns_realloc, c, &c->select_ctx);
|
|
|
|
if (error != CSS_OK) {
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add sheets to it */
|
|
|
|
for (i = STYLESHEET_BASE; i != c->stylesheet_count; i++) {
|
|
|
|
const struct html_stylesheet *hsheet = &c->stylesheets[i];
|
|
|
|
css_stylesheet *sheet;
|
|
|
|
css_origin origin = CSS_ORIGIN_AUTHOR;
|
|
|
|
|
|
|
|
if (i < STYLESHEET_USER)
|
|
|
|
origin = CSS_ORIGIN_UA;
|
|
|
|
else if (i < STYLESHEET_START)
|
|
|
|
origin = CSS_ORIGIN_USER;
|
|
|
|
|
|
|
|
if (hsheet->type == HTML_STYLESHEET_EXTERNAL &&
|
|
|
|
hsheet->data.external != NULL) {
|
|
|
|
sheet = nscss_get_stylesheet(hsheet->data.external);
|
|
|
|
} else if (hsheet->type == HTML_STYLESHEET_INTERNAL) {
|
|
|
|
sheet = hsheet->data.internal->sheet;
|
|
|
|
} else {
|
|
|
|
sheet = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sheet != NULL) {
|
|
|
|
error = css_select_ctx_append_sheet(
|
|
|
|
c->select_ctx, sheet,
|
|
|
|
origin, CSS_MEDIA_SCREEN);
|
|
|
|
if (error != CSS_OK) {
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR,
|
|
|
|
msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
2007-10-02 08:48:30 +04:00
|
|
|
}
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
|
|
|
}
|
2003-12-26 03:17:55 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* convert xml tree to box tree */
|
|
|
|
LOG(("XML to box (%p)", c));
|
|
|
|
content_set_status(&c->base, messages_get("Processing"));
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_STATUS, msg_data);
|
|
|
|
|
2012-03-25 02:26:44 +04:00
|
|
|
exc = dom_document_get_document_element(c->document, (void *) &html);
|
2012-03-24 21:11:17 +04:00
|
|
|
if ((exc != DOM_NO_ERR) || (html == NULL)) {
|
|
|
|
LOG(("error retrieving html element from dom"));
|
|
|
|
msg_data.error = messages_get("ParsingFail");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xml_to_box(html, c, html_box_convert_done) == false) {
|
|
|
|
html_destroy_objects(c);
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
content_set_error(&c->base);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2003-04-13 16:50:10 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/**
|
|
|
|
* Callback for fetchcache() for linked stylesheets.
|
|
|
|
*/
|
2003-04-13 16:50:10 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static nserror
|
|
|
|
html_convert_css_callback(hlcache_handle *css,
|
|
|
|
const hlcache_event *event,
|
|
|
|
void *pw)
|
|
|
|
{
|
|
|
|
html_content *parent = pw;
|
|
|
|
unsigned int i;
|
|
|
|
struct html_stylesheet *s;
|
2009-11-22 16:58:05 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Find sheet */
|
|
|
|
for (i = 0, s = parent->stylesheets;
|
|
|
|
i != parent->stylesheet_count; i++, s++) {
|
|
|
|
if (s->type == HTML_STYLESHEET_EXTERNAL &&
|
|
|
|
s->data.external == css)
|
|
|
|
break;
|
|
|
|
}
|
2009-02-10 21:35:56 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
assert(i != parent->stylesheet_count);
|
2009-02-10 21:35:56 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
switch (event->type) {
|
|
|
|
case CONTENT_MSG_LOADING:
|
|
|
|
break;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
case CONTENT_MSG_READY:
|
|
|
|
break;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
case CONTENT_MSG_DONE:
|
|
|
|
LOG(("got stylesheet '%s'",
|
|
|
|
nsurl_access(hlcache_handle_get_url(css))));
|
|
|
|
parent->base.active--;
|
|
|
|
break;
|
2009-02-10 21:35:56 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
case CONTENT_MSG_ERROR:
|
|
|
|
LOG(("stylesheet %s failed: %s",
|
|
|
|
nsurl_access(hlcache_handle_get_url(css)),
|
|
|
|
event->data.error));
|
|
|
|
hlcache_handle_release(css);
|
|
|
|
s->data.external = NULL;
|
|
|
|
parent->base.active--;
|
|
|
|
content_add_error(&parent->base, "?", 0);
|
|
|
|
break;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
case CONTENT_MSG_STATUS:
|
|
|
|
html_set_status(parent, content_get_status_message(css));
|
|
|
|
content_broadcast(&parent->base, CONTENT_MSG_STATUS,
|
|
|
|
event->data);
|
|
|
|
break;
|
2003-04-06 01:38:06 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
2003-04-13 16:50:10 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (parent->base.active == 0)
|
|
|
|
html_finish_conversion(parent);
|
2007-05-06 04:41:12 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
return NSERROR_OK;
|
2003-04-15 21:53:00 +04:00
|
|
|
}
|
|
|
|
|
2012-03-25 01:06:30 +04:00
|
|
|
/**
|
|
|
|
* Handle notification of inline style completion
|
|
|
|
*
|
|
|
|
* \param css Inline style object
|
|
|
|
* \param pw Private data
|
|
|
|
*/
|
|
|
|
static void html_inline_style_done(struct content_css_data *css, void *pw)
|
|
|
|
{
|
|
|
|
html_content *html = pw;
|
|
|
|
|
|
|
|
if (--html->base.active == 0)
|
|
|
|
html_finish_conversion(html);
|
|
|
|
}
|
|
|
|
|
2007-10-02 08:48:30 +04:00
|
|
|
/**
|
|
|
|
* Process an inline stylesheet in the document.
|
|
|
|
*
|
|
|
|
* \param c content structure
|
2009-07-24 05:48:53 +04:00
|
|
|
* \param index Index of stylesheet in stylesheet_content array,
|
|
|
|
* updated if successful
|
2007-10-02 08:48:30 +04:00
|
|
|
* \param style xml node of style element
|
|
|
|
* \return true on success, false if an error occurred
|
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool
|
|
|
|
html_process_style_element(html_content *c,
|
|
|
|
unsigned int *index,
|
|
|
|
dom_node *style)
|
2007-10-02 08:48:30 +04:00
|
|
|
{
|
2012-03-25 01:06:30 +04:00
|
|
|
dom_node *child, *next;
|
|
|
|
dom_string *val;
|
|
|
|
dom_exception exc;
|
2007-10-02 08:48:30 +04:00
|
|
|
union content_msg_data msg_data;
|
2010-03-28 16:56:39 +04:00
|
|
|
struct html_stylesheet *stylesheets;
|
|
|
|
struct content_css_data *sheet;
|
|
|
|
nserror error;
|
2007-10-02 08:48:30 +04:00
|
|
|
|
|
|
|
/* type='text/css', or not present (invalid but common) */
|
2012-03-25 01:06:30 +04:00
|
|
|
exc = dom_element_get_attribute(style, html_dom_string_type, &val);
|
|
|
|
if (exc == DOM_NO_ERR && val != NULL) {
|
|
|
|
if (strcmp(dom_string_data(val), "text/css") != 0) {
|
|
|
|
dom_string_unref(val);
|
2007-10-02 08:48:30 +04:00
|
|
|
return true;
|
|
|
|
}
|
2012-03-25 01:06:30 +04:00
|
|
|
dom_string_unref(val);
|
2007-10-02 08:48:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* media contains 'screen' or 'all' or not present */
|
2012-03-25 01:06:30 +04:00
|
|
|
exc = dom_element_get_attribute(style, html_dom_string_media, &val);
|
|
|
|
if (exc == DOM_NO_ERR && val != NULL) {
|
|
|
|
if (strcasestr(dom_string_data(val), "screen") == NULL &&
|
|
|
|
strcasestr(dom_string_data(val),
|
|
|
|
"all") == NULL) {
|
|
|
|
dom_string_unref(val);
|
2007-10-02 08:48:30 +04:00
|
|
|
return true;
|
|
|
|
}
|
2012-03-25 01:06:30 +04:00
|
|
|
dom_string_unref(val);
|
2007-10-02 08:48:30 +04:00
|
|
|
}
|
|
|
|
|
2009-07-24 03:05:34 +04:00
|
|
|
/* Extend array */
|
2011-05-07 00:40:09 +04:00
|
|
|
stylesheets = talloc_realloc(c, c->stylesheets,
|
2010-03-28 16:56:39 +04:00
|
|
|
struct html_stylesheet, *index + 1);
|
2009-07-27 17:49:10 +04:00
|
|
|
if (stylesheets == NULL)
|
2009-07-24 03:05:34 +04:00
|
|
|
goto no_memory;
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
c->stylesheets = stylesheets;
|
|
|
|
c->stylesheet_count++;
|
2009-07-24 03:05:34 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
c->stylesheets[(*index)].type = HTML_STYLESHEET_INTERNAL;
|
|
|
|
c->stylesheets[(*index)].data.internal = NULL;
|
2009-07-27 22:32:55 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
/* create stylesheet */
|
|
|
|
sheet = talloc(c, struct content_css_data);
|
|
|
|
if (sheet == NULL) {
|
2011-05-07 00:40:09 +04:00
|
|
|
c->stylesheet_count--;
|
2009-07-24 03:05:34 +04:00
|
|
|
goto no_memory;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
2009-07-24 05:48:53 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
error = nscss_create_css_data(sheet,
|
2011-10-03 19:56:47 +04:00
|
|
|
nsurl_access(c->base_url), NULL, c->quirks,
|
2011-02-26 03:58:54 +03:00
|
|
|
html_inline_style_done, c);
|
2010-03-28 16:56:39 +04:00
|
|
|
if (error != NSERROR_OK) {
|
2012-03-25 01:06:30 +04:00
|
|
|
talloc_free(sheet);
|
2011-05-07 00:40:09 +04:00
|
|
|
c->stylesheet_count--;
|
2009-07-24 03:05:34 +04:00
|
|
|
goto no_memory;
|
2009-07-27 22:32:55 +04:00
|
|
|
}
|
2007-10-02 08:48:30 +04:00
|
|
|
|
|
|
|
/* can't just use xmlNodeGetContent(style), because that won't
|
|
|
|
* give the content of comments which may be used to 'hide'
|
|
|
|
* the content */
|
2012-03-25 01:06:30 +04:00
|
|
|
exc = dom_node_get_first_child(style, &child);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
nscss_destroy_css_data(sheet);
|
|
|
|
talloc_free(sheet);
|
|
|
|
c->stylesheet_count--;
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (child != NULL) {
|
|
|
|
dom_string *data;
|
|
|
|
|
|
|
|
exc = dom_node_get_text_content(child, &data);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(child);
|
|
|
|
nscss_destroy_css_data(sheet);
|
|
|
|
talloc_free(sheet);
|
|
|
|
c->stylesheet_count--;
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nscss_process_css_data(sheet, dom_string_data(data),
|
|
|
|
dom_string_byte_length(data)) == false) {
|
|
|
|
dom_string_unref(data);
|
|
|
|
dom_node_unref(child);
|
|
|
|
nscss_destroy_css_data(sheet);
|
|
|
|
talloc_free(sheet);
|
|
|
|
c->stylesheet_count--;
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom_string_unref(data);
|
|
|
|
|
|
|
|
exc = dom_node_get_next_sibling(child, &next);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(child);
|
2010-03-28 16:56:39 +04:00
|
|
|
nscss_destroy_css_data(sheet);
|
|
|
|
talloc_free(sheet);
|
2011-05-07 00:40:09 +04:00
|
|
|
c->stylesheet_count--;
|
2007-10-02 08:48:30 +04:00
|
|
|
goto no_memory;
|
|
|
|
}
|
2012-03-25 01:06:30 +04:00
|
|
|
|
|
|
|
dom_node_unref(child);
|
|
|
|
child = next;
|
2007-10-02 08:48:30 +04:00
|
|
|
}
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
c->base.active++;
|
2010-04-11 14:52:18 +04:00
|
|
|
|
2009-07-27 22:32:55 +04:00
|
|
|
/* Convert the content -- manually, as we want the result */
|
2011-02-26 03:58:54 +03:00
|
|
|
if (nscss_convert_css_data(sheet) != CSS_OK) {
|
2009-07-24 03:05:34 +04:00
|
|
|
/* conversion failed */
|
2011-05-07 00:40:09 +04:00
|
|
|
c->base.active--;
|
2010-03-28 16:56:39 +04:00
|
|
|
nscss_destroy_css_data(sheet);
|
|
|
|
talloc_free(sheet);
|
|
|
|
sheet = NULL;
|
2009-07-24 03:05:34 +04:00
|
|
|
}
|
|
|
|
|
2009-07-24 05:48:53 +04:00
|
|
|
/* Update index */
|
2011-05-07 00:40:09 +04:00
|
|
|
c->stylesheets[(*index)].data.internal = sheet;
|
2009-07-24 05:48:53 +04:00
|
|
|
(*index)++;
|
|
|
|
|
2007-10-02 08:48:30 +04:00
|
|
|
return true;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
2011-05-07 00:40:09 +04:00
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
2007-10-02 08:48:30 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-04-11 14:52:18 +04:00
|
|
|
/**
|
2012-03-24 21:11:17 +04:00
|
|
|
* Process inline stylesheets and fetch linked stylesheets.
|
2010-04-11 14:52:18 +04:00
|
|
|
*
|
2012-03-24 21:11:17 +04:00
|
|
|
* Uses STYLE and LINK elements inside and outside HEAD
|
|
|
|
*
|
|
|
|
* \param c content structure
|
|
|
|
* \param html xml node of html element
|
|
|
|
* \return true on success, false if an error occurred
|
2004-02-20 03:43:17 +03:00
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool html_find_stylesheets(html_content *c, dom_node *html)
|
2004-02-20 03:43:17 +03:00
|
|
|
{
|
2012-03-24 21:11:17 +04:00
|
|
|
content_type accept = CONTENT_CSS;
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_node *node;
|
2012-03-24 21:11:17 +04:00
|
|
|
unsigned int i = STYLESHEET_START;
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
struct html_stylesheet *stylesheets;
|
|
|
|
hlcache_child_context child;
|
|
|
|
nserror ns_error;
|
|
|
|
nsurl *joined;
|
2010-04-11 14:52:18 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
child.charset = c->encoding;
|
|
|
|
child.quirks = c->base.quirks;
|
2004-02-20 03:43:17 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* stylesheet 0 is the base style sheet,
|
|
|
|
* stylesheet 1 is the quirks mode style sheet,
|
|
|
|
* stylesheet 2 is the adblocking stylesheet,
|
|
|
|
* stylesheet 3 is the user stylesheet */
|
|
|
|
c->stylesheets = talloc_array(c, struct html_stylesheet,
|
|
|
|
STYLESHEET_START);
|
|
|
|
if (c->stylesheets == NULL)
|
|
|
|
goto no_memory;
|
|
|
|
c->stylesheets[STYLESHEET_BASE].type = HTML_STYLESHEET_EXTERNAL;
|
|
|
|
c->stylesheets[STYLESHEET_BASE].data.external = NULL;
|
|
|
|
c->stylesheets[STYLESHEET_QUIRKS].type = HTML_STYLESHEET_EXTERNAL;
|
|
|
|
c->stylesheets[STYLESHEET_QUIRKS].data.external = NULL;
|
|
|
|
c->stylesheets[STYLESHEET_ADBLOCK].type = HTML_STYLESHEET_EXTERNAL;
|
|
|
|
c->stylesheets[STYLESHEET_ADBLOCK].data.external = NULL;
|
|
|
|
c->stylesheets[STYLESHEET_USER].type = HTML_STYLESHEET_EXTERNAL;
|
|
|
|
c->stylesheets[STYLESHEET_USER].data.external = NULL;
|
|
|
|
c->stylesheet_count = STYLESHEET_START;
|
2004-02-20 03:43:17 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
c->base.active = 0;
|
2004-02-20 03:43:17 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
ns_error = hlcache_handle_retrieve(html_default_stylesheet_url, 0,
|
|
|
|
content_get_url(&c->base), NULL,
|
|
|
|
html_convert_css_callback, c, &child, accept,
|
|
|
|
&c->stylesheets[STYLESHEET_BASE].data.external);
|
|
|
|
if (ns_error != NSERROR_OK)
|
|
|
|
goto no_memory;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
c->base.active++;
|
2011-07-21 00:16:01 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (c->quirks == BINDING_QUIRKS_MODE_FULL) {
|
|
|
|
ns_error = hlcache_handle_retrieve(html_quirks_stylesheet_url,
|
|
|
|
0, content_get_url(&c->base), NULL,
|
|
|
|
html_convert_css_callback, c, &child, accept,
|
|
|
|
&c->stylesheets[STYLESHEET_QUIRKS].
|
|
|
|
data.external);
|
|
|
|
if (ns_error != NSERROR_OK)
|
|
|
|
goto no_memory;
|
2011-10-04 00:38:23 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
c->base.active++;
|
2011-03-11 02:08:34 +03:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (nsoption_bool(block_ads)) {
|
|
|
|
ns_error = hlcache_handle_retrieve(html_adblock_stylesheet_url,
|
|
|
|
0, content_get_url(&c->base), NULL,
|
|
|
|
html_convert_css_callback, c, &child, accept,
|
|
|
|
&c->stylesheets[STYLESHEET_ADBLOCK].
|
|
|
|
data.external);
|
|
|
|
if (ns_error != NSERROR_OK)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
c->base.active++;
|
2011-10-03 12:51:57 +04:00
|
|
|
}
|
2011-03-11 02:08:34 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
ns_error = hlcache_handle_retrieve(html_user_stylesheet_url, 0,
|
|
|
|
content_get_url(&c->base), NULL,
|
|
|
|
html_convert_css_callback, c, &child, accept,
|
|
|
|
&c->stylesheets[STYLESHEET_USER].data.external);
|
|
|
|
if (ns_error != NSERROR_OK)
|
|
|
|
goto no_memory;
|
2011-10-03 19:56:47 +04:00
|
|
|
|
2011-10-04 00:38:23 +04:00
|
|
|
c->base.active++;
|
2011-09-29 23:15:54 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* depth-first search the tree for link elements */
|
2012-03-24 23:35:59 +04:00
|
|
|
|
|
|
|
node = dom_node_ref(html); /* tree root */
|
|
|
|
|
|
|
|
while (node != NULL) {
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_node *next = NULL;
|
|
|
|
dom_node_type type;
|
|
|
|
dom_string *name;
|
|
|
|
dom_exception exc;
|
|
|
|
|
|
|
|
exc = dom_node_get_first_child(node, &next);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(node);
|
2012-03-24 23:35:59 +04:00
|
|
|
break;
|
2012-03-25 00:43:19 +04:00
|
|
|
}
|
2012-03-24 23:35:59 +04:00
|
|
|
|
2012-03-25 00:43:19 +04:00
|
|
|
if (next != NULL) { /* 1. children */
|
|
|
|
dom_node_unref(node);
|
|
|
|
node = next;
|
|
|
|
} else {
|
|
|
|
exc = dom_node_get_next_sibling(node, &next);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(node);
|
2012-03-24 21:11:17 +04:00
|
|
|
break;
|
2012-03-25 00:43:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (next != NULL) { /* 2. siblings */
|
|
|
|
dom_node_unref(node);
|
|
|
|
node = next;
|
|
|
|
} else { /* 3. ancestor siblings */
|
|
|
|
while (node != NULL) {
|
|
|
|
exc = dom_node_get_next_sibling(node,
|
|
|
|
&next);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(node);
|
|
|
|
node = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (next != NULL) {
|
|
|
|
dom_node_unref(next);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
exc = dom_node_get_parent_node(node,
|
|
|
|
&next);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(node);
|
|
|
|
node = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom_node_unref(node);
|
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
exc = dom_node_get_next_sibling(node, &next);
|
|
|
|
if (exc != DOM_NO_ERR) {
|
|
|
|
dom_node_unref(node);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
dom_node_unref(node);
|
|
|
|
node = next;
|
|
|
|
}
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
2005-10-31 00:23:03 +03:00
|
|
|
|
2012-03-25 00:43:19 +04:00
|
|
|
assert(node != NULL);
|
2005-10-31 00:23:03 +03:00
|
|
|
|
2012-03-25 00:43:19 +04:00
|
|
|
exc = dom_node_get_node_type(node, &type);
|
2012-03-25 00:48:02 +04:00
|
|
|
if (exc != DOM_NO_ERR || type != DOM_ELEMENT_NODE)
|
2012-03-25 00:43:19 +04:00
|
|
|
continue;
|
|
|
|
|
|
|
|
exc = dom_node_get_node_name(node, &name);
|
|
|
|
if (exc != DOM_NO_ERR)
|
2012-03-24 21:11:17 +04:00
|
|
|
continue;
|
2011-03-11 02:08:34 +03:00
|
|
|
|
2012-03-25 00:43:19 +04:00
|
|
|
if (strcmp(dom_string_data(name), "link") == 0) {
|
|
|
|
dom_string *rel, *type_attr, *media, *href;
|
|
|
|
|
|
|
|
dom_string_unref(name);
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* rel=<space separated list, including 'stylesheet'> */
|
2012-03-25 00:43:19 +04:00
|
|
|
exc = dom_element_get_attribute(node,
|
|
|
|
html_dom_string_rel, &rel);
|
|
|
|
if (exc != DOM_NO_ERR || rel == NULL)
|
2012-03-24 21:11:17 +04:00
|
|
|
continue;
|
2012-03-25 00:43:19 +04:00
|
|
|
|
|
|
|
if (strcasestr(dom_string_data(rel),
|
|
|
|
"stylesheet") == 0) {
|
|
|
|
dom_string_unref(rel);
|
2012-03-24 21:11:17 +04:00
|
|
|
continue;
|
2012-03-25 00:43:19 +04:00
|
|
|
} else if (strcasestr(dom_string_data(rel),
|
|
|
|
"alternate") != 0) {
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Ignore alternate stylesheets */
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_string_unref(rel);
|
2012-03-24 21:11:17 +04:00
|
|
|
continue;
|
|
|
|
}
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_string_unref(rel);
|
|
|
|
|
|
|
|
/* type='text/css' or not present */
|
|
|
|
exc = dom_element_get_attribute(node,
|
|
|
|
html_dom_string_type, &type_attr);
|
|
|
|
if (exc == DOM_NO_ERR && type_attr != NULL) {
|
|
|
|
if (strcmp(dom_string_data(type_attr),
|
|
|
|
"text/css") != 0) {
|
|
|
|
dom_string_unref(type_attr);
|
2012-03-24 21:11:17 +04:00
|
|
|
continue;
|
|
|
|
}
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_string_unref(type_attr);
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* media contains 'screen' or 'all' or not present */
|
2012-03-25 00:43:19 +04:00
|
|
|
exc = dom_element_get_attribute(node,
|
|
|
|
html_dom_string_media, &media);
|
|
|
|
if (exc == DOM_NO_ERR && media != NULL) {
|
|
|
|
if (strcasestr(dom_string_data(media),
|
|
|
|
"screen") == NULL &&
|
|
|
|
strcasestr(
|
|
|
|
dom_string_data(media),
|
|
|
|
"all") == NULL) {
|
|
|
|
dom_string_unref(media);
|
2012-03-24 21:11:17 +04:00
|
|
|
continue;
|
|
|
|
}
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_string_unref(media);
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
2011-03-11 02:08:34 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* href='...' */
|
2012-03-25 00:43:19 +04:00
|
|
|
exc = dom_element_get_attribute(node,
|
|
|
|
html_dom_string_href, &href);
|
|
|
|
if (exc != DOM_NO_ERR || href == NULL)
|
2012-03-24 21:11:17 +04:00
|
|
|
continue;
|
2011-03-11 02:08:34 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* TODO: only the first preferred stylesheets (ie.
|
|
|
|
* those with a title attribute) should be loaded
|
|
|
|
* (see HTML4 14.3) */
|
2005-10-31 00:23:03 +03:00
|
|
|
|
2012-03-25 00:43:19 +04:00
|
|
|
ns_error = nsurl_join(c->base_url,
|
|
|
|
dom_string_data(href), &joined);
|
2012-03-24 21:11:17 +04:00
|
|
|
if (ns_error != NSERROR_OK) {
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_string_unref(href);
|
2012-03-24 21:11:17 +04:00
|
|
|
goto no_memory;
|
|
|
|
}
|
2012-03-25 00:43:19 +04:00
|
|
|
dom_string_unref(href);
|
2009-02-10 21:35:56 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
LOG(("linked stylesheet %i '%s'", i,
|
|
|
|
nsurl_access(joined)));
|
2005-10-31 00:23:03 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* start fetch */
|
|
|
|
stylesheets = talloc_realloc(c,
|
|
|
|
c->stylesheets,
|
|
|
|
struct html_stylesheet, i + 1);
|
|
|
|
if (stylesheets == NULL) {
|
|
|
|
nsurl_unref(joined);
|
|
|
|
goto no_memory;
|
|
|
|
}
|
|
|
|
|
|
|
|
c->stylesheets = stylesheets;
|
|
|
|
c->stylesheet_count++;
|
|
|
|
c->stylesheets[i].type = HTML_STYLESHEET_EXTERNAL;
|
|
|
|
ns_error = hlcache_handle_retrieve(joined, 0,
|
|
|
|
content_get_url(&c->base), NULL,
|
|
|
|
html_convert_css_callback, c, &child,
|
|
|
|
accept,
|
|
|
|
&c->stylesheets[i].data.external);
|
|
|
|
|
|
|
|
nsurl_unref(joined);
|
|
|
|
|
|
|
|
if (ns_error != NSERROR_OK)
|
|
|
|
goto no_memory;
|
|
|
|
|
|
|
|
c->base.active++;
|
|
|
|
|
|
|
|
i++;
|
2012-03-25 00:43:19 +04:00
|
|
|
} else if (strcmp(dom_string_data(name), "style") == 0) {
|
|
|
|
dom_string_unref(name);
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (!html_process_style_element(c, &i, node))
|
|
|
|
return false;
|
2012-03-25 00:43:19 +04:00
|
|
|
} else {
|
|
|
|
dom_string_unref(name);
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
2005-10-31 00:23:03 +03:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
assert(c->stylesheet_count == i);
|
|
|
|
|
2005-10-31 00:23:03 +03:00
|
|
|
return true;
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
no_memory:
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
2005-10-31 00:23:03 +03:00
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
/**
|
2012-03-24 21:11:17 +04:00
|
|
|
* Convert a CONTENT_HTML for display.
|
|
|
|
*
|
|
|
|
* The following steps are carried out in order:
|
|
|
|
*
|
|
|
|
* - parsing to an XML tree is completed
|
|
|
|
* - stylesheets are fetched
|
|
|
|
* - the XML tree is converted to a box tree and object fetches are started
|
|
|
|
*
|
|
|
|
* On exit, the content status will be either CONTENT_STATUS_DONE if the
|
|
|
|
* document is completely loaded or CONTENT_STATUS_READY if objects are still
|
|
|
|
* being fetched.
|
2004-02-20 03:43:17 +03:00
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool html_convert(struct content *c)
|
2003-04-15 21:53:00 +04:00
|
|
|
{
|
2012-03-24 21:11:17 +04:00
|
|
|
html_content *htmlc = (html_content *) c;
|
|
|
|
binding_error err;
|
|
|
|
dom_node *html, *head;
|
|
|
|
union content_msg_data msg_data;
|
|
|
|
unsigned long size;
|
|
|
|
struct form *f;
|
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
dom_string *node_name = NULL;
|
2004-01-24 20:08:16 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* finish parsing */
|
|
|
|
content__get_source_data(c, &size);
|
|
|
|
if (size == 0) {
|
|
|
|
/* Destroy current binding */
|
|
|
|
binding_destroy_tree(htmlc->parser_binding);
|
2011-07-19 17:43:48 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Also, any existing encoding information,
|
|
|
|
* as it's not guaranteed to match the error page.
|
|
|
|
*/
|
|
|
|
talloc_free(htmlc->encoding);
|
|
|
|
htmlc->encoding = NULL;
|
2003-06-17 23:24:21 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Create new binding, using default charset */
|
|
|
|
err = binding_create_tree(c, NULL, &htmlc->parser_binding);
|
|
|
|
if (err != BINDING_OK) {
|
|
|
|
union content_msg_data msg_data;
|
2003-10-25 23:20:13 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (err == BINDING_BADENCODING) {
|
|
|
|
LOG(("Bad encoding: %s", htmlc->encoding
|
|
|
|
? htmlc->encoding : ""));
|
|
|
|
msg_data.error = messages_get("ParsingFail");
|
|
|
|
} else
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Process the error page */
|
|
|
|
if (html_process_data(c, (char *) empty_document,
|
|
|
|
SLEN(empty_document)) == false)
|
|
|
|
return false;
|
|
|
|
}
|
2011-04-27 17:50:49 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
err = binding_parse_completed(htmlc->parser_binding);
|
|
|
|
if (err != BINDING_OK) {
|
|
|
|
union content_msg_data msg_data;
|
2011-04-27 17:50:49 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
2011-04-27 17:50:49 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
return false;
|
|
|
|
}
|
2011-04-27 17:50:49 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
htmlc->document = binding_get_document(htmlc->parser_binding,
|
|
|
|
&htmlc->quirks);
|
|
|
|
/*xmlDebugDumpDocument(stderr, htmlc->document);*/
|
|
|
|
|
|
|
|
if (htmlc->document == NULL) {
|
|
|
|
LOG(("Parsing failed"));
|
|
|
|
msg_data.error = messages_get("ParsingFail");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (htmlc->encoding == NULL) {
|
|
|
|
const char *encoding = binding_get_encoding(
|
|
|
|
htmlc->parser_binding,
|
|
|
|
&htmlc->encoding_source);
|
2011-04-27 17:50:49 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
htmlc->encoding = talloc_strdup(c, encoding);
|
|
|
|
if (htmlc->encoding == NULL) {
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
2011-04-27 17:50:49 +04:00
|
|
|
}
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Give up processing if we've been aborted */
|
|
|
|
if (htmlc->aborted) {
|
|
|
|
msg_data.error = messages_get("Stopped");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* locate html and head elements */
|
2012-03-25 02:26:44 +04:00
|
|
|
exc = dom_document_get_document_element(htmlc->document, (void *) &html);
|
2012-03-24 21:11:17 +04:00
|
|
|
if ((exc != DOM_NO_ERR) || (html == NULL)) {
|
|
|
|
LOG(("error retrieving html element from dom"));
|
|
|
|
msg_data.error = messages_get("ParsingFail");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
exc = dom_node_get_node_name(html, &node_name);
|
|
|
|
if ((exc != DOM_NO_ERR) ||
|
|
|
|
(node_name == NULL) ||
|
|
|
|
(!dom_string_caseless_isequal(node_name, html_dom_string_html))) {
|
|
|
|
LOG(("html element not found"));
|
|
|
|
msg_data.error = messages_get("ParsingFail");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
dom_string_unref(node_name);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
exc = dom_node_get_first_child(html, &head);
|
|
|
|
if ((exc != DOM_NO_ERR) || (head == NULL)) {
|
|
|
|
head = NULL;
|
|
|
|
LOG(("head element not found"));
|
|
|
|
} else {
|
|
|
|
dom_node_type node_type;
|
|
|
|
dom_node *next_node;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* find first node thats a element */
|
|
|
|
do {
|
|
|
|
exc = dom_node_get_node_type(head, &node_type);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if ((exc != DOM_NO_ERR) ||
|
|
|
|
(node_type == DOM_ELEMENT_NODE))
|
|
|
|
break;
|
2006-02-23 18:06:54 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
exc = dom_node_get_next_sibling(head, &next_node);
|
|
|
|
dom_node_unref(head);
|
|
|
|
if (exc == DOM_NO_ERR) {
|
|
|
|
head = next_node;
|
|
|
|
} else {
|
|
|
|
head = NULL;
|
|
|
|
}
|
|
|
|
} while (head != NULL);
|
|
|
|
|
|
|
|
if (head != NULL) {
|
|
|
|
exc = dom_node_get_node_name(head, &node_name);
|
|
|
|
if ((exc == DOM_NO_ERR) || (node_name != NULL)) {
|
|
|
|
if (!dom_string_caseless_isequal(node_name,
|
|
|
|
html_dom_string_head)) {
|
|
|
|
dom_node_unref(head);
|
|
|
|
LOG(("head element not found"));
|
|
|
|
head = NULL;
|
|
|
|
}
|
|
|
|
dom_string_unref(node_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (head != NULL) {
|
|
|
|
if (html_head(htmlc, head) == false) {
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* handle meta refresh */
|
|
|
|
if (html_meta_refresh(htmlc, head) == false)
|
|
|
|
return false;
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Retrieve forms from parser */
|
|
|
|
htmlc->forms = binding_get_forms(htmlc->parser_binding);
|
|
|
|
for (f = htmlc->forms; f != NULL; f = f->prev) {
|
|
|
|
char *action;
|
|
|
|
url_func_result res;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* Make all actions absolute */
|
|
|
|
if (f->action == NULL || f->action[0] == '\0') {
|
|
|
|
/* HTML5 4.10.22.3 step 11 */
|
|
|
|
res = url_join(nsurl_access(content_get_url(c)),
|
|
|
|
nsurl_access(htmlc->base_url), &action);
|
|
|
|
} else {
|
|
|
|
res = url_join(f->action, nsurl_access(htmlc->base_url),
|
|
|
|
&action);
|
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (res != URL_FUNC_OK) {
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
|
|
|
|
return false;
|
2011-10-04 00:38:23 +04:00
|
|
|
}
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
free(f->action);
|
|
|
|
f->action = action;
|
|
|
|
|
|
|
|
/* Ensure each form has a document encoding */
|
|
|
|
if (f->document_charset == NULL) {
|
|
|
|
f->document_charset = strdup(htmlc->encoding);
|
|
|
|
if (f->document_charset == NULL) {
|
|
|
|
msg_data.error = messages_get("NoMemory");
|
|
|
|
content_broadcast(c, CONTENT_MSG_ERROR,
|
|
|
|
msg_data);
|
|
|
|
return false;
|
|
|
|
}
|
2011-03-11 02:08:34 +03:00
|
|
|
}
|
2012-03-24 21:11:17 +04:00
|
|
|
}
|
2011-03-11 02:08:34 +03:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* get stylesheets */
|
|
|
|
if (html_find_stylesheets(htmlc, html) == false)
|
|
|
|
return false;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
return true;
|
|
|
|
}
|
2011-12-02 19:08:25 +04:00
|
|
|
|
2003-06-17 23:24:21 +04:00
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
|
2004-05-21 18:26:59 +04:00
|
|
|
/**
|
2012-03-24 21:11:17 +04:00
|
|
|
* Start a fetch for an object required by a page.
|
|
|
|
*
|
|
|
|
* \param c content of type CONTENT_HTML
|
|
|
|
* \param url URL of object to fetch (copied)
|
|
|
|
* \param box box that will contain the object
|
|
|
|
* \param permitted_types bitmap of acceptable types
|
|
|
|
* \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
|
2004-05-21 18:26:59 +04:00
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
bool html_fetch_object(html_content *c, nsurl *url, struct box *box,
|
|
|
|
content_type permitted_types,
|
|
|
|
int available_width, int available_height,
|
|
|
|
bool background)
|
2004-05-21 18:26:59 +04:00
|
|
|
{
|
2012-03-24 21:11:17 +04:00
|
|
|
struct content_html_object *object;
|
|
|
|
hlcache_child_context child;
|
|
|
|
nserror error;
|
2004-05-21 18:26:59 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* If we've already been aborted, don't bother attempting the fetch */
|
|
|
|
if (c->aborted)
|
|
|
|
return true;
|
2004-06-25 03:29:31 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
child.charset = c->encoding;
|
|
|
|
child.quirks = c->base.quirks;
|
2004-05-21 18:26:59 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
object = talloc(c, struct content_html_object);
|
|
|
|
if (object == NULL) {
|
|
|
|
return false;
|
|
|
|
}
|
2004-05-21 18:26:59 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
object->parent = (struct content *) c;
|
|
|
|
object->next = NULL;
|
|
|
|
object->content = NULL;
|
|
|
|
object->box = box;
|
|
|
|
object->permitted_types = permitted_types;
|
|
|
|
object->background = background;
|
|
|
|
|
|
|
|
error = hlcache_handle_retrieve(url,
|
|
|
|
HLCACHE_RETRIEVE_SNIFF_TYPE,
|
|
|
|
content_get_url(&c->base), NULL,
|
|
|
|
html_object_callback, object, &child,
|
|
|
|
object->permitted_types, &object->content);
|
|
|
|
if (error != NSERROR_OK) {
|
|
|
|
talloc_free(object);
|
|
|
|
return error != NSERROR_NOMEM;
|
2004-05-21 18:26:59 +04:00
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
/* add to content object list */
|
|
|
|
object->next = c->object_list;
|
|
|
|
c->object_list = object;
|
2004-05-21 18:26:59 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
c->num_objects++;
|
|
|
|
c->base.active++;
|
2005-04-14 01:58:28 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
return true;
|
2005-04-14 01:58:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-01-25 09:52:38 +03:00
|
|
|
|
|
|
|
|
2011-02-16 00:49:28 +03:00
|
|
|
|
2008-02-27 21:38:41 +03:00
|
|
|
|
2006-01-25 09:52:38 +03:00
|
|
|
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
|
|
|
|
|
2006-01-25 09:52:38 +03:00
|
|
|
|
2004-06-21 03:09:52 +04:00
|
|
|
/**
|
2011-07-20 00:23:59 +04:00
|
|
|
* Stop loading a CONTENT_HTML.
|
2004-06-21 03:09:52 +04:00
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void html_stop(struct content *c)
|
2004-06-21 03:09:52 +04:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *htmlc = (html_content *) c;
|
2011-03-11 02:08:34 +03:00
|
|
|
struct content_html_object *object;
|
2004-06-21 03:09:52 +04:00
|
|
|
|
2011-07-20 00:23:59 +04:00
|
|
|
switch (c->status) {
|
|
|
|
case CONTENT_STATUS_LOADING:
|
|
|
|
/* Still loading; simply flag that we've been aborted
|
|
|
|
* html_convert/html_finish_conversion will do the rest */
|
|
|
|
htmlc->aborted = true;
|
|
|
|
break;
|
|
|
|
case CONTENT_STATUS_READY:
|
|
|
|
for (object = htmlc->object_list; object != NULL;
|
|
|
|
object = object->next) {
|
|
|
|
if (object->content == NULL)
|
|
|
|
continue;
|
2004-06-21 03:09:52 +04:00
|
|
|
|
2011-07-20 00:23:59 +04:00
|
|
|
if (content_get_status(object->content) ==
|
|
|
|
CONTENT_STATUS_DONE)
|
|
|
|
; /* already loaded: do nothing */
|
|
|
|
else if (content_get_status(object->content) ==
|
|
|
|
CONTENT_STATUS_READY)
|
|
|
|
hlcache_handle_abort(object->content);
|
2011-07-20 03:08:55 +04:00
|
|
|
/* Active count will be updated when
|
|
|
|
* html_object_callback receives
|
|
|
|
* CONTENT_MSG_DONE from this object */
|
2011-07-20 00:23:59 +04:00
|
|
|
else {
|
2011-07-20 03:08:55 +04:00
|
|
|
hlcache_handle_abort(object->content);
|
2011-07-20 00:23:59 +04:00
|
|
|
hlcache_handle_release(object->content);
|
|
|
|
object->content = NULL;
|
2011-07-20 03:08:55 +04:00
|
|
|
|
|
|
|
c->active--;
|
2011-07-20 00:23:59 +04:00
|
|
|
}
|
2004-06-21 03:09:52 +04:00
|
|
|
}
|
2011-07-20 03:08:55 +04:00
|
|
|
|
|
|
|
/* If there are no further active fetches and we're still
|
|
|
|
* in the READY state, transition to the DONE state. */
|
|
|
|
if (c->status == CONTENT_STATUS_READY && c->active == 0) {
|
|
|
|
html_set_status(htmlc, "");
|
|
|
|
content_set_done(c);
|
|
|
|
}
|
|
|
|
|
2011-07-20 00:23:59 +04:00
|
|
|
break;
|
|
|
|
case CONTENT_STATUS_DONE:
|
|
|
|
/* Nothing to do */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG(("Unexpected status %d", c->status));
|
|
|
|
assert(0);
|
2004-06-21 03:09:52 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
/**
|
|
|
|
* Reformat a CONTENT_HTML to a new width.
|
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void html_reformat(struct content *c, int width, int height)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *htmlc = (html_content *) c;
|
2006-09-17 01:33:55 +04:00
|
|
|
struct box *layout;
|
2010-03-30 02:33:21 +04:00
|
|
|
unsigned int time_before, time_taken;
|
|
|
|
|
|
|
|
time_before = wallclock();
|
2006-06-29 23:55:08 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
layout_document(htmlc, width, height);
|
|
|
|
layout = htmlc->layout;
|
2006-09-17 01:33:55 +04:00
|
|
|
|
|
|
|
/* width and height are at least margin box of document */
|
|
|
|
c->width = layout->x + layout->padding[LEFT] + layout->width +
|
2009-07-24 03:05:34 +04:00
|
|
|
layout->padding[RIGHT] + layout->border[RIGHT].width +
|
2006-09-17 01:33:55 +04:00
|
|
|
layout->margin[RIGHT];
|
|
|
|
c->height = layout->y + layout->padding[TOP] + layout->height +
|
2009-07-24 03:05:34 +04:00
|
|
|
layout->padding[BOTTOM] + layout->border[BOTTOM].width +
|
2006-09-17 01:33:55 +04:00
|
|
|
layout->margin[BOTTOM];
|
|
|
|
|
|
|
|
/* if boxes overflow right or bottom edge, expand to contain it */
|
|
|
|
if (c->width < layout->x + layout->descendant_x1)
|
|
|
|
c->width = layout->x + layout->descendant_x1;
|
|
|
|
if (c->height < layout->y + layout->descendant_y1)
|
|
|
|
c->height = layout->y + layout->descendant_y1;
|
2010-03-30 02:33:21 +04:00
|
|
|
|
2011-07-13 17:20:26 +04:00
|
|
|
selection_reinit(&htmlc->sel, htmlc->layout);
|
|
|
|
|
2010-03-30 02:33:21 +04:00
|
|
|
time_taken = wallclock() - time_before;
|
|
|
|
c->reformat_time = wallclock() +
|
2012-03-22 13:34:34 +04:00
|
|
|
((time_taken * 3 < nsoption_int(min_reflow_period) ?
|
|
|
|
nsoption_int(min_reflow_period) : time_taken * 3));
|
2003-02-09 15:58:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-04 13:35:08 +04:00
|
|
|
/**
|
|
|
|
* Redraw a box.
|
|
|
|
*
|
2010-11-03 18:44:01 +03:00
|
|
|
* \param h content containing the box, of type CONTENT_HTML
|
2010-06-04 13:35:08 +04:00
|
|
|
* \param box box to redraw
|
|
|
|
*/
|
|
|
|
|
|
|
|
void html_redraw_a_box(hlcache_handle *h, struct box *box)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
box_coords(box, &x, &y);
|
|
|
|
|
|
|
|
content_request_redraw(h, x, y,
|
|
|
|
box->padding[LEFT] + box->width + box->padding[RIGHT],
|
|
|
|
box->padding[TOP] + box->height + box->padding[BOTTOM]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-07 21:50:04 +04:00
|
|
|
/**
|
|
|
|
* Redraw a box.
|
|
|
|
*
|
|
|
|
* \param h content containing the box, of type CONTENT_HTML
|
|
|
|
* \param box box to redraw
|
|
|
|
*/
|
|
|
|
|
|
|
|
void html__redraw_a_box(struct content *c, struct box *box)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
box_coords(box, &x, &y);
|
|
|
|
|
|
|
|
content__request_redraw(c, x, y,
|
|
|
|
box->padding[LEFT] + box->width + box->padding[RIGHT],
|
|
|
|
box->padding[TOP] + box->height + box->padding[BOTTOM]);
|
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void html_destroy_frameset(struct content_html_frames *frameset)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (frameset->name) {
|
|
|
|
talloc_free(frameset->name);
|
|
|
|
frameset->name = NULL;
|
|
|
|
}
|
|
|
|
if (frameset->url) {
|
|
|
|
talloc_free(frameset->url);
|
|
|
|
frameset->url = NULL;
|
|
|
|
}
|
|
|
|
if (frameset->children) {
|
|
|
|
for (i = 0; i < (frameset->rows * frameset->cols); i++) {
|
|
|
|
if (frameset->children[i].name) {
|
|
|
|
talloc_free(frameset->children[i].name);
|
|
|
|
frameset->children[i].name = NULL;
|
|
|
|
}
|
|
|
|
if (frameset->children[i].url) {
|
|
|
|
nsurl_unref(frameset->children[i].url);
|
|
|
|
frameset->children[i].url = NULL;
|
|
|
|
}
|
|
|
|
if (frameset->children[i].children)
|
|
|
|
html_destroy_frameset(&frameset->children[i]);
|
|
|
|
}
|
|
|
|
talloc_free(frameset->children);
|
|
|
|
frameset->children = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void html_destroy_iframe(struct content_html_iframe *iframe)
|
|
|
|
{
|
|
|
|
struct content_html_iframe *next;
|
|
|
|
next = iframe;
|
|
|
|
while ((iframe = next) != NULL) {
|
|
|
|
next = iframe->next;
|
|
|
|
if (iframe->name)
|
|
|
|
talloc_free(iframe->name);
|
|
|
|
if (iframe->url) {
|
|
|
|
nsurl_unref(iframe->url);
|
|
|
|
iframe->url = NULL;
|
|
|
|
}
|
|
|
|
talloc_free(iframe);
|
|
|
|
}
|
|
|
|
}
|
2011-07-07 21:50:04 +04:00
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
/**
|
|
|
|
* Destroy a CONTENT_HTML and free all resources it owns.
|
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void html_destroy(struct content *c)
|
2003-02-09 15:58:15 +03:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *html = (html_content *) c;
|
2003-04-15 21:53:00 +04:00
|
|
|
unsigned int i;
|
2009-02-20 14:39:25 +03:00
|
|
|
struct form *f, *g;
|
|
|
|
|
2003-02-09 15:58:15 +03:00
|
|
|
LOG(("content %p", c));
|
|
|
|
|
2009-02-20 14:39:25 +03:00
|
|
|
/* Destroy forms */
|
2010-04-11 21:20:07 +04:00
|
|
|
for (f = html->forms; f != NULL; f = g) {
|
2009-02-20 14:39:25 +03:00
|
|
|
g = f->prev;
|
|
|
|
|
|
|
|
form_free(f);
|
|
|
|
}
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
imagemap_destroy(html);
|
2004-03-27 01:16:31 +03:00
|
|
|
|
2011-10-03 19:56:47 +04:00
|
|
|
if (c->refresh)
|
|
|
|
nsurl_unref(c->refresh);
|
|
|
|
|
|
|
|
if (html->base_url)
|
|
|
|
nsurl_unref(html->base_url);
|
|
|
|
|
2010-04-11 21:20:07 +04:00
|
|
|
if (html->parser_binding != NULL)
|
|
|
|
binding_destroy_tree(html->parser_binding);
|
2004-02-20 03:43:17 +03:00
|
|
|
|
2010-04-11 21:20:07 +04:00
|
|
|
if (html->document != NULL)
|
2011-09-29 23:15:54 +04:00
|
|
|
binding_destroy_document(html->document);
|
2008-09-09 01:55:20 +04:00
|
|
|
|
2006-09-02 19:52:41 +04:00
|
|
|
/* Free base target */
|
2010-04-11 21:20:07 +04:00
|
|
|
if (html->base_target != NULL) {
|
|
|
|
talloc_free(html->base_target);
|
|
|
|
html->base_target = NULL;
|
2006-09-02 19:52:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free frameset */
|
2010-04-11 21:20:07 +04:00
|
|
|
if (html->frameset != NULL) {
|
|
|
|
html_destroy_frameset(html->frameset);
|
|
|
|
talloc_free(html->frameset);
|
|
|
|
html->frameset = NULL;
|
2006-09-02 19:52:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free iframes */
|
2010-04-11 21:20:07 +04:00
|
|
|
if (html->iframe != NULL) {
|
|
|
|
html_destroy_iframe(html->iframe);
|
|
|
|
html->iframe = NULL;
|
2006-09-02 19:52:41 +04:00
|
|
|
}
|
|
|
|
|
2009-07-24 03:05:34 +04:00
|
|
|
/* Destroy selection context */
|
2010-04-11 21:20:07 +04:00
|
|
|
if (html->select_ctx != NULL) {
|
|
|
|
css_select_ctx_destroy(html->select_ctx);
|
|
|
|
html->select_ctx = NULL;
|
2009-07-24 03:05:34 +04:00
|
|
|
}
|
|
|
|
|
2011-10-08 04:21:59 +04:00
|
|
|
if (html->universal != NULL) {
|
|
|
|
lwc_string_unref(html->universal);
|
|
|
|
html->universal = NULL;
|
|
|
|
}
|
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
/* Free stylesheets */
|
2010-04-11 21:20:07 +04:00
|
|
|
for (i = 0; i != html->stylesheet_count; i++) {
|
|
|
|
if (html->stylesheets[i].type == HTML_STYLESHEET_EXTERNAL &&
|
|
|
|
html->stylesheets[i].data.external != NULL) {
|
|
|
|
hlcache_handle_release(
|
|
|
|
html->stylesheets[i].data.external);
|
|
|
|
} else if (html->stylesheets[i].type ==
|
|
|
|
HTML_STYLESHEET_INTERNAL &&
|
|
|
|
html->stylesheets[i].data.internal != NULL) {
|
|
|
|
nscss_destroy_css_data(
|
|
|
|
html->stylesheets[i].data.internal);
|
2004-06-21 19:09:59 +04:00
|
|
|
}
|
2004-02-20 03:43:17 +03:00
|
|
|
}
|
2005-01-17 00:32:10 +03:00
|
|
|
|
2004-02-20 03:43:17 +03:00
|
|
|
/* Free objects */
|
2011-08-20 05:13:51 +04:00
|
|
|
html_destroy_objects(html);
|
|
|
|
}
|
|
|
|
|
2006-09-02 19:52:41 +04:00
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static nserror html_clone(const struct content *old, struct content **newc)
|
2010-04-04 16:41:19 +04:00
|
|
|
{
|
|
|
|
/** \todo Clone HTML specifics */
|
2010-04-10 16:36:21 +04:00
|
|
|
|
|
|
|
/* In the meantime, we should never be called, as HTML contents
|
|
|
|
* cannot be shared and we're not intending to fix printing's
|
|
|
|
* cloning of documents. */
|
|
|
|
assert(0 && "html_clone should never be called");
|
|
|
|
|
2010-04-04 16:41:19 +04:00
|
|
|
return true;
|
|
|
|
}
|
2004-08-12 02:08:26 +04:00
|
|
|
|
2007-01-13 03:21:15 +03:00
|
|
|
/**
|
|
|
|
* Set the content status.
|
|
|
|
*/
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
void html_set_status(html_content *c, const char *extra)
|
2007-01-13 03:21:15 +03:00
|
|
|
{
|
2011-05-08 23:11:34 +04:00
|
|
|
content_set_status(&c->base, "%s", extra);
|
2007-01-13 03:21:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-12 02:08:26 +04:00
|
|
|
/**
|
|
|
|
* Handle a window containing a CONTENT_HTML being opened.
|
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void
|
|
|
|
html_open(struct content *c,
|
|
|
|
struct browser_window *bw,
|
|
|
|
struct content *page,
|
|
|
|
struct box *box,
|
|
|
|
struct object_params *params)
|
2004-08-12 02:08:26 +04:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *html = (html_content *) c;
|
2011-03-11 02:08:34 +03:00
|
|
|
struct content_html_object *object, *next;
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
html->bw = bw;
|
|
|
|
html->page = (html_content *) page;
|
|
|
|
html->box = box;
|
2011-03-11 02:08:34 +03:00
|
|
|
|
2011-07-13 17:20:26 +04:00
|
|
|
/* text selection */
|
|
|
|
selection_init(&html->sel, html->layout);
|
2011-07-01 15:16:43 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
for (object = html->object_list; object != NULL; object = next) {
|
2011-03-11 02:08:34 +03:00
|
|
|
next = object->next;
|
|
|
|
|
|
|
|
if (object->content == NULL)
|
2004-08-12 02:08:26 +04:00
|
|
|
continue;
|
2011-03-11 02:08:34 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
if (content_get_type(object->content) == CONTENT_NONE)
|
2004-08-12 02:08:26 +04:00
|
|
|
continue;
|
2011-03-11 02:08:34 +03:00
|
|
|
|
|
|
|
content_open(object->content,
|
2011-03-11 02:13:03 +03:00
|
|
|
bw, c,
|
2011-03-11 02:08:34 +03:00
|
|
|
object->box,
|
|
|
|
object->box->object_params);
|
2004-08-12 02:08:26 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle a window containing a CONTENT_HTML being closed.
|
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void html_close(struct content *c)
|
2004-08-12 02:08:26 +04:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *html = (html_content *) c;
|
2011-03-11 02:08:34 +03:00
|
|
|
struct content_html_object *object, *next;
|
2011-02-16 00:49:28 +03:00
|
|
|
|
2011-08-24 16:29:30 +04:00
|
|
|
if (html->search != NULL)
|
|
|
|
search_destroy_context(html->search);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
html->bw = NULL;
|
2011-02-16 00:49:28 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
for (object = html->object_list; object != NULL; object = next) {
|
2011-03-11 02:08:34 +03:00
|
|
|
next = object->next;
|
|
|
|
|
|
|
|
if (object->content == NULL)
|
2004-08-12 02:08:26 +04:00
|
|
|
continue;
|
2011-02-16 00:49:28 +03:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
if (content_get_type(object->content) == CONTENT_NONE)
|
2004-08-12 02:08:26 +04:00
|
|
|
continue;
|
2011-02-16 00:49:28 +03:00
|
|
|
|
2011-03-11 02:08:34 +03:00
|
|
|
if (content_get_type(object->content) == CONTENT_HTML)
|
|
|
|
schedule_remove(html_object_refresh, object);
|
2011-02-16 00:49:28 +03:00
|
|
|
|
2011-03-11 02:08:34 +03:00
|
|
|
content_close(object->content);
|
2004-08-12 02:08:26 +04:00
|
|
|
}
|
|
|
|
}
|
2007-01-25 02:16:02 +03:00
|
|
|
|
2011-07-13 17:20:26 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return an HTML content's selection context
|
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static struct selection *html_get_selection(struct content *c)
|
2011-07-13 17:20:26 +04:00
|
|
|
{
|
|
|
|
html_content *html = (html_content *) c;
|
|
|
|
|
|
|
|
return &html->sel;
|
|
|
|
}
|
|
|
|
|
2011-08-24 16:29:30 +04:00
|
|
|
|
2011-09-06 22:08:18 +04:00
|
|
|
/**
|
|
|
|
* Get access to any content, link URLs and objects (images) currently
|
|
|
|
* at the given (x, y) coordinates.
|
|
|
|
*
|
|
|
|
* \param c html content to look inside
|
|
|
|
* \param x x-coordinate of point of interest
|
|
|
|
* \param y y-coordinate of point of interest
|
|
|
|
* \param data pointer to contextual_content struct. Its fields are updated
|
|
|
|
* with pointers to any relevent content, or set to NULL if none.
|
|
|
|
*/
|
2012-03-24 21:11:17 +04:00
|
|
|
static void
|
|
|
|
html_get_contextual_content(struct content *c,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
struct contextual_content *data)
|
2011-09-06 22:08:18 +04:00
|
|
|
{
|
|
|
|
html_content *html = (html_content *) c;
|
|
|
|
|
|
|
|
struct box *box = html->layout;
|
|
|
|
struct box *next;
|
|
|
|
int box_x = 0, box_y = 0;
|
|
|
|
hlcache_handle *containing_content = NULL;
|
|
|
|
|
|
|
|
while ((next = box_at_point(box, x, y, &box_x, &box_y,
|
|
|
|
&containing_content)) != NULL) {
|
|
|
|
box = next;
|
|
|
|
|
|
|
|
if (box->style && css_computed_visibility(box->style) ==
|
|
|
|
CSS_VISIBILITY_HIDDEN)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (box->iframe)
|
|
|
|
browser_window_get_contextual_content(box->iframe,
|
|
|
|
x - box_x, y - box_y, data);
|
|
|
|
|
|
|
|
if (box->object)
|
|
|
|
data->object = box->object;
|
|
|
|
|
|
|
|
if (box->href)
|
2011-10-04 00:28:29 +04:00
|
|
|
data->link_url = nsurl_access(box->href);
|
2011-09-06 22:08:18 +04:00
|
|
|
|
|
|
|
if (box->usemap) {
|
|
|
|
const char *target = NULL;
|
2011-10-04 00:28:29 +04:00
|
|
|
data->link_url = nsurl_access(imagemap_get(html,
|
|
|
|
box->usemap, box_x, box_y, x, y,
|
|
|
|
&target));
|
2011-09-06 22:08:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 21:47:29 +04:00
|
|
|
/**
|
|
|
|
* Scroll deepest thing within the content which can be scrolled at given point
|
|
|
|
*
|
|
|
|
* \param c html content to look inside
|
|
|
|
* \param x x-coordinate of point of interest
|
|
|
|
* \param y y-coordinate of point of interest
|
|
|
|
* \param scrx x-coordinate of point of interest
|
|
|
|
* \param scry y-coordinate of point of interest
|
|
|
|
* \return true iff scroll was consumed by something in the content
|
|
|
|
*/
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool
|
|
|
|
html_scroll_at_point(struct content *c, int x, int y, int scrx, int scry)
|
2011-11-29 21:47:29 +04:00
|
|
|
{
|
|
|
|
html_content *html = (html_content *) c;
|
|
|
|
|
|
|
|
struct box *box = html->layout;
|
|
|
|
struct box *next;
|
|
|
|
int box_x = 0, box_y = 0;
|
|
|
|
hlcache_handle *containing_content = NULL;
|
|
|
|
bool handled_scroll = false;
|
|
|
|
|
|
|
|
/* TODO: invert order; visit deepest box first */
|
|
|
|
|
|
|
|
while ((next = box_at_point(box, x, y, &box_x, &box_y,
|
|
|
|
&containing_content)) != NULL) {
|
|
|
|
box = next;
|
|
|
|
|
|
|
|
if (box->style && css_computed_visibility(box->style) ==
|
|
|
|
CSS_VISIBILITY_HIDDEN)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Pass into iframe */
|
|
|
|
if (box->iframe && browser_window_scroll_at_point(box->iframe,
|
|
|
|
x - box_x, y - box_y, scrx, scry) == true)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
/* Handle box scrollbars */
|
|
|
|
if (box->scroll_y && scrollbar_scroll(box->scroll_y, scry))
|
|
|
|
handled_scroll = true;
|
|
|
|
|
|
|
|
if (box->scroll_x && scrollbar_scroll(box->scroll_x, scrx))
|
|
|
|
handled_scroll = true;
|
|
|
|
|
|
|
|
if (handled_scroll == true)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-02 01:49:57 +04:00
|
|
|
/**
|
|
|
|
* Drop a file onto a content at a particular point.
|
|
|
|
*
|
|
|
|
* \param c html content to look inside
|
|
|
|
* \param x x-coordinate of point of interest
|
|
|
|
* \param y y-coordinate of point of interest
|
|
|
|
* \param file path to file to be dropped
|
|
|
|
* \return true iff file drop has been handled
|
|
|
|
*/
|
2012-03-24 21:11:17 +04:00
|
|
|
static bool html_drop_file_at_point(struct content *c, int x, int y, char *file)
|
2011-12-02 01:49:57 +04:00
|
|
|
{
|
|
|
|
html_content *html = (html_content *) c;
|
|
|
|
|
|
|
|
struct box *box = html->layout;
|
|
|
|
struct box *next;
|
|
|
|
struct box *file_box = NULL;
|
|
|
|
struct box *text_box = NULL;
|
|
|
|
int box_x = 0, box_y = 0;
|
|
|
|
hlcache_handle *containing_content = NULL;
|
|
|
|
|
|
|
|
/* Scan box tree for boxes that can handle drop */
|
|
|
|
while ((next = box_at_point(box, x, y, &box_x, &box_y,
|
|
|
|
&containing_content)) != NULL) {
|
|
|
|
box = next;
|
|
|
|
|
|
|
|
if (box->style && css_computed_visibility(box->style) ==
|
|
|
|
CSS_VISIBILITY_HIDDEN)
|
|
|
|
continue;
|
|
|
|
|
2011-12-02 03:52:45 +04:00
|
|
|
if (box->iframe)
|
|
|
|
return browser_window_drop_file_at_point(box->iframe,
|
|
|
|
x - box_x, y - box_y, file);
|
|
|
|
|
2011-12-02 01:49:57 +04:00
|
|
|
if (box->gadget) {
|
|
|
|
switch (box->gadget->type) {
|
|
|
|
case GADGET_FILE:
|
|
|
|
file_box = box;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GADGET_TEXTBOX:
|
|
|
|
case GADGET_TEXTAREA:
|
|
|
|
case GADGET_PASSWORD:
|
|
|
|
text_box = box;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* appease compiler */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!file_box && !text_box)
|
|
|
|
/* No box capable of handling drop */
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* Handle the drop */
|
|
|
|
if (file_box) {
|
|
|
|
/* File dropped on file input */
|
|
|
|
utf8_convert_ret ret;
|
|
|
|
char *utf8_fn;
|
|
|
|
|
|
|
|
ret = utf8_from_local_encoding(file, 0,
|
|
|
|
&utf8_fn);
|
|
|
|
if (ret != UTF8_CONVERT_OK) {
|
|
|
|
/* A bad encoding should never happen */
|
|
|
|
assert(ret != UTF8_CONVERT_BADENC);
|
|
|
|
LOG(("utf8_from_local_encoding failed"));
|
|
|
|
/* Load was for us - just no memory */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Found: update form input */
|
|
|
|
free(file_box->gadget->value);
|
|
|
|
file_box->gadget->value = utf8_fn;
|
|
|
|
|
|
|
|
/* Redraw box. */
|
2011-12-02 03:52:45 +04:00
|
|
|
if (containing_content == NULL)
|
|
|
|
html__redraw_a_box(c, file_box);
|
|
|
|
else
|
|
|
|
html_redraw_a_box(containing_content, file_box);
|
2011-12-02 01:49:57 +04:00
|
|
|
|
|
|
|
} else if (html->bw != NULL) {
|
|
|
|
/* File dropped on text input */
|
|
|
|
|
|
|
|
size_t file_len;
|
|
|
|
FILE *fp = NULL;
|
|
|
|
char *buffer;
|
|
|
|
char *utf8_buff;
|
|
|
|
utf8_convert_ret ret;
|
|
|
|
unsigned int size;
|
2011-12-02 03:52:45 +04:00
|
|
|
struct browser_window *bw;
|
2011-12-02 01:49:57 +04:00
|
|
|
|
|
|
|
/* Open file */
|
|
|
|
fp = fopen(file, "rb");
|
|
|
|
if (fp == NULL) {
|
|
|
|
/* Couldn't open file, but drop was for us */
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get filesize */
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
|
|
file_len = ftell(fp);
|
|
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
|
|
|
|
/* Allocate buffer for file data */
|
|
|
|
buffer = malloc(file_len + 1);
|
|
|
|
if (buffer == NULL) {
|
|
|
|
/* No memory, but drop was for us */
|
|
|
|
fclose(fp);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Stick file into buffer */
|
|
|
|
if (file_len != fread(buffer, 1, file_len, fp)) {
|
|
|
|
/* Failed, but drop was for us */
|
|
|
|
free(buffer);
|
|
|
|
fclose(fp);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Done with file */
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
/* Ensure buffer's string termination */
|
|
|
|
buffer[file_len] = '\0';
|
|
|
|
|
|
|
|
/* TODO: Sniff for text? */
|
|
|
|
|
|
|
|
/* Convert to UTF-8 */
|
|
|
|
ret = utf8_from_local_encoding(buffer, file_len, &utf8_buff);
|
|
|
|
if (ret != UTF8_CONVERT_OK) {
|
|
|
|
/* bad encoding shouldn't happen */
|
|
|
|
assert(ret != UTF8_CONVERT_BADENC);
|
|
|
|
LOG(("utf8_from_local_encoding failed"));
|
|
|
|
free(buffer);
|
|
|
|
warn_user("NoMemory", NULL);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Done with buffer */
|
|
|
|
free(buffer);
|
|
|
|
|
|
|
|
/* Get new length */
|
|
|
|
size = strlen(utf8_buff);
|
|
|
|
|
|
|
|
/* Simulate a click over the input box, to place caret */
|
|
|
|
browser_window_mouse_click(html->bw,
|
|
|
|
BROWSER_MOUSE_PRESS_1, x, y);
|
|
|
|
|
2011-12-02 03:52:45 +04:00
|
|
|
bw = browser_window_get_root(html->bw);
|
|
|
|
|
2011-12-02 01:49:57 +04:00
|
|
|
/* Paste the file as text */
|
2011-12-02 03:52:45 +04:00
|
|
|
browser_window_paste_text(bw, utf8_buff, size, true);
|
2011-12-02 01:49:57 +04:00
|
|
|
|
|
|
|
free(utf8_buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-08-24 16:29:30 +04:00
|
|
|
/**
|
|
|
|
* Set an HTML content's search context
|
|
|
|
*
|
|
|
|
* \param c content of type html
|
|
|
|
* \param s search context, or NULL if none
|
|
|
|
*/
|
|
|
|
|
|
|
|
void html_set_search(struct content *c, struct search_context *s)
|
|
|
|
{
|
|
|
|
html_content *html = (html_content *) c;
|
|
|
|
|
|
|
|
html->search = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return an HTML content's search context
|
|
|
|
*
|
|
|
|
* \param c content of type html
|
|
|
|
* \return content's search context, or NULL if none
|
|
|
|
*/
|
|
|
|
|
2012-03-25 02:16:03 +04:00
|
|
|
struct search_context *html_get_search(struct content *c)
|
2011-08-24 16:29:30 +04:00
|
|
|
{
|
|
|
|
html_content *html = (html_content *) c;
|
|
|
|
|
|
|
|
return html->search;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-10 14:56:34 +04:00
|
|
|
#if ALWAYS_DUMP_FRAMESET
|
2007-01-25 02:16:02 +03:00
|
|
|
/**
|
|
|
|
* Print a frameset tree to stderr.
|
|
|
|
*/
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
static void
|
|
|
|
html_dump_frameset(struct content_html_frames *frame, unsigned int depth)
|
2007-01-25 02:16:02 +03:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
int row, col, index;
|
|
|
|
const char *unit[] = {"px", "%", "*"};
|
|
|
|
const char *scrolling[] = {"auto", "yes", "no"};
|
|
|
|
|
|
|
|
assert(frame);
|
|
|
|
|
|
|
|
fprintf(stderr, "%p ", frame);
|
|
|
|
|
|
|
|
fprintf(stderr, "(%i %i) ", frame->rows, frame->cols);
|
|
|
|
|
|
|
|
fprintf(stderr, "w%g%s ", frame->width.value, unit[frame->width.unit]);
|
|
|
|
fprintf(stderr, "h%g%s ", frame->height.value,unit[frame->height.unit]);
|
|
|
|
fprintf(stderr, "(margin w%i h%i) ",
|
|
|
|
frame->margin_width, frame->margin_height);
|
|
|
|
|
|
|
|
if (frame->name)
|
|
|
|
fprintf(stderr, "'%s' ", frame->name);
|
|
|
|
if (frame->url)
|
|
|
|
fprintf(stderr, "<%s> ", frame->url);
|
|
|
|
|
|
|
|
if (frame->no_resize)
|
|
|
|
fprintf(stderr, "noresize ");
|
|
|
|
fprintf(stderr, "(scrolling %s) ", scrolling[frame->scrolling]);
|
|
|
|
if (frame->border)
|
|
|
|
fprintf(stderr, "border %x ",
|
|
|
|
(unsigned int) frame->border_colour);
|
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
|
|
|
if (frame->children) {
|
|
|
|
for (row = 0; row != frame->rows; row++) {
|
|
|
|
for (col = 0; col != frame->cols; col++) {
|
|
|
|
for (i = 0; i != depth; i++)
|
|
|
|
fprintf(stderr, " ");
|
|
|
|
fprintf(stderr, "(%i %i): ", row, col);
|
|
|
|
index = (row * frame->cols) + col;
|
|
|
|
html_dump_frameset(&frame->children[index],
|
|
|
|
depth + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-10-10 14:56:34 +04:00
|
|
|
|
|
|
|
#endif
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve HTML document tree
|
|
|
|
*
|
|
|
|
* \param h HTML content to retrieve document tree from
|
|
|
|
* \return Pointer to document tree
|
|
|
|
*/
|
2012-03-24 03:18:04 +04:00
|
|
|
dom_document *html_get_document(hlcache_handle *h)
|
2010-03-28 16:56:39 +04:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->document;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve box tree
|
|
|
|
*
|
|
|
|
* \param h HTML content to retrieve tree from
|
|
|
|
* \return Pointer to box tree
|
|
|
|
*
|
|
|
|
* \todo This API must die, as must all use of the box tree outside render/
|
|
|
|
*/
|
|
|
|
struct box *html_get_box_tree(hlcache_handle *h)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->layout;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve the charset of an HTML document
|
|
|
|
*
|
|
|
|
* \param h Content to retrieve charset from
|
|
|
|
* \return Pointer to charset, or NULL
|
|
|
|
*/
|
|
|
|
const char *html_get_encoding(hlcache_handle *h)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->encoding;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
2010-04-07 17:12:27 +04:00
|
|
|
/**
|
|
|
|
* Retrieve the charset of an HTML document
|
|
|
|
*
|
|
|
|
* \param h Content to retrieve charset from
|
|
|
|
* \return Pointer to charset, or NULL
|
|
|
|
*/
|
|
|
|
binding_encoding_source html_get_encoding_source(hlcache_handle *h)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-04-07 17:12:27 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->encoding_source;
|
2010-04-07 17:12:27 +04:00
|
|
|
}
|
|
|
|
|
2010-03-28 16:56:39 +04:00
|
|
|
/**
|
|
|
|
* Retrieve framesets used in an HTML document
|
|
|
|
*
|
|
|
|
* \param h Content to inspect
|
|
|
|
* \return Pointer to framesets, or NULL if none
|
|
|
|
*/
|
|
|
|
struct content_html_frames *html_get_frameset(hlcache_handle *h)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->frameset;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve iframes used in an HTML document
|
|
|
|
*
|
|
|
|
* \param h Content to inspect
|
|
|
|
* \return Pointer to iframes, or NULL if none
|
|
|
|
*/
|
|
|
|
struct content_html_iframe *html_get_iframe(hlcache_handle *h)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->iframe;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve an HTML content's base URL
|
|
|
|
*
|
|
|
|
* \param h Content to retrieve base target from
|
|
|
|
* \return Pointer to URL
|
|
|
|
*/
|
2011-10-03 19:56:47 +04:00
|
|
|
nsurl *html_get_base_url(hlcache_handle *h)
|
2010-03-28 16:56:39 +04:00
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->base_url;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve an HTML content's base target
|
|
|
|
*
|
|
|
|
* \param h Content to retrieve base target from
|
|
|
|
* \return Pointer to target, or NULL if none
|
|
|
|
*/
|
|
|
|
const char *html_get_base_target(hlcache_handle *h)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->base_target;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve stylesheets used by HTML document
|
|
|
|
*
|
|
|
|
* \param h Content to retrieve stylesheets from
|
|
|
|
* \param n Pointer to location to receive number of sheets
|
|
|
|
* \return Pointer to array of stylesheets
|
|
|
|
*/
|
|
|
|
struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
assert(n != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
*n = c->stylesheet_count;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->stylesheets;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve objects used by HTML document
|
|
|
|
*
|
|
|
|
* \param h Content to retrieve objects from
|
|
|
|
* \param n Pointer to location to receive number of objects
|
2011-03-11 02:08:34 +03:00
|
|
|
* \return Pointer to list of objects
|
2010-03-28 16:56:39 +04:00
|
|
|
*/
|
|
|
|
struct content_html_object *html_get_objects(hlcache_handle *h, unsigned int *n)
|
|
|
|
{
|
2011-05-07 00:40:09 +04:00
|
|
|
html_content *c = (html_content *) hlcache_handle_get_content(h);
|
2010-03-28 16:56:39 +04:00
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
assert(n != NULL);
|
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
*n = c->num_objects;
|
2010-03-28 16:56:39 +04:00
|
|
|
|
2011-05-07 00:40:09 +04:00
|
|
|
return c->object_list;
|
2010-03-28 16:56:39 +04:00
|
|
|
}
|
|
|
|
|
2010-06-04 13:35:08 +04:00
|
|
|
/**
|
|
|
|
* Retrieve layout coordinates of box with given id
|
|
|
|
*
|
|
|
|
* \param h HTML document to search
|
|
|
|
* \param frag_id String containing an element id
|
|
|
|
* \param x Updated to global x coord iff id found
|
|
|
|
* \param y Updated to global y coord iff id found
|
|
|
|
* \return true iff id found
|
|
|
|
*/
|
2011-10-29 15:37:05 +04:00
|
|
|
bool html_get_id_offset(hlcache_handle *h, lwc_string *frag_id, int *x, int *y)
|
2010-06-04 13:35:08 +04:00
|
|
|
{
|
|
|
|
struct box *pos;
|
2010-10-11 10:54:37 +04:00
|
|
|
struct box *layout;
|
2010-06-04 13:35:08 +04:00
|
|
|
|
|
|
|
if (content_get_type(h) != CONTENT_HTML)
|
|
|
|
return false;
|
|
|
|
|
2010-10-11 10:54:37 +04:00
|
|
|
layout = html_get_box_tree(h);
|
|
|
|
|
2010-06-04 13:35:08 +04:00
|
|
|
if ((pos = box_find_by_id(layout, frag_id)) != 0) {
|
|
|
|
box_coords(pos, x, y);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2011-05-07 00:40:09 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Compute the type of a content
|
|
|
|
*
|
|
|
|
* \return CONTENT_HTML
|
|
|
|
*/
|
2012-03-24 21:11:17 +04:00
|
|
|
static content_type html_content_type(void)
|
2011-05-07 00:40:09 +04:00
|
|
|
{
|
|
|
|
return CONTENT_HTML;
|
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
|
|
|
|
static void html_fini(void)
|
|
|
|
{
|
2012-03-25 12:37:48 +04:00
|
|
|
box_construct_fini();
|
2012-03-24 21:11:17 +04:00
|
|
|
|
2012-03-24 23:35:59 +04:00
|
|
|
#define HTML_DOM_STRING_UNREF(NAME) \
|
|
|
|
do { \
|
|
|
|
if (html_dom_string_##NAME != NULL) { \
|
|
|
|
dom_string_unref(html_dom_string_##NAME); \
|
|
|
|
html_dom_string_##NAME = NULL; \
|
|
|
|
} \
|
|
|
|
} while (0) \
|
|
|
|
|
|
|
|
HTML_DOM_STRING_UNREF(html);
|
|
|
|
HTML_DOM_STRING_UNREF(head);
|
|
|
|
HTML_DOM_STRING_UNREF(rel);
|
|
|
|
HTML_DOM_STRING_UNREF(href);
|
|
|
|
HTML_DOM_STRING_UNREF(hreflang);
|
|
|
|
HTML_DOM_STRING_UNREF(type);
|
|
|
|
HTML_DOM_STRING_UNREF(media);
|
|
|
|
HTML_DOM_STRING_UNREF(sizes);
|
|
|
|
HTML_DOM_STRING_UNREF(title);
|
|
|
|
HTML_DOM_STRING_UNREF(base);
|
|
|
|
HTML_DOM_STRING_UNREF(link);
|
|
|
|
HTML_DOM_STRING_UNREF(target);
|
|
|
|
HTML_DOM_STRING_UNREF(_blank);
|
|
|
|
HTML_DOM_STRING_UNREF(_self);
|
|
|
|
HTML_DOM_STRING_UNREF(_parent);
|
|
|
|
HTML_DOM_STRING_UNREF(_top);
|
2012-03-25 12:05:18 +04:00
|
|
|
HTML_DOM_STRING_UNREF(content);
|
2012-03-25 19:07:08 +04:00
|
|
|
HTML_DOM_STRING_UNREF(map);
|
|
|
|
HTML_DOM_STRING_UNREF(id);
|
|
|
|
HTML_DOM_STRING_UNREF(name);
|
|
|
|
HTML_DOM_STRING_UNREF(area);
|
|
|
|
HTML_DOM_STRING_UNREF(a);
|
|
|
|
HTML_DOM_STRING_UNREF(nohref);
|
|
|
|
HTML_DOM_STRING_UNREF(shape);
|
|
|
|
HTML_DOM_STRING_UNREF(default);
|
|
|
|
HTML_DOM_STRING_UNREF(rect);
|
|
|
|
HTML_DOM_STRING_UNREF(rectangle);
|
|
|
|
HTML_DOM_STRING_UNREF(coords);
|
|
|
|
HTML_DOM_STRING_UNREF(circle);
|
|
|
|
HTML_DOM_STRING_UNREF(poly);
|
|
|
|
HTML_DOM_STRING_UNREF(polygon);
|
2012-03-24 23:35:59 +04:00
|
|
|
|
|
|
|
#undef HTML_DOM_STRING_UNREF
|
2012-03-24 21:11:17 +04:00
|
|
|
|
2012-03-25 12:05:18 +04:00
|
|
|
if (html_dom_string_http_equiv != NULL) {
|
|
|
|
dom_string_unref(html_dom_string_http_equiv);
|
|
|
|
html_dom_string_http_equiv = NULL;
|
|
|
|
}
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
if (html_user_stylesheet_url != NULL) {
|
|
|
|
nsurl_unref(html_user_stylesheet_url);
|
|
|
|
html_user_stylesheet_url = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (html_quirks_stylesheet_url != NULL) {
|
|
|
|
nsurl_unref(html_quirks_stylesheet_url);
|
|
|
|
html_quirks_stylesheet_url = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (html_adblock_stylesheet_url != NULL) {
|
|
|
|
nsurl_unref(html_adblock_stylesheet_url);
|
|
|
|
html_adblock_stylesheet_url = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (html_default_stylesheet_url != NULL) {
|
|
|
|
nsurl_unref(html_default_stylesheet_url);
|
|
|
|
html_default_stylesheet_url = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (html_charset != NULL) {
|
|
|
|
lwc_string_unref(html_charset);
|
|
|
|
html_charset = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const content_handler html_content_handler = {
|
|
|
|
.fini = html_fini,
|
|
|
|
.create = html_create,
|
|
|
|
.process_data = html_process_data,
|
|
|
|
.data_complete = html_convert,
|
|
|
|
.reformat = html_reformat,
|
|
|
|
.destroy = html_destroy,
|
|
|
|
.stop = html_stop,
|
|
|
|
.mouse_track = html_mouse_track,
|
|
|
|
.mouse_action = html_mouse_action,
|
|
|
|
.redraw = html_redraw,
|
|
|
|
.open = html_open,
|
|
|
|
.close = html_close,
|
|
|
|
.get_selection = html_get_selection,
|
|
|
|
.get_contextual_content = html_get_contextual_content,
|
|
|
|
.scroll_at_point = html_scroll_at_point,
|
|
|
|
.drop_file_at_point = html_drop_file_at_point,
|
|
|
|
.clone = html_clone,
|
|
|
|
.type = html_content_type,
|
|
|
|
.no_share = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
nserror html_init(void)
|
|
|
|
{
|
|
|
|
uint32_t i;
|
|
|
|
lwc_error lerror;
|
|
|
|
nserror error;
|
|
|
|
dom_exception exc; /* returned by libdom functions */
|
|
|
|
|
|
|
|
lerror = lwc_intern_string("charset", SLEN("charset"), &html_charset);
|
|
|
|
if (lerror != lwc_error_ok) {
|
|
|
|
error = NSERROR_NOMEM;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = nsurl_create("resource:default.css",
|
|
|
|
&html_default_stylesheet_url);
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
error = nsurl_create("resource:adblock.css",
|
|
|
|
&html_adblock_stylesheet_url);
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
error = nsurl_create("resource:quirks.css",
|
|
|
|
&html_quirks_stylesheet_url);
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
error = nsurl_create("resource:user.css",
|
|
|
|
&html_user_stylesheet_url);
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
goto error;
|
|
|
|
|
2012-03-24 23:35:59 +04:00
|
|
|
#define HTML_DOM_STRING_INTERN(NAME) \
|
|
|
|
exc = dom_string_create_interned((const uint8_t *)#NAME, \
|
|
|
|
sizeof(#NAME) - 1, \
|
|
|
|
&html_dom_string_##NAME ); \
|
|
|
|
if ((exc != DOM_NO_ERR) || (html_dom_string_##NAME == NULL)) \
|
|
|
|
goto error
|
|
|
|
|
|
|
|
HTML_DOM_STRING_INTERN(html);
|
|
|
|
HTML_DOM_STRING_INTERN(head);
|
|
|
|
HTML_DOM_STRING_INTERN(rel);
|
|
|
|
HTML_DOM_STRING_INTERN(href);
|
|
|
|
HTML_DOM_STRING_INTERN(hreflang);
|
|
|
|
HTML_DOM_STRING_INTERN(type);
|
|
|
|
HTML_DOM_STRING_INTERN(media);
|
|
|
|
HTML_DOM_STRING_INTERN(sizes);
|
|
|
|
HTML_DOM_STRING_INTERN(title);
|
|
|
|
HTML_DOM_STRING_INTERN(base);
|
|
|
|
HTML_DOM_STRING_INTERN(link);
|
|
|
|
HTML_DOM_STRING_INTERN(target);
|
|
|
|
HTML_DOM_STRING_INTERN(_blank);
|
|
|
|
HTML_DOM_STRING_INTERN(_self);
|
|
|
|
HTML_DOM_STRING_INTERN(_parent);
|
|
|
|
HTML_DOM_STRING_INTERN(_top);
|
2012-03-25 02:08:13 +04:00
|
|
|
HTML_DOM_STRING_INTERN(content);
|
2012-03-25 19:07:08 +04:00
|
|
|
HTML_DOM_STRING_INTERN(map);
|
|
|
|
HTML_DOM_STRING_INTERN(id);
|
|
|
|
HTML_DOM_STRING_INTERN(name);
|
|
|
|
HTML_DOM_STRING_INTERN(area);
|
|
|
|
HTML_DOM_STRING_INTERN(a);
|
|
|
|
HTML_DOM_STRING_INTERN(nohref);
|
|
|
|
HTML_DOM_STRING_INTERN(shape);
|
|
|
|
HTML_DOM_STRING_INTERN(default);
|
|
|
|
HTML_DOM_STRING_INTERN(rect);
|
|
|
|
HTML_DOM_STRING_INTERN(rectangle);
|
|
|
|
HTML_DOM_STRING_INTERN(coords);
|
|
|
|
HTML_DOM_STRING_INTERN(circle);
|
|
|
|
HTML_DOM_STRING_INTERN(poly);
|
|
|
|
HTML_DOM_STRING_INTERN(polygon);
|
2012-03-24 23:35:59 +04:00
|
|
|
|
|
|
|
#undef HTML_DOM_STRING_INTERN
|
2012-03-24 21:11:17 +04:00
|
|
|
|
2012-03-25 02:08:13 +04:00
|
|
|
exc = dom_string_create_interned((const uint8_t *) "http-equiv",
|
|
|
|
SLEN("http-equiv"),
|
|
|
|
&html_dom_string_http_equiv);
|
|
|
|
if ((exc != DOM_NO_ERR) || (html_dom_string_http_equiv == NULL))
|
|
|
|
goto error;
|
|
|
|
|
2012-03-25 12:37:48 +04:00
|
|
|
error = box_construct_init();
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
goto error;
|
|
|
|
|
2012-03-24 21:11:17 +04:00
|
|
|
for (i = 0; i < NOF_ELEMENTS(html_types); i++) {
|
|
|
|
error = content_factory_register_handler(html_types[i],
|
|
|
|
&html_content_handler);
|
|
|
|
if (error != NSERROR_OK)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NSERROR_OK;
|
|
|
|
|
|
|
|
error:
|
|
|
|
html_fini();
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2011-07-26 17:53:42 +04:00
|
|
|
/**
|
|
|
|
* Get the browser window containing an HTML content
|
|
|
|
*
|
|
|
|
* \param c HTML content
|
|
|
|
* \return the browser window
|
|
|
|
*/
|
|
|
|
struct browser_window *html_get_browser_window(struct content *c)
|
|
|
|
{
|
|
|
|
html_content *html = (html_content *) c;
|
|
|
|
|
|
|
|
assert(c != NULL);
|
|
|
|
assert(c->handler == &html_content_handler);
|
|
|
|
|
|
|
|
return html->bw;
|
|
|
|
}
|