[gs-commits] mupdf 1.16.1.epub-prerelease-6 XML parser: Tweak for impr
[email protected] (Robin Watts) Fri, 25 Oct 2019 14:53:20 +0000 (UTC)
| Newsgroups | gmane.comp.printing.ghostscript.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit 91782a434877d84b828fdeef20c569d4c3b4071b Author: Robin Watts <[email protected]> Date: Sat Oct 5 17:48:39 2019 -0500 XML parser: Tweak for improved HTML parsing The XML parser copes badly with HTML, for several reasons. Firstly, many HTML tags close themselves, without requiring a "/>". (e.g. <meta foo=blah>). The XML parser would leave such tags open. Secondly, many HTML tags should close themselves when a second sucessive tag of the same type is found (e.g. "<p>foo<p>bar"). Again, the XML parser would leave such tags open. For situations such as tables, this is even worse; for example a TR tag should automatically close any existing TD tags. Thirdly, HTML is case insensitive, so tags need not exactly match. Finally, the XML parser itself will get confused if the XML is less than perfect. e.g. <a><b></a> will see the </a> close the <b> tag, but not the <a> tag. We therefore introduce some improvements to the parser to cope with such issues. The biggest change is a "for_html" flag to the xml parser; this triggers various changes to the way the parser works. Firstly, it lowercases all HTML tags as they are read. Secondly, it makes use of a table of all defined HTML tags with various flags so that any tags that autoclose themselves (or other tags) are handled correctly. In addition, using the same table, we can 'auto open' tags (for instance if we meet a <tr> without a <table>, we can automatically open the <table> first). This makes us much more resilient to HTML (as opposed to XHTML) files. In both XML and HTML parsing modes, we now check the tag we are closing, so <a><b></a> will close both the <b> and <a> tags when the </a> is parsed. Unmatched closing tags are ignored, so <a><b></a></b> will still be parsed correctly. All of these changes should leave operation on well formed XML files unchanged. diff --git a/include/mupdf/fitz/xml.h b/include/mupdf/fitz/xml.h index 5ab486c..b1bb93e 100644 --- a/include/mupdf/fitz/xml.h +++ b/include/mupdf/fitz/xml.h @@ -11,7 +11,7 @@ typedef struct fz_xml_doc_s fz_xml_doc; typedef struct fz_xml_s fz_xml; -fz_xml_doc *fz_parse_xml(fz_context *ctx, fz_buffer *buf, int preserve_white); +fz_xml_doc *fz_parse_xml(fz_context *ctx, fz_buffer *buf, int preserve_white, int for_html); void fz_drop_xml(fz_context *ctx, fz_xml_doc *xml); diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj index 67eb95c..3609993 100644 --- a/platform/win32/libmupdf.vcproj +++ b/platform/win32/libmupdf.vcproj @@ -1739,6 +1739,10 @@ > </File> <File + RelativePath="..\..\source\fitz\html-tags.h" + > + </File> + <File RelativePath="..\..\source\fitz\image.c" > </File> diff --git a/source/fitz/html-tags.h b/source/fitz/html-tags.h new file mode 100644 index 0000000..39e452d --- /dev/null +++ b/source/fitz/html-tags.h @@ -0,0 +1,99 @@ +/* No repeated inclusion header here, as this + * file is included several times. */ + +/* The following table, was built to encode the information in: + * https://www.w3.org/TR/REC-html40/index/elements.html + */ +HTML_TAG(a, body, _NONE, _NONE, 0), +HTML_TAG(abbr, body, _NONE, _NONE, 0), +HTML_TAG(acronym, body, _NONE, _NONE, 0), +HTML_TAG(address, body, _NONE, _NONE, 0), +HTML_TAG(applet, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(area, map, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(b, body, _NONE, _NONE, 0), +HTML_TAG(base, head, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(basefont, body, _NONE, _NONE, END_FORBIDDEN | DEPRECATED | DTD_LOOSE), +HTML_TAG(bdo, html, _NONE, _NONE, 0), +HTML_TAG(big, body, _NONE, _NONE, 0), +HTML_TAG(blockquote, body, _NONE, _NONE, 0), +HTML_TAG(body, html, _NONE, _NONE, START_OPTIONAL | END_OPTIONAL), +HTML_TAG(br, body, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(button, body, _NONE, _NONE, 0), +HTML_TAG(caption, body, _NONE, _NONE, 0), +HTML_TAG(center, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(cite, body, _NONE, _NONE, 0), +HTML_TAG(code, body, _NONE, _NONE, 0), +HTML_TAG(col, table, _NONE, _NONE, END_FORBIDDEN | (3<<TABLE_SHIFT)), +HTML_TAG(colgroup, table, _NONE, _NONE, END_OPTIONAL | (2<<TABLE_SHIFT)), +HTML_TAG(dd, dl, _NONE, _NONE, END_OPTIONAL), +HTML_TAG(del, body, _NONE, _NONE, 0), +HTML_TAG(dfn, body, _NONE, _NONE, 0), +HTML_TAG(dir, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(div, body, _NONE, _NONE, CONTAINER), +HTML_TAG(dl, body, _NONE, _NONE, CONTAINER), +HTML_TAG(dt, dl, _NONE, _NONE, 0), +HTML_TAG(em, body, _NONE, _NONE, 0), +HTML_TAG(fieldset, form, _NONE, _NONE, 0), +HTML_TAG(font, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(form, body, _NONE, _NONE, 0), +HTML_TAG(frame, frameset,_NONE, _NONE, END_FORBIDDEN | DTD_FRAMESET), +HTML_TAG(frameset, body, _NONE, _NONE, DTD_FRAMESET), +HTML_TAG(h1, body, _NONE, _NONE, 0), +HTML_TAG(h2, body, _NONE, _NONE, 0), +HTML_TAG(h3, body, _NONE, _NONE, 0), +HTML_TAG(h4, body, _NONE, _NONE, 0), +HTML_TAG(h5, body, _NONE, _NONE, 0), +HTML_TAG(h6, body, _NONE, _NONE, 0), +HTML_TAG(head, html, _NONE, _NONE, START_OPTIONAL | END_OPTIONAL), +HTML_TAG(hr, body, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(html, _NONE, _NONE, _NONE, START_OPTIONAL | END_OPTIONAL), +HTML_TAG(i, body, _NONE, _NONE, 0), +HTML_TAG(iframe, html, _NONE, _NONE, DTD_LOOSE), +HTML_TAG(img, body, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(input, body, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(ins, body, _NONE, _NONE, 0), +HTML_TAG(isindex, head, _NONE, _NONE, END_FORBIDDEN | DEPRECATED | DTD_LOOSE), +HTML_TAG(kbd, body, _NONE, _NONE, 0), +HTML_TAG(label, body, _NONE, _NONE, 0), +HTML_TAG(legend, body, _NONE, _NONE, 0), +HTML_TAG(li, ul, ol, menu, END_OPTIONAL), +HTML_TAG(link, html, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(map, body, _NONE, _NONE, 0), +HTML_TAG(menu, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(meta, head, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(noframes, frameset,_NONE, _NONE, DTD_FRAMESET), +HTML_TAG(noscript, html, _NONE, _NONE, 0), +HTML_TAG(object, body, _NONE, _NONE, 0), +HTML_TAG(ol, body, _NONE, _NONE, CONTAINER), +HTML_TAG(optgroup, select, _NONE, _NONE, 0), +HTML_TAG(option, select, _NONE, _NONE, END_OPTIONAL), +HTML_TAG(p, body, _NONE, _NONE, END_OPTIONAL), +HTML_TAG(param, object, _NONE, _NONE, END_FORBIDDEN), +HTML_TAG(pre, body, _NONE, _NONE, 0), +HTML_TAG(q, body, _NONE, _NONE, 0), +HTML_TAG(s, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(samp, body, _NONE, _NONE, 0), +HTML_TAG(script, html, _NONE, _NONE, 0), +HTML_TAG(select, body, _NONE, _NONE, 0), +HTML_TAG(small, body, _NONE, _NONE, 0), +HTML_TAG(span, body, _NONE, _NONE, CONTAINER), +HTML_TAG(strike, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(strong, body, _NONE, _NONE, 0), +HTML_TAG(style, html, _NONE, _NONE, 0), +HTML_TAG(sub, body, _NONE, _NONE, 0), +HTML_TAG(sup, body, _NONE, _NONE, 0), +HTML_TAG(table, body, _NONE, _NONE, CONTAINER | (1<<TABLE_SHIFT)), +HTML_TAG(tbody, table, _NONE, _NONE, START_OPTIONAL | END_OPTIONAL | (4<<TABLE_SHIFT)), +HTML_TAG(td, tr, _NONE, _NONE, END_OPTIONAL | (6<<TABLE_SHIFT)), +HTML_TAG(textarea, body, _NONE, _NONE, 0), +HTML_TAG(tfoot, table, _NONE, _NONE, END_OPTIONAL | (4<<TABLE_SHIFT)), +HTML_TAG(th, tr, _NONE, _NONE, END_OPTIONAL | (6<<TABLE_SHIFT)), +HTML_TAG(thead, table, _NONE, _NONE, END_OPTIONAL | (4<<TABLE_SHIFT)), +HTML_TAG(title, head, _NONE, _NONE, 0), +HTML_TAG(tr, table, _NONE, _NONE, END_OPTIONAL | (5<<TABLE_SHIFT)), +HTML_TAG(tt, body, _NONE, _NONE, 0), +HTML_TAG(u, body, _NONE, _NONE, DEPRECATED | DTD_LOOSE), +HTML_TAG(ul, body, _NONE, _NONE, CONTAINER), +HTML_TAG(var, body, _NONE, _NONE, 0) + +#undef HTML_TAG diff --git a/source/fitz/xml.c b/source/fitz/xml.c index d1a5ec8..b12cb36 100644 --- a/source/fitz/xml.c +++ b/source/fitz/xml.c @@ -6,6 +6,105 @@ /* #define FZ_XML_SEQ */ +/* We bend the XML parser slightly when it's reading for HTML. + * To do this, we use extra knowledge about HTML tags, expressed + * in the table in a header. */ + +#define START_OPTIONAL 1 +#define END_OPTIONAL 2 +#define END_FORBIDDEN 4 +#define DEPRECATED 8 +#define DTD_LOOSE 16 +#define DTD_FRAMESET 32 +/* The following values are added by us. */ +/* If a tag can contain nested instances of itself, we + * mark it as being a container. */ +#define CONTAINER 64 +/* Table tags autoclose each other in complex ways. */ +#define TABLE_SHIFT 7 +#define TABLE_MASK 7 +/* Which level of a table are we? */ +/* 128 * 1 = TABLE + * 128 * 2 = COLGROUP + * 128 * 3 = COL + * 128 * 4 = THEAD/TBODY/TFOOT + * 128 * 5 = TR + * 128 * 6 = TD/TH + * Any table tag, will be autoclosed by the opening of another table tag + * (within the same container) of a smaller level than it. */ +#define IMPLIES_SHIFT 10 +#define IMPLIES_SHIFT2 17 +#define IMPLIES_SHIFT3 24 +#define IMPLIES_MASK 127 +/* If a tag should always be contained within another one, we + * indicate this with an 'implies'. TABLE tags never imply + * out of the current table. */ + +typedef struct { char tag[16]; int flags; } fz_xml_html_tag_t; + +#define HTML_TAG(A,B,C,D,E) fz_xml_html_tag_ ## A + +enum +{ + fz_xml_html_tag__NONE, +#include "html-tags.h" + , fz_xml_html_tag__NUMTAGS +}; + +#define HTML_TAG(A,B,C,D,E) { # A, E | (fz_xml_html_tag_ ## B << IMPLIES_SHIFT) | (fz_xml_html_tag_ ## C << IMPLIES_SHIFT2) | (fz_xml_html_tag_ ## D << IMPLIES_SHIFT3) } + +fz_xml_html_tag_t html_tags[] = +{ + { "", 0 }, +#include "html-tags.h" +}; + +/* +When parsing XML, we assume that all tags are properly terminated. +i.e. <foo> has </foo> or <foo />. +We currently don't check this at all. In fact, we generate an incorrect +tree if this isn't the case. + +For example: + +<a><b><c></b><d></d></a> + +Will produce: + a + b + cd + +Rather than: + a + bd + c + +Over the course of a large HTML file, this can lead to HUGE "south easterly" skew +in the tree. + +This happens because (when parsing pure xml) when we hit </d>, we don't check that the tag we are closing is actually a <d>. + +So, some heuristics to use when parsing HTML: + * When we open a tag 'foo', if we are immediately in another 'foo', then close the first 'foo' first. + * When we close a tag 'foo', run up the stack looking for an enclosing 'foo'. If we find one, close + everything up to and including that. If we don't find one, don't close anything. + +With these heuristics, we get the following for free: + * A TD closes any other TD. + * A /TR closes and open TD. + * A TR closes any open TR. + +This leaves problems with: + * Nested tables. + * Nested divs. + * Nested spans. + +Tables, divs and spans (let alone nested ones) are problematic anyway. Ignore +this for now. + +We could special case TABLE, DIV and SPAN so appropriate tags don't pop up past them. +*/ + static const struct { const char *name; int c; } html_entities[] = { {"nbsp",160}, {"iexcl",161}, {"cent",162}, {"pound",163}, {"curren",164}, {"yen",165}, {"brvbar",166}, {"sect",167}, @@ -74,6 +173,7 @@ struct parser fz_pool *pool; fz_xml *head; int preserve_white; + int for_html; int depth; #ifdef FZ_XML_SEQ int seq; @@ -372,30 +472,68 @@ static inline int iswhite(int c) return c == ' ' || c == '\r' || c == '\n' || c == '\t'; } -static void xml_emit_open_tag(fz_context *ctx, struct parser *parser, char *a, char *b, int is_text) +static int +find_html_tag(const char *tag, int len) +{ + int low = 0; + int high = nelem(html_tags); + int mid; + + while (low != high) + { + int cmp; + mid = (low + high)>>1; + cmp = strncmp(html_tags[mid].tag, tag, len); + if (cmp == 0) + cmp = html_tags[mid].tag[len]; + if (cmp == 0) + return mid; + if (cmp < 0) + low = mid+1; + else + high = mid; + } + + return fz_xml_html_tag__NONE; +} + +static int xml_emit_open_tag(fz_context *ctx, struct parser *parser, char *a, char *b, int is_text) { fz_xml *head, *tail; - char *ns; size_t size; + int autoclose = 0; if (is_text) size = offsetof(fz_xml, u.text) + b-a+1; else - { - /* skip namespace prefix */ - for (ns = a; ns < b - 1; ++ns) - if (*ns == ':') - a = ns + 1; - size = offsetof(fz_xml, u.d.name) + b-a+1; - } head = fz_pool_alloc(ctx, parser->pool, size); if (is_text) head->down = MAGIC_TEXT; else { - memcpy(head->u.d.name, a, b - a); + if (parser->for_html) + { + int tag_num; + + /* Lowercase the tag */ + char *s = head->u.d.name; + char *t = a; + while (t != b) + { + char c = *t++; + if (c >= 'A' && c <= 'Z') + c += 'a' - 'A'; + *s++ = c; + } + + tag_num = find_html_tag(a, b-a); + if (tag_num != fz_xml_html_tag__NONE && (html_tags[tag_num].flags & END_FORBIDDEN)) + autoclose = 1; + } + else + memcpy(head->u.d.name, a, b - a); head->u.d.name[b - a] = 0; head->u.d.atts = NULL; head->down = NULL; @@ -424,6 +562,8 @@ static void xml_emit_open_tag(fz_context *ctx, struct parser *parser, char *a, c parser->head = head; parser->depth++; + + return autoclose; } static void xml_emit_att_name(fz_context *ctx, struct parser *parser, char *a, char *b) @@ -490,7 +630,7 @@ static void xml_emit_text(fz_context *ctx, struct parser *parser, char *a, char return; } - xml_emit_open_tag(ctx, parser, a, b, 1); + (void)xml_emit_open_tag(ctx, parser, a, b, 1); head = parser->head; /* entities are all longer than UTFmax so runetochar is safe */ @@ -514,7 +654,7 @@ static void xml_emit_cdata(fz_context *ctx, struct parser *parser, char *a, char fz_xml *head; char *s; - xml_emit_open_tag(ctx, parser, a, b, 1); + (void)xml_emit_open_tag(ctx, parser, a, b, 1); head = parser->head; s = head->u.text; @@ -525,10 +665,193 @@ static void xml_emit_cdata(fz_context *ctx, struct parser *parser, char *a, char xml_emit_close_tag(ctx, parser); } +static int +pop_to_tag(fz_context *ctx, struct parser *parser, char *mark, char *p) +{ + fz_xml *to, *head; + + /* Run up from the tag */ + if (parser->for_html) + { + for (to = parser->head; to; to = to->up) + { + char *tag = fz_xml_tag(to); + if (tag && fz_strncasecmp(tag, mark, p-mark) == 0 && tag[p-mark] == 0) + break; /* Found a matching tag */ + } + } + else + { + for (to = parser->head; to; to = to->up) + { + char *tag = fz_xml_tag(to); + if (tag && strncmp(tag, mark, p-mark) == 0 && tag[p-mark] == 0) + break; /* Found a matching tag */ + } + } + + if (to == NULL) + { + /* We didn't find a matching enclosing tag. Don't close anything. */ + return 0; + } + + /* Pop everything up to and including this tag. */ + for (head = parser->head; head != to; head = head->up) + xml_emit_close_tag(ctx, parser); + return 1; +} + +static void +open_implied(fz_context *ctx, struct parser *parser, int tag) +{ + fz_xml *head; + int implied, implied2, implied3, tag_num; + int table_level; + + if (tag == fz_xml_html_tag__NONE) + return; + + implied = (html_tags[tag].flags >> IMPLIES_SHIFT) & IMPLIES_MASK; + implied2 = (html_tags[tag].flags >> IMPLIES_SHIFT2) & IMPLIES_MASK; + implied3 = (html_tags[tag].flags >> IMPLIES_SHIFT3) & IMPLIES_MASK; + if (implied == fz_xml_html_tag__NONE) + return; + if (implied2 == fz_xml_html_tag__NONE) + implied2 = implied; + if (implied3 == fz_xml_html_tag__NONE) + implied3 = implied; + + /* So, check to see whether implied{,2,3} is present. */ + table_level = (html_tags[tag].flags>>TABLE_SHIFT) & TABLE_MASK; + if (table_level != 0) + { + /* Table tag. Autoclose anything within the current TABLE + * with >= table_level. */ + fz_xml *close_to = NULL; + int implied_found = 0; + for (head = parser->head; head; head = head->up) + { + char *tag = fz_xml_tag(head); + int level; + + if (tag == NULL) + continue; + tag_num = find_html_tag(tag, strlen(tag)); + level = (html_tags[tag_num].flags>>TABLE_SHIFT) & TABLE_MASK; + if (level >= table_level) + close_to = head; + if (tag_num == implied || tag_num == implied2 || tag_num == implied3) + implied_found = 1; + if (tag_num == fz_xml_html_tag_table) + break; + } + if (close_to) + { + for (head = parser->head; head; head = head->up) + { + xml_emit_close_tag(ctx, parser); + if (head == close_to) + break; + } + } + if (!implied_found) + { + char *tag = html_tags[implied].tag; + open_implied(ctx, parser, implied); + xml_emit_open_tag(ctx, parser, tag, tag + strlen(tag), 0); + } + } + else + { + /* Non table tag. Open by implication. */ + for (head = parser->head; head; head = head->up) + { + char *tag = fz_xml_tag(head); + + if (tag == NULL) + continue; + tag_num = find_html_tag(tag, strlen(tag)); + if (tag_num == implied || tag_num == implied2 || tag_num == implied3) + break; + } + if (head == NULL) + { + char *s = html_tags[implied].tag; + open_implied(ctx, parser, implied); + (void)xml_emit_open_tag(ctx, parser, s, s+strlen(s), 0); + } + } +} + +/* When we meet a new tag, before we open it, there may be + * things we should do first... */ +static void +pre_open_tag(fz_context *ctx, struct parser *parser, char *mark, char *p) +{ + fz_xml *head = parser->head; + int tag_num; + + if (!parser->for_html) + return; + + tag_num = find_html_tag(mark, p-mark); + + if (tag_num == fz_xml_html_tag__NONE) + return; + + if ((html_tags[tag_num].flags & CONTAINER) == 0) + { + /* We aren't a container flag. This means that we should autoclose up to + * any matching tags in the same container. */ + fz_xml *which; + for (which = head; which; which = which->up) + { + char *tag = fz_xml_tag(which); + int tag_num2 = tag ? find_html_tag(tag, strlen(tag)) : fz_xml_html_tag__NONE; + if (tag_num == tag_num2) + { + /* Autoclose everything from head to which inclusive */ + while (1) + { + int done = (head == which); + xml_emit_close_tag(ctx, parser); + head = head->up; + if (done) + break; + } + break; + } + if (html_tags[tag_num2].flags & CONTAINER) + { + /* Stop searching */ + break; + } + } + } + + /* Now, autoopen any tags implied by this one. */ + open_implied(ctx, parser, tag_num); +} + +static char * +skip_namespace_prefix(char *mark, char *p) +{ + char *ns; + + for (ns = mark; ns < p - 1; ++ns) + if (*ns == ':') + mark = ns + 1; + + return mark; +} + static char *xml_parse_document_imp(fz_context *ctx, struct parser *parser, char *p) { char *mark; int quote; + int autoclose; + char *q; parse_text: mark = p; @@ -602,19 +925,27 @@ parse_processing_instruction: parse_closing_element: while (iswhite(*p)) ++p; + mark = p; while (isname(*p)) ++p; + q = p; while (iswhite(*p)) ++p; if (*p != '>') return "syntax error in closing element"; - xml_emit_close_tag(ctx, parser); + mark = skip_namespace_prefix(mark, q); + if (pop_to_tag(ctx, parser, mark, q)) + xml_emit_close_tag(ctx, parser); ++p; goto parse_text; parse_element_name: mark = p; while (isname(*p)) ++p; - xml_emit_open_tag(ctx, parser, mark, p, 0); + mark = skip_namespace_prefix(mark, p); + pre_open_tag(ctx, parser, mark, p); + autoclose = xml_emit_open_tag(ctx, parser, mark, p, 0); if (*p == '>') { + if (autoclose) + xml_emit_close_tag(ctx, parser); ++p; if (*p == '\n') ++p; /* must skip linebreak immediately after an opening tag */ goto parse_text; @@ -633,6 +964,8 @@ parse_attributes: if (isname(*p)) goto parse_attribute_name; if (*p == '>') { + if (autoclose) + xml_emit_close_tag(ctx, parser); ++p; if (*p == '\n') ++p; /* must skip linebreak immediately after an opening tag */ goto parse_text; @@ -766,7 +1099,7 @@ static char *convert_to_utf8(fz_context *ctx, unsigned char *s, size_t n, int *d preserve_white: whether to keep or delete all-whitespace nodes. */ fz_xml_doc * -fz_parse_xml(fz_context *ctx, fz_buffer *buf, int preserve_white) +fz_parse_xml(fz_context *ctx, fz_buffer *buf, int preserve_white, int for_html) { struct parser parser; fz_xml_doc *xml = NULL; @@ -788,6 +1121,7 @@ fz_parse_xml(fz_context *ctx, fz_buffer *buf, int preserve_white) parser.pool = fz_new_pool(ctx); parser.head = &root; parser.preserve_white = preserve_white; + parser.for_html = for_html; parser.depth = 0; #ifdef FZ_XML_SEQ parser.seq = 0; diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c index b1aae2b..9cea040 100644 --- a/source/html/epub-doc.c +++ b/source/html/epub-doc.c @@ -636,7 +636,7 @@ epub_parse_ncx(fz_context *ctx, epub_document *doc, const char *path) { fz_dirname(base_uri, path, sizeof base_uri); buf = fz_read_archive_entry(ctx, zip, path); - ncx = fz_parse_xml(ctx, buf, 0); + ncx = fz_parse_xml(ctx, buf, 0, 0); doc->outline = epub_parse_ncx_imp(ctx, doc, fz_xml_find_down(fz_xml_root(ncx), "navMap"), base_uri); } fz_always(ctx) @@ -687,7 +687,7 @@ epub_parse_header(fz_context *ctx, epub_document *doc) /* parse META-INF/container.xml to find OPF */ buf = fz_read_archive_entry(ctx, zip, "META-INF/container.xml"); - container_xml = fz_parse_xml(ctx, buf, 0); + container_xml = fz_parse_xml(ctx, buf, 0, 0); fz_drop_buffer(ctx, buf); buf = NULL; @@ -703,7 +703,7 @@ epub_parse_header(fz_context *ctx, epub_document *doc) /* parse OPF to find NCX and spine */ buf = fz_read_archive_entry(ctx, zip, full_path); - content_opf = fz_parse_xml(ctx, buf, 0); + content_opf = fz_parse_xml(ctx, buf, 0, 0); fz_drop_buffer(ctx, buf); buf = NULL; diff --git a/source/html/html-parse.c b/source/html/html-parse.c index 92b8db2..add1bfd 100644 --- a/source/html/html-parse.c +++ b/source/html/html-parse.c @@ -1050,7 +1050,7 @@ load_fb2_images(fz_context *ctx, fz_xml *root) fz_xml *fictionbook, *binary; fz_tree *images = NULL; - fictionbook = fz_xml_find(root, "FictionBook"); + fictionbook = fz_xml_find(root, "fictionbook"); for (binary = fz_xml_find_down(fictionbook, "binary"); binary; binary = fz_xml_find_next(binary, "binary")) { const char *id = fz_xml_att(binary, "id"); @@ -1284,7 +1284,7 @@ fz_parse_html(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const cha g.last_brk_cls = UCDN_LINEBREAK_CLASS_OP; g.styles = NULL; - xml = fz_parse_xml(ctx, buf, 1); + xml = fz_parse_xml(ctx, buf, 1, 1); root = fz_xml_root(xml); fz_try(ctx) @@ -1302,7 +1302,7 @@ fz_parse_html(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const cha fz_try(ctx) { - if (fz_xml_find(root, "FictionBook")) + if (fz_xml_find(root, "fictionbook")) { g.is_fb2 = 1; fz_parse_css(ctx, g.css, fb2_default_css, "<default:fb2>"); @@ -1364,7 +1364,7 @@ fz_parse_html(fz_context *ctx, fz_html_font_set *set, fz_archive *zip, const cha if (g.is_fb2) { - node = fz_xml_find(root, "FictionBook"); + node = fz_xml_find(root, "fictionbook"); node = fz_xml_find_down(node, "description"); node = fz_xml_find_down(node, "title-info"); node = fz_xml_find_down(node, "book-title"); diff --git a/source/svg/svg-doc.c b/source/svg/svg-doc.c index 1d3162d..794a25f 100644 --- a/source/svg/svg-doc.c +++ b/source/svg/svg-doc.c @@ -126,7 +126,7 @@ svg_open_document_with_buffer(fz_context *ctx, fz_buffer *buf, const char *base_ fz_try(ctx) { - doc->xml = fz_parse_xml(ctx, buf, 0); + doc->xml = fz_parse_xml(ctx, buf, 0, 0); doc->root = fz_xml_root(doc->xml); svg_build_id_map(ctx, doc, doc->root); } diff --git a/source/xps/xps-doc.c b/source/xps/xps-doc.c index b71182c..1731aae 100644 --- a/source/xps/xps-doc.c +++ b/source/xps/xps-doc.c @@ -290,7 +290,7 @@ xps_parse_metadata(fz_context *ctx, xps_document *doc, xps_part *part, xps_fixdo doc->base_uri = buf; doc->part_uri = part->name; - xml = fz_parse_xml(ctx, part->data, 0); + xml = fz_parse_xml(ctx, part->data, 0, 0); fz_try(ctx) { xps_parse_metadata_imp(ctx, doc, fz_xml_root(xml), fixdoc); @@ -376,7 +376,7 @@ xps_load_fixed_page(fz_context *ctx, xps_document *doc, xps_fixpage *page) part = xps_read_part(ctx, doc, page->name); fz_try(ctx) { - xml = fz_parse_xml(ctx, part->data, 0); + xml = fz_parse_xml(ctx, part->data, 0, 0); root = fz_xml_root(xml); if (!root) diff --git a/source/xps/xps-outline.c b/source/xps/xps-outline.c index dd44275..c4dda2a 100644 --- a/source/xps/xps-outline.c +++ b/source/xps/xps-outline.c @@ -91,7 +91,7 @@ xps_load_document_structure(fz_context *ctx, xps_document *doc, xps_fixdoc *fixd part = xps_read_part(ctx, doc, fixdoc->outline); fz_try(ctx) { - xml = fz_parse_xml(ctx, part->data, 0); + xml = fz_parse_xml(ctx, part->data, 0, 0); outline = xps_parse_document_structure(ctx, doc, fz_xml_root(xml)); } fz_always(ctx) diff --git a/source/xps/xps-resource.c b/source/xps/xps-resource.c index ed6f131..c8a4133 100644 --- a/source/xps/xps-resource.c +++ b/source/xps/xps-resource.c @@ -72,7 +72,7 @@ xps_parse_remote_resource_dictionary(fz_context *ctx, xps_document *doc, char *b part = xps_read_part(ctx, doc, part_name); fz_try(ctx) { - xml = fz_parse_xml(ctx, part->data, 0); + xml = fz_parse_xml(ctx, part->data, 0, 0); if (!fz_xml_is_tag(fz_xml_root(xml), "ResourceDictionary")) fz_throw(ctx, FZ_ERROR_GENERIC, "expected ResourceDictionary element"); diff --git a/thirdparty/mujs b/thirdparty/mujs index 14dc935..00d4606 160000 --- a/thirdparty/mujs +++ b/thirdparty/mujs @@ -1 +1 @@ -Subproject commit 14dc9355bd71818cf01c1c690c1c91a0978ea9b8 +Subproject commit 00d4606c3baf813b7b1c176823b2729bf51002a2 http://git.ghostscript.com/?p=mupdf.git;a=commit;h=91782a434877d84b828fdeef20c569d4c3b4071b -- MuPDF library Artifex Software, Inc.