bf827ea97dd4931082ca269b0d36acb957656914
[WebKit-https.git] / Source / WebCore / xml / parser / XMLDocumentParserLibxml2.cpp
1 /*
2  * Copyright (C) 2000 Peter Kelly <pmk@post.com>
3  * Copyright (C) 2005-2017 Apple Inc. All rights reserved.
4  * Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
5  * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
6  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
7  * Copyright (C) 2008 Holger Hans Peter Freyther
8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9  * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
10  * Copyright (C) 2013 Samsung Electronics. All rights reserved.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27
28 #include "config.h"
29 #include "XMLDocumentParser.h"
30
31 #include "CDATASection.h"
32 #include "Comment.h"
33 #include "CachedResourceLoader.h"
34 #include "Document.h"
35 #include "DocumentFragment.h"
36 #include "DocumentType.h"
37 #include "Frame.h"
38 #include "FrameLoader.h"
39 #include "HTMLEntityParser.h"
40 #include "HTMLHtmlElement.h"
41 #include "HTMLTemplateElement.h"
42 #include "InlineClassicScript.h"
43 #include "PendingScript.h"
44 #include "ProcessingInstruction.h"
45 #include "ResourceError.h"
46 #include "ResourceResponse.h"
47 #include "ScriptElement.h"
48 #include "ScriptSourceCode.h"
49 #include "Settings.h"
50 #include "SharedBuffer.h"
51 #include "StyleScope.h"
52 #include "TransformSource.h"
53 #include "XMLNSNames.h"
54 #include "XMLDocumentParserScope.h"
55 #include <libxml/parserInternals.h>
56 #include <wtf/StringExtras.h>
57 #include <wtf/unicode/UTF8.h>
58
59 #if ENABLE(XSLT)
60 #include "XMLTreeViewer.h"
61 #include <libxslt/xslt.h>
62 #endif
63
64 namespace WebCore {
65
66 #if ENABLE(XSLT)
67
68 static inline bool shouldRenderInXMLTreeViewerMode(Document& document)
69 {
70     if (document.sawElementsInKnownNamespaces())
71         return false;
72
73     if (document.transformSourceDocument())
74         return false;
75
76     auto* frame = document.frame();
77     if (!frame)
78         return false;
79
80     if (!frame->settings().developerExtrasEnabled())
81         return false;
82
83     if (frame->tree().parent())
84         return false; // This document is not in a top frame
85
86     return true;
87 }
88
89 #endif
90
91 class PendingCallbacks {
92     WTF_MAKE_FAST_ALLOCATED;
93 public:
94     void appendStartElementNSCallback(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int numNamespaces, const xmlChar** namespaces, int numAttributes, int numDefaulted, const xmlChar** attributes)
95     {
96         auto callback = std::make_unique<PendingStartElementNSCallback>();
97
98         callback->xmlLocalName = xmlStrdup(xmlLocalName);
99         callback->xmlPrefix = xmlStrdup(xmlPrefix);
100         callback->xmlURI = xmlStrdup(xmlURI);
101         callback->numNamespaces = numNamespaces;
102         callback->namespaces = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * numNamespaces * 2));
103         for (int i = 0; i < numNamespaces * 2 ; i++)
104             callback->namespaces[i] = xmlStrdup(namespaces[i]);
105         callback->numAttributes = numAttributes;
106         callback->numDefaulted = numDefaulted;
107         callback->attributes = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * numAttributes * 5));
108         for (int i = 0; i < numAttributes; i++) {
109             // Each attribute has 5 elements in the array:
110             // name, prefix, uri, value and an end pointer.
111
112             for (int j = 0; j < 3; j++)
113                 callback->attributes[i * 5 + j] = xmlStrdup(attributes[i * 5 + j]);
114
115             int len = attributes[i * 5 + 4] - attributes[i * 5 + 3];
116
117             callback->attributes[i * 5 + 3] = xmlStrndup(attributes[i * 5 + 3], len);
118             callback->attributes[i * 5 + 4] = callback->attributes[i * 5 + 3] + len;
119         }
120
121         m_callbacks.append(WTFMove(callback));
122     }
123
124     void appendEndElementNSCallback()
125     {
126         m_callbacks.append(std::make_unique<PendingEndElementNSCallback>());
127     }
128
129     void appendCharactersCallback(const xmlChar* s, int len)
130     {
131         auto callback = std::make_unique<PendingCharactersCallback>();
132
133         callback->s = xmlStrndup(s, len);
134         callback->len = len;
135
136         m_callbacks.append(WTFMove(callback));
137     }
138
139     void appendProcessingInstructionCallback(const xmlChar* target, const xmlChar* data)
140     {
141         auto callback = std::make_unique<PendingProcessingInstructionCallback>();
142
143         callback->target = xmlStrdup(target);
144         callback->data = xmlStrdup(data);
145
146         m_callbacks.append(WTFMove(callback));
147     }
148
149     void appendCDATABlockCallback(const xmlChar* s, int len)
150     {
151         auto callback = std::make_unique<PendingCDATABlockCallback>();
152
153         callback->s = xmlStrndup(s, len);
154         callback->len = len;
155
156         m_callbacks.append(WTFMove(callback));
157     }
158
159     void appendCommentCallback(const xmlChar* s)
160     {
161         auto callback = std::make_unique<PendingCommentCallback>();
162
163         callback->s = xmlStrdup(s);
164
165         m_callbacks.append(WTFMove(callback));
166     }
167
168     void appendInternalSubsetCallback(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
169     {
170         auto callback = std::make_unique<PendingInternalSubsetCallback>();
171
172         callback->name = xmlStrdup(name);
173         callback->externalID = xmlStrdup(externalID);
174         callback->systemID = xmlStrdup(systemID);
175
176         m_callbacks.append(WTFMove(callback));
177     }
178
179     void appendErrorCallback(XMLErrors::ErrorType type, const xmlChar* message, OrdinalNumber lineNumber, OrdinalNumber columnNumber)
180     {
181         auto callback = std::make_unique<PendingErrorCallback>();
182
183         callback->message = xmlStrdup(message);
184         callback->type = type;
185         callback->lineNumber = lineNumber;
186         callback->columnNumber = columnNumber;
187
188         m_callbacks.append(WTFMove(callback));
189     }
190
191     void callAndRemoveFirstCallback(XMLDocumentParser* parser)
192     {
193         std::unique_ptr<PendingCallback> callback = m_callbacks.takeFirst();
194         callback->call(parser);
195     }
196
197     bool isEmpty() const { return m_callbacks.isEmpty(); }
198
199 private:
200     struct PendingCallback {
201         virtual ~PendingCallback() { }
202         virtual void call(XMLDocumentParser* parser) = 0;
203     };
204
205     struct PendingStartElementNSCallback : public PendingCallback {
206         virtual ~PendingStartElementNSCallback()
207         {
208             xmlFree(xmlLocalName);
209             xmlFree(xmlPrefix);
210             xmlFree(xmlURI);
211             for (int i = 0; i < numNamespaces * 2; i++)
212                 xmlFree(namespaces[i]);
213             xmlFree(namespaces);
214             for (int i = 0; i < numAttributes; i++) {
215                 for (int j = 0; j < 4; j++)
216                     xmlFree(attributes[i * 5 + j]);
217             }
218             xmlFree(attributes);
219         }
220
221         void call(XMLDocumentParser* parser) override
222         {
223             parser->startElementNs(xmlLocalName, xmlPrefix, xmlURI, numNamespaces, const_cast<const xmlChar**>(namespaces), numAttributes, numDefaulted, const_cast<const xmlChar**>(attributes));
224         }
225
226         xmlChar* xmlLocalName;
227         xmlChar* xmlPrefix;
228         xmlChar* xmlURI;
229         int numNamespaces;
230         xmlChar** namespaces;
231         int numAttributes;
232         int numDefaulted;
233         xmlChar** attributes;
234     };
235
236     struct PendingEndElementNSCallback : public PendingCallback {
237         void call(XMLDocumentParser* parser) override
238         {
239             parser->endElementNs();
240         }
241     };
242
243     struct PendingCharactersCallback : public PendingCallback {
244         virtual ~PendingCharactersCallback()
245         {
246             xmlFree(s);
247         }
248
249         void call(XMLDocumentParser* parser) override
250         {
251             parser->characters(s, len);
252         }
253
254         xmlChar* s;
255         int len;
256     };
257
258     struct PendingProcessingInstructionCallback : public PendingCallback {
259         virtual ~PendingProcessingInstructionCallback()
260         {
261             xmlFree(target);
262             xmlFree(data);
263         }
264
265         void call(XMLDocumentParser* parser) override
266         {
267             parser->processingInstruction(target, data);
268         }
269
270         xmlChar* target;
271         xmlChar* data;
272     };
273
274     struct PendingCDATABlockCallback : public PendingCallback {
275         virtual ~PendingCDATABlockCallback()
276         {
277             xmlFree(s);
278         }
279
280         void call(XMLDocumentParser* parser) override
281         {
282             parser->cdataBlock(s, len);
283         }
284
285         xmlChar* s;
286         int len;
287     };
288
289     struct PendingCommentCallback : public PendingCallback {
290         virtual ~PendingCommentCallback()
291         {
292             xmlFree(s);
293         }
294
295         void call(XMLDocumentParser* parser) override
296         {
297             parser->comment(s);
298         }
299
300         xmlChar* s;
301     };
302
303     struct PendingInternalSubsetCallback : public PendingCallback {
304         virtual ~PendingInternalSubsetCallback()
305         {
306             xmlFree(name);
307             xmlFree(externalID);
308             xmlFree(systemID);
309         }
310
311         void call(XMLDocumentParser* parser) override
312         {
313             parser->internalSubset(name, externalID, systemID);
314         }
315
316         xmlChar* name;
317         xmlChar* externalID;
318         xmlChar* systemID;
319     };
320
321     struct PendingErrorCallback: public PendingCallback {
322         virtual ~PendingErrorCallback()
323         {
324             xmlFree(message);
325         }
326
327         void call(XMLDocumentParser* parser) override
328         {
329             parser->handleError(type, reinterpret_cast<char*>(message), TextPosition(lineNumber, columnNumber));
330         }
331
332         XMLErrors::ErrorType type;
333         xmlChar* message;
334         OrdinalNumber lineNumber;
335         OrdinalNumber columnNumber;
336     };
337
338     Deque<std::unique_ptr<PendingCallback>> m_callbacks;
339 };
340 // --------------------------------
341
342 static int globalDescriptor = 0;
343 static ThreadIdentifier libxmlLoaderThread = 0;
344
345 static int matchFunc(const char*)
346 {
347     // Only match loads initiated due to uses of libxml2 from within XMLDocumentParser to avoid
348     // interfering with client applications that also use libxml2.  http://bugs.webkit.org/show_bug.cgi?id=17353
349     return XMLDocumentParserScope::currentCachedResourceLoader && currentThread() == libxmlLoaderThread;
350 }
351
352 class OffsetBuffer {
353     WTF_MAKE_FAST_ALLOCATED;
354 public:
355     OffsetBuffer(Vector<char> buffer)
356         : m_buffer(WTFMove(buffer))
357         , m_currentOffset(0)
358     {
359     }
360
361     int readOutBytes(char* outputBuffer, unsigned askedToRead)
362     {
363         unsigned bytesLeft = m_buffer.size() - m_currentOffset;
364         unsigned lenToCopy = std::min(askedToRead, bytesLeft);
365         if (lenToCopy) {
366             memcpy(outputBuffer, m_buffer.data() + m_currentOffset, lenToCopy);
367             m_currentOffset += lenToCopy;
368         }
369         return lenToCopy;
370     }
371
372 private:
373     Vector<char> m_buffer;
374     unsigned m_currentOffset;
375 };
376
377 static inline void setAttributes(Element* element, Vector<Attribute>& attributeVector, ParserContentPolicy parserContentPolicy)
378 {
379     if (!scriptingContentIsAllowed(parserContentPolicy))
380         element->stripScriptingAttributes(attributeVector);
381     element->parserSetAttributes(attributeVector);
382 }
383
384 static void switchToUTF16(xmlParserCtxtPtr ctxt)
385 {
386     // Hack around libxml2's lack of encoding overide support by manually
387     // resetting the encoding to UTF-16 before every chunk.  Otherwise libxml
388     // will detect <?xml version="1.0" encoding="<encoding name>"?> blocks
389     // and switch encodings, causing the parse to fail.
390
391     // FIXME: Can we just use XML_PARSE_IGNORE_ENC now?
392
393     const UChar BOM = 0xFEFF;
394     const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
395     xmlSwitchEncoding(ctxt, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
396 }
397
398 static bool shouldAllowExternalLoad(const URL& url)
399 {
400     String urlString = url.string();
401
402     // On non-Windows platforms libxml asks for this URL, the
403     // "XML_XML_DEFAULT_CATALOG", on initialization.
404     if (urlString == "file:///etc/xml/catalog")
405         return false;
406
407     // On Windows, libxml computes a URL relative to where its DLL resides.
408     if (urlString.startsWith("file:///", false) && urlString.endsWith("/etc/catalog", false))
409         return false;
410
411     // The most common DTD.  There isn't much point in hammering www.w3c.org
412     // by requesting this URL for every XHTML document.
413     if (urlString.startsWith("http://www.w3.org/TR/xhtml", false))
414         return false;
415
416     // Similarly, there isn't much point in requesting the SVG DTD.
417     if (urlString.startsWith("http://www.w3.org/Graphics/SVG", false))
418         return false;
419
420     // The libxml doesn't give us a lot of context for deciding whether to
421     // allow this request.  In the worst case, this load could be for an
422     // external entity and the resulting document could simply read the
423     // retrieved content.  If we had more context, we could potentially allow
424     // the parser to load a DTD.  As things stand, we take the conservative
425     // route and allow same-origin requests only.
426     if (!XMLDocumentParserScope::currentCachedResourceLoader->document()->securityOrigin().canRequest(url)) {
427         XMLDocumentParserScope::currentCachedResourceLoader->printAccessDeniedMessage(url);
428         return false;
429     }
430
431     return true;
432 }
433
434 static void* openFunc(const char* uri)
435 {
436     ASSERT(XMLDocumentParserScope::currentCachedResourceLoader);
437     ASSERT(currentThread() == libxmlLoaderThread);
438
439     URL url(URL(), uri);
440
441     if (!shouldAllowExternalLoad(url))
442         return &globalDescriptor;
443
444     ResourceError error;
445     ResourceResponse response;
446     RefPtr<SharedBuffer> data;
447
448
449     {
450         CachedResourceLoader* cachedResourceLoader = XMLDocumentParserScope::currentCachedResourceLoader;
451         XMLDocumentParserScope scope(nullptr);
452         // FIXME: We should restore the original global error handler as well.
453
454         if (cachedResourceLoader->frame())
455             cachedResourceLoader->frame()->loader().loadResourceSynchronously(url, AllowStoredCredentials, ClientCredentialPolicy::MayAskClientForCredentials, error, response, data);
456     }
457
458     // We have to check the URL again after the load to catch redirects.
459     // See <https://bugs.webkit.org/show_bug.cgi?id=21963>.
460     if (!shouldAllowExternalLoad(response.url()))
461         return &globalDescriptor;
462     Vector<char> buffer;
463     if (data)
464         buffer.append(data->data(), data->size());
465     return new OffsetBuffer(WTFMove(buffer));
466 }
467
468 static int readFunc(void* context, char* buffer, int len)
469 {
470     // Do 0-byte reads in case of a null descriptor
471     if (context == &globalDescriptor)
472         return 0;
473
474     OffsetBuffer* data = static_cast<OffsetBuffer*>(context);
475     return data->readOutBytes(buffer, len);
476 }
477
478 static int writeFunc(void*, const char*, int)
479 {
480     // Always just do 0-byte writes
481     return 0;
482 }
483
484 static int closeFunc(void* context)
485 {
486     if (context != &globalDescriptor) {
487         OffsetBuffer* data = static_cast<OffsetBuffer*>(context);
488         delete data;
489     }
490     return 0;
491 }
492
493 #if ENABLE(XSLT)
494 static void errorFunc(void*, const char*, ...)
495 {
496     // FIXME: It would be nice to display error messages somewhere.
497 }
498 #endif
499
500 static bool didInit = false;
501
502 Ref<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData)
503 {
504     if (!didInit) {
505         xmlInitParser();
506         xmlRegisterInputCallbacks(matchFunc, openFunc, readFunc, closeFunc);
507         xmlRegisterOutputCallbacks(matchFunc, openFunc, writeFunc, closeFunc);
508         libxmlLoaderThread = currentThread();
509         didInit = true;
510     }
511
512     xmlParserCtxtPtr parser = xmlCreatePushParserCtxt(handlers, 0, 0, 0, 0);
513     parser->_private = userData;
514
515     // Substitute entities.
516     xmlCtxtUseOptions(parser, XML_PARSE_NOENT | XML_PARSE_HUGE);
517
518     switchToUTF16(parser);
519
520     return adoptRef(*new XMLParserContext(parser));
521 }
522
523
524 // Chunk should be encoded in UTF-8
525 RefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const CString& chunk)
526 {
527     if (!didInit) {
528         xmlInitParser();
529         xmlRegisterInputCallbacks(matchFunc, openFunc, readFunc, closeFunc);
530         xmlRegisterOutputCallbacks(matchFunc, openFunc, writeFunc, closeFunc);
531         libxmlLoaderThread = currentThread();
532         didInit = true;
533     }
534
535     // appendFragmentSource() checks that the length doesn't overflow an int.
536     xmlParserCtxtPtr parser = xmlCreateMemoryParserCtxt(chunk.data(), chunk.length());
537
538     if (!parser)
539         return 0;
540
541     memcpy(parser->sax, handlers, sizeof(xmlSAXHandler));
542
543     // Substitute entities.
544     // FIXME: Why is XML_PARSE_NODICT needed? This is different from what createStringParser does.
545     xmlCtxtUseOptions(parser, XML_PARSE_NODICT | XML_PARSE_NOENT | XML_PARSE_HUGE);
546
547     // Internal initialization
548     parser->sax2 = 1;
549     parser->instate = XML_PARSER_CONTENT; // We are parsing a CONTENT
550     parser->depth = 0;
551     parser->str_xml = xmlDictLookup(parser->dict, BAD_CAST "xml", 3);
552     parser->str_xmlns = xmlDictLookup(parser->dict, BAD_CAST "xmlns", 5);
553     parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36);
554     parser->_private = userData;
555
556     return adoptRef(*new XMLParserContext(parser));
557 }
558
559 // --------------------------------
560
561 bool XMLDocumentParser::supportsXMLVersion(const String& version)
562 {
563     return version == "1.0";
564 }
565
566 XMLDocumentParser::XMLDocumentParser(Document& document, FrameView* frameView)
567     : ScriptableDocumentParser(document)
568     , m_view(frameView)
569     , m_pendingCallbacks(std::make_unique<PendingCallbacks>())
570     , m_currentNode(&document)
571     , m_scriptStartPosition(TextPosition::belowRangePosition())
572 {
573 }
574
575 XMLDocumentParser::XMLDocumentParser(DocumentFragment& fragment, Element* parentElement, ParserContentPolicy parserContentPolicy)
576     : ScriptableDocumentParser(fragment.document(), parserContentPolicy)
577     , m_pendingCallbacks(std::make_unique<PendingCallbacks>())
578     , m_currentNode(&fragment)
579     , m_scriptStartPosition(TextPosition::belowRangePosition())
580     , m_parsingFragment(true)
581 {
582     fragment.ref();
583
584     // Add namespaces based on the parent node
585     Vector<Element*> elemStack;
586     while (parentElement) {
587         elemStack.append(parentElement);
588
589         ContainerNode* node = parentElement->parentNode();
590         if (!is<Element>(node))
591             break;
592         parentElement = downcast<Element>(node);
593     }
594
595     if (elemStack.isEmpty())
596         return;
597
598     // FIXME: Share code with isDefaultNamespace() per http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syntax.html#parsing-xhtml-fragments
599     for (; !elemStack.isEmpty(); elemStack.removeLast()) {
600         Element* element = elemStack.last();
601         if (element->hasAttributes()) {
602             for (const Attribute& attribute : element->attributesIterator()) {
603                 if (attribute.localName() == xmlnsAtom)
604                     m_defaultNamespaceURI = attribute.value();
605                 else if (attribute.prefix() == xmlnsAtom)
606                     m_prefixToNamespaceMap.set(attribute.localName(), attribute.value());
607             }
608         }
609     }
610
611     if (m_defaultNamespaceURI.isNull())
612         m_defaultNamespaceURI = parentElement->namespaceURI();
613 }
614
615 XMLParserContext::~XMLParserContext()
616 {
617     if (m_context->myDoc)
618         xmlFreeDoc(m_context->myDoc);
619     xmlFreeParserCtxt(m_context);
620 }
621
622 XMLDocumentParser::~XMLDocumentParser()
623 {
624     // The XMLDocumentParser will always be detached before being destroyed.
625     ASSERT(m_currentNodeStack.isEmpty());
626     ASSERT(!m_currentNode);
627
628     // FIXME: m_pendingScript handling should be moved into XMLDocumentParser.cpp!
629     if (m_pendingScript)
630         m_pendingScript->clearClient();
631 }
632
633 void XMLDocumentParser::doWrite(const String& parseString)
634 {
635     ASSERT(!isDetached());
636     if (!m_context)
637         initializeParserContext();
638
639     // Protect the libxml context from deletion during a callback
640     RefPtr<XMLParserContext> context = m_context;
641
642     // libXML throws an error if you try to switch the encoding for an empty string.
643     if (parseString.length()) {
644         // JavaScript may cause the parser to detach during xmlParseChunk
645         // keep this alive until this function is done.
646         Ref<XMLDocumentParser> protectedThis(*this);
647
648         XMLDocumentParserScope scope(&document()->cachedResourceLoader());
649
650         // FIXME: Can we parse 8-bit strings directly as Latin-1 instead of upconverting to UTF-16?
651         switchToUTF16(context->context());
652         xmlParseChunk(context->context(), reinterpret_cast<const char*>(StringView(parseString).upconvertedCharacters().get()), sizeof(UChar) * parseString.length(), 0);
653
654         // JavaScript (which may be run under the xmlParseChunk callstack) may
655         // cause the parser to be stopped or detached.
656         if (isStopped())
657             return;
658     }
659
660     // FIXME: Why is this here?  And why is it after we process the passed source?
661     if (document()->decoder() && document()->decoder()->sawError()) {
662         // If the decoder saw an error, report it as fatal (stops parsing)
663         TextPosition position(OrdinalNumber::fromOneBasedInt(context->context()->input->line), OrdinalNumber::fromOneBasedInt(context->context()->input->col));
664         handleError(XMLErrors::fatal, "Encoding error", position);
665     }
666 }
667
668 static inline String toString(const xmlChar* string, size_t size)
669 {
670     return String::fromUTF8(reinterpret_cast<const char*>(string), size);
671 }
672
673 static inline String toString(const xmlChar* string)
674 {
675     return String::fromUTF8(reinterpret_cast<const char*>(string));
676 }
677
678 static inline AtomicString toAtomicString(const xmlChar* string, size_t size)
679 {
680     return AtomicString::fromUTF8(reinterpret_cast<const char*>(string), size);
681 }
682
683 static inline AtomicString toAtomicString(const xmlChar* string)
684 {
685     return AtomicString::fromUTF8(reinterpret_cast<const char*>(string));
686 }
687
688 struct _xmlSAX2Namespace {
689     const xmlChar* prefix;
690     const xmlChar* uri;
691 };
692 typedef struct _xmlSAX2Namespace xmlSAX2Namespace;
693
694 static inline bool handleNamespaceAttributes(Vector<Attribute>& prefixedAttributes, const xmlChar** libxmlNamespaces, int numNamespaces)
695 {
696     xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNamespaces);
697     for (int i = 0; i < numNamespaces; i++) {
698         AtomicString namespaceQName = xmlnsAtom;
699         AtomicString namespaceURI = toAtomicString(namespaces[i].uri);
700         if (namespaces[i].prefix)
701             namespaceQName = "xmlns:" + toString(namespaces[i].prefix);
702
703         auto result = Element::parseAttributeName(XMLNSNames::xmlnsNamespaceURI, namespaceQName);
704         if (result.hasException())
705             return false;
706
707         prefixedAttributes.append(Attribute(result.releaseReturnValue(), namespaceURI));
708     }
709     return true;
710 }
711
712 struct _xmlSAX2Attributes {
713     const xmlChar* localname;
714     const xmlChar* prefix;
715     const xmlChar* uri;
716     const xmlChar* value;
717     const xmlChar* end;
718 };
719 typedef struct _xmlSAX2Attributes xmlSAX2Attributes;
720
721 static inline bool handleElementAttributes(Vector<Attribute>& prefixedAttributes, const xmlChar** libxmlAttributes, int numAttributes)
722 {
723     xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes);
724     for (int i = 0; i < numAttributes; i++) {
725         int valueLength = static_cast<int>(attributes[i].end - attributes[i].value);
726         AtomicString attrValue = toAtomicString(attributes[i].value, valueLength);
727         String attrPrefix = toString(attributes[i].prefix);
728         AtomicString attrURI = attrPrefix.isEmpty() ? nullAtom : toAtomicString(attributes[i].uri);
729         AtomicString attrQName = attrPrefix.isEmpty() ? toAtomicString(attributes[i].localname) : attrPrefix + ":" + toString(attributes[i].localname);
730
731         auto result = Element::parseAttributeName(attrURI, attrQName);
732         if (result.hasException())
733             return false;
734
735         prefixedAttributes.append(Attribute(result.releaseReturnValue(), attrValue));
736     }
737     return true;
738 }
739
740 // This is a hack around https://bugzilla.gnome.org/show_bug.cgi?id=502960
741 // Otherwise libxml doesn't include namespace for parsed entities, breaking entity
742 // expansion for all entities containing elements.
743 static inline bool hackAroundLibXMLEntityParsingBug()
744 {
745 #if LIBXML_VERSION >= 20704
746     // This bug has been fixed in libxml 2.7.4.
747     return false;
748 #else
749     return true;
750 #endif
751 }
752
753 void XMLDocumentParser::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int numNamespaces, const xmlChar** libxmlNamespaces, int numAttributes, int numDefaulted, const xmlChar** libxmlAttributes)
754 {
755     if (isStopped())
756         return;
757
758     if (m_parserPaused) {
759         m_pendingCallbacks->appendStartElementNSCallback(xmlLocalName, xmlPrefix, xmlURI, numNamespaces, libxmlNamespaces, numAttributes, numDefaulted, libxmlAttributes);
760         return;
761     }
762
763     if (!updateLeafTextNode())
764         return;
765
766     AtomicString localName = toAtomicString(xmlLocalName);
767     AtomicString uri = toAtomicString(xmlURI);
768     AtomicString prefix = toAtomicString(xmlPrefix);
769
770     if (m_parsingFragment && uri.isNull()) {
771         if (!prefix.isNull())
772             uri = m_prefixToNamespaceMap.get(prefix);
773         else
774             uri = m_defaultNamespaceURI;
775     }
776
777     // If libxml entity parsing is broken, transfer the currentNodes' namespaceURI to the new node,
778     // if we're currently expanding elements which originate from an entity declaration.
779     if (hackAroundLibXMLEntityParsingBug() && depthTriggeringEntityExpansion() != -1 && context()->depth > depthTriggeringEntityExpansion() && uri.isNull() && prefix.isNull())
780         uri = m_currentNode->namespaceURI();
781
782     bool isFirstElement = !m_sawFirstElement;
783     m_sawFirstElement = true;
784
785     QualifiedName qName(prefix, localName, uri);
786     auto newElement = m_currentNode->document().createElement(qName, true);
787
788     Vector<Attribute> prefixedAttributes;
789     if (!handleNamespaceAttributes(prefixedAttributes, libxmlNamespaces, numNamespaces)) {
790         setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy());
791         stopParsing();
792         return;
793     }
794
795     bool success = handleElementAttributes(prefixedAttributes, libxmlAttributes, numAttributes);
796     setAttributes(newElement.ptr(), prefixedAttributes, parserContentPolicy());
797     if (!success) {
798         stopParsing();
799         return;
800     }
801
802     newElement->beginParsingChildren();
803
804     if (isScriptElement(newElement.get()))
805         m_scriptStartPosition = textPosition();
806
807     m_currentNode->parserAppendChild(newElement);
808     if (!m_currentNode) // Synchronous DOM events may have removed the current node.
809         return;
810
811     if (is<HTMLTemplateElement>(newElement))
812         pushCurrentNode(&downcast<HTMLTemplateElement>(newElement.get()).content());
813     else
814         pushCurrentNode(newElement.ptr());
815
816     if (is<HTMLHtmlElement>(newElement))
817         downcast<HTMLHtmlElement>(newElement.get()).insertedByParser();
818
819     if (!m_parsingFragment && isFirstElement && document()->frame())
820         document()->frame()->injectUserScripts(InjectAtDocumentStart);
821 }
822
823 void XMLDocumentParser::endElementNs()
824 {
825     if (isStopped())
826         return;
827
828     if (m_parserPaused) {
829         m_pendingCallbacks->appendEndElementNSCallback();
830         return;
831     }
832
833     // JavaScript can detach the parser.  Make sure this is not released
834     // before the end of this method.
835     Ref<XMLDocumentParser> protectedThis(*this);
836
837     if (!updateLeafTextNode())
838         return;
839
840     RefPtr<ContainerNode> node = m_currentNode;
841     node->finishParsingChildren();
842
843     // Once we reach the depth again where entity expansion started, stop executing the work-around.
844     if (hackAroundLibXMLEntityParsingBug() && context()->depth <= depthTriggeringEntityExpansion())
845         setDepthTriggeringEntityExpansion(-1);
846
847     if (!scriptingContentIsAllowed(parserContentPolicy()) && is<Element>(*node) && isScriptElement(downcast<Element>(*node))) {
848         popCurrentNode();
849         node->remove();
850         return;
851     }
852
853     if (!node->isElementNode() || !m_view) {
854         popCurrentNode();
855         return;
856     }
857
858     auto& element = downcast<Element>(*node);
859
860     // The element's parent may have already been removed from document.
861     // Parsing continues in this case, but scripts aren't executed.
862     if (!element.isConnected()) {
863         popCurrentNode();
864         return;
865     }
866
867     if (!isScriptElement(element)) {
868         popCurrentNode();
869         return;
870     }
871
872     // Don't load external scripts for standalone documents (for now).
873     ASSERT(!m_pendingScript);
874     m_requestingScript = true;
875
876     auto& scriptElement = downcastScriptElement(element);
877     if (scriptElement.prepareScript(m_scriptStartPosition, ScriptElement::AllowLegacyTypeInTypeAttribute)) {
878         // FIXME: Script execution should be shared between
879         // the libxml2 and Qt XMLDocumentParser implementations.
880
881         if (scriptElement.readyToBeParserExecuted())
882             scriptElement.executeClassicScript(ScriptSourceCode(scriptElement.scriptContent(), document()->url(), m_scriptStartPosition, JSC::SourceProviderSourceType::Program, InlineClassicScript::create(scriptElement)));
883         else if (scriptElement.willBeParserExecuted() && scriptElement.loadableScript()) {
884             m_pendingScript = PendingScript::create(scriptElement, *scriptElement.loadableScript());
885             m_pendingScript->setClient(*this);
886
887             // m_pendingScript will be nullptr if script was already loaded and setClient() executed it.
888             if (m_pendingScript)
889                 pauseParsing();
890         }
891
892         // JavaScript may have detached the parser
893         if (isDetached())
894             return;
895     }
896     m_requestingScript = false;
897     popCurrentNode();
898 }
899
900 void XMLDocumentParser::characters(const xmlChar* characters, int length)
901 {
902     if (isStopped())
903         return;
904
905     if (m_parserPaused) {
906         m_pendingCallbacks->appendCharactersCallback(characters, length);
907         return;
908     }
909
910     if (!m_leafTextNode)
911         createLeafTextNode();
912     m_bufferedText.append(characters, length);
913 }
914
915 void XMLDocumentParser::error(XMLErrors::ErrorType type, const char* message, va_list args)
916 {
917     if (isStopped())
918         return;
919
920     va_list preflightArgs;
921     va_copy(preflightArgs, args);
922     size_t stringLength = vsnprintf(nullptr, 0, message, preflightArgs);
923     va_end(preflightArgs);
924
925     Vector<char, 1024> buffer(stringLength + 1);
926     vsnprintf(buffer.data(), stringLength + 1, message, args);
927
928     TextPosition position = textPosition();
929     if (m_parserPaused)
930         m_pendingCallbacks->appendErrorCallback(type, reinterpret_cast<const xmlChar*>(buffer.data()), position.m_line, position.m_column);
931     else
932         handleError(type, buffer.data(), textPosition());
933 }
934
935 void XMLDocumentParser::processingInstruction(const xmlChar* target, const xmlChar* data)
936 {
937     if (isStopped())
938         return;
939
940     if (m_parserPaused) {
941         m_pendingCallbacks->appendProcessingInstructionCallback(target, data);
942         return;
943     }
944
945     if (!updateLeafTextNode())
946         return;
947
948     auto result = m_currentNode->document().createProcessingInstruction(toString(target), toString(data));
949     if (result.hasException())
950         return;
951     auto pi = result.releaseReturnValue();
952
953     pi->setCreatedByParser(true);
954
955     m_currentNode->parserAppendChild(pi);
956
957     pi->finishParsingChildren();
958
959     if (pi->isCSS())
960         m_sawCSS = true;
961
962 #if ENABLE(XSLT)
963     m_sawXSLTransform = !m_sawFirstElement && pi->isXSL();
964     if (m_sawXSLTransform && !document()->transformSourceDocument())
965         stopParsing();
966 #endif
967 }
968
969 void XMLDocumentParser::cdataBlock(const xmlChar* s, int len)
970 {
971     if (isStopped())
972         return;
973
974     if (m_parserPaused) {
975         m_pendingCallbacks->appendCDATABlockCallback(s, len);
976         return;
977     }
978
979     if (!updateLeafTextNode())
980         return;
981
982     m_currentNode->parserAppendChild(CDATASection::create(m_currentNode->document(), toString(s, len)));
983 }
984
985 void XMLDocumentParser::comment(const xmlChar* s)
986 {
987     if (isStopped())
988         return;
989
990     if (m_parserPaused) {
991         m_pendingCallbacks->appendCommentCallback(s);
992         return;
993     }
994
995     if (!updateLeafTextNode())
996         return;
997
998     m_currentNode->parserAppendChild(Comment::create(m_currentNode->document(), toString(s)));
999 }
1000
1001 enum StandaloneInfo {
1002     StandaloneUnspecified = -2,
1003     NoXMlDeclaration,
1004     StandaloneNo,
1005     StandaloneYes
1006 };
1007
1008 void XMLDocumentParser::startDocument(const xmlChar* version, const xmlChar* encoding, int standalone)
1009 {
1010     StandaloneInfo standaloneInfo = (StandaloneInfo)standalone;
1011     if (standaloneInfo == NoXMlDeclaration) {
1012         document()->setHasXMLDeclaration(false);
1013         return;
1014     }
1015
1016     if (version)
1017         document()->setXMLVersion(toString(version));
1018     if (standalone != StandaloneUnspecified)
1019         document()->setXMLStandalone(standaloneInfo == StandaloneYes);
1020     if (encoding)
1021         document()->setXMLEncoding(toString(encoding));
1022     document()->setHasXMLDeclaration(true);
1023 }
1024
1025 void XMLDocumentParser::endDocument()
1026 {
1027     updateLeafTextNode();
1028 }
1029
1030 void XMLDocumentParser::internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
1031 {
1032     if (isStopped())
1033         return;
1034
1035     if (m_parserPaused) {
1036         m_pendingCallbacks->appendInternalSubsetCallback(name, externalID, systemID);
1037         return;
1038     }
1039
1040     if (document())
1041         document()->parserAppendChild(DocumentType::create(*document(), toString(name), toString(externalID), toString(systemID)));
1042 }
1043
1044 static inline XMLDocumentParser* getParser(void* closure)
1045 {
1046     xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure);
1047     return static_cast<XMLDocumentParser*>(ctxt->_private);
1048 }
1049
1050 // This is a hack around http://bugzilla.gnome.org/show_bug.cgi?id=159219
1051 // Otherwise libxml seems to call all the SAX callbacks twice for any replaced entity.
1052 static inline bool hackAroundLibXMLEntityBug(void* closure)
1053 {
1054 #if LIBXML_VERSION >= 20627
1055     // This bug has been fixed in libxml 2.6.27.
1056     UNUSED_PARAM(closure);
1057     return false;
1058 #else
1059     return static_cast<xmlParserCtxtPtr>(closure)->node;
1060 #endif
1061 }
1062
1063 static void startElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix, const xmlChar* uri, int numNamespaces, const xmlChar** namespaces, int numAttributes, int numDefaulted, const xmlChar** libxmlAttributes)
1064 {
1065     if (hackAroundLibXMLEntityBug(closure))
1066         return;
1067
1068     getParser(closure)->startElementNs(localname, prefix, uri, numNamespaces, namespaces, numAttributes, numDefaulted, libxmlAttributes);
1069 }
1070
1071 static void endElementNsHandler(void* closure, const xmlChar*, const xmlChar*, const xmlChar*)
1072 {
1073     if (hackAroundLibXMLEntityBug(closure))
1074         return;
1075
1076     getParser(closure)->endElementNs();
1077 }
1078
1079 static void charactersHandler(void* closure, const xmlChar* s, int len)
1080 {
1081     if (hackAroundLibXMLEntityBug(closure))
1082         return;
1083
1084     getParser(closure)->characters(s, len);
1085 }
1086
1087 static void processingInstructionHandler(void* closure, const xmlChar* target, const xmlChar* data)
1088 {
1089     if (hackAroundLibXMLEntityBug(closure))
1090         return;
1091
1092     getParser(closure)->processingInstruction(target, data);
1093 }
1094
1095 static void cdataBlockHandler(void* closure, const xmlChar* s, int len)
1096 {
1097     if (hackAroundLibXMLEntityBug(closure))
1098         return;
1099
1100     getParser(closure)->cdataBlock(s, len);
1101 }
1102
1103 static void commentHandler(void* closure, const xmlChar* comment)
1104 {
1105     if (hackAroundLibXMLEntityBug(closure))
1106         return;
1107
1108     getParser(closure)->comment(comment);
1109 }
1110
1111 WTF_ATTRIBUTE_PRINTF(2, 3)
1112 static void warningHandler(void* closure, const char* message, ...)
1113 {
1114     va_list args;
1115     va_start(args, message);
1116     getParser(closure)->error(XMLErrors::warning, message, args);
1117     va_end(args);
1118 }
1119
1120 WTF_ATTRIBUTE_PRINTF(2, 3)
1121 static void fatalErrorHandler(void* closure, const char* message, ...)
1122 {
1123     va_list args;
1124     va_start(args, message);
1125     getParser(closure)->error(XMLErrors::fatal, message, args);
1126     va_end(args);
1127 }
1128
1129 WTF_ATTRIBUTE_PRINTF(2, 3)
1130 static void normalErrorHandler(void* closure, const char* message, ...)
1131 {
1132     va_list args;
1133     va_start(args, message);
1134     getParser(closure)->error(XMLErrors::nonFatal, message, args);
1135     va_end(args);
1136 }
1137
1138 // Using a static entity and marking it XML_INTERNAL_PREDEFINED_ENTITY is
1139 // a hack to avoid malloc/free. Using a global variable like this could cause trouble
1140 // if libxml implementation details were to change
1141 static xmlChar sharedXHTMLEntityResult[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
1142
1143 static xmlEntityPtr sharedXHTMLEntity()
1144 {
1145     static xmlEntity entity;
1146     if (!entity.type) {
1147         entity.type = XML_ENTITY_DECL;
1148         entity.orig = sharedXHTMLEntityResult;
1149         entity.content = sharedXHTMLEntityResult;
1150         entity.etype = XML_INTERNAL_PREDEFINED_ENTITY;
1151     }
1152     return &entity;
1153 }
1154
1155 static size_t convertUTF16EntityToUTF8(const UChar* utf16Entity, size_t numberOfCodeUnits, char* target, size_t targetSize)
1156 {
1157     const char* originalTarget = target;
1158     auto conversionResult = WTF::Unicode::convertUTF16ToUTF8(&utf16Entity, utf16Entity + numberOfCodeUnits, &target, target + targetSize);
1159     if (conversionResult != WTF::Unicode::conversionOK)
1160         return 0;
1161
1162     // Even though we must pass the length, libxml expects the entity string to be null terminated.
1163     ASSERT(target >= originalTarget + 1);
1164     *target = '\0';
1165     return target - originalTarget;
1166 }
1167
1168 static xmlEntityPtr getXHTMLEntity(const xmlChar* name)
1169 {
1170     UChar utf16DecodedEntity[4];
1171     size_t numberOfCodeUnits = decodeNamedEntityToUCharArray(reinterpret_cast<const char*>(name), utf16DecodedEntity);
1172     if (!numberOfCodeUnits)
1173         return 0;
1174
1175     ASSERT(numberOfCodeUnits <= 4);
1176     size_t entityLengthInUTF8 = convertUTF16EntityToUTF8(utf16DecodedEntity, numberOfCodeUnits,
1177         reinterpret_cast<char*>(sharedXHTMLEntityResult), WTF_ARRAY_LENGTH(sharedXHTMLEntityResult));
1178     if (!entityLengthInUTF8)
1179         return 0;
1180
1181     xmlEntityPtr entity = sharedXHTMLEntity();
1182     entity->length = entityLengthInUTF8;
1183     entity->name = name;
1184     return entity;
1185 }
1186
1187 static void entityDeclarationHandler(void* closure, const xmlChar* name, int type, const xmlChar* publicId, const xmlChar* systemId, xmlChar* content)
1188 {
1189     // Prevent the next call to getEntityHandler() to record the entity expansion depth.
1190     // We're parsing the entity declaration, so there's no need to record anything.
1191     // We only need to record the depth, if we're actually expanding the entity, when it's referenced.
1192     if (hackAroundLibXMLEntityParsingBug())
1193         getParser(closure)->setIsParsingEntityDeclaration(true);
1194     xmlSAX2EntityDecl(closure, name, type, publicId, systemId, content);
1195 }
1196
1197 static xmlEntityPtr getEntityHandler(void* closure, const xmlChar* name)
1198 {
1199     xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure);
1200
1201     XMLDocumentParser* parser = getParser(closure);
1202     if (hackAroundLibXMLEntityParsingBug()) {
1203         if (parser->isParsingEntityDeclaration()) {
1204             // We're parsing the entity declarations (not an entity reference), no need to do anything special.
1205             parser->setIsParsingEntityDeclaration(false);
1206             ASSERT(parser->depthTriggeringEntityExpansion() == -1);
1207         } else {
1208             // The entity will be used and eventually expanded. Record the current parser depth
1209             // so the next call to startElementNs() knows that the new element originates from
1210             // an entity declaration.
1211             parser->setDepthTriggeringEntityExpansion(ctxt->depth);
1212         }
1213     }
1214
1215     xmlEntityPtr ent = xmlGetPredefinedEntity(name);
1216     if (ent) {
1217         ent->etype = XML_INTERNAL_PREDEFINED_ENTITY;
1218         return ent;
1219     }
1220
1221     ent = xmlGetDocEntity(ctxt->myDoc, name);
1222     if (!ent && parser->isXHTMLDocument()) {
1223         ent = getXHTMLEntity(name);
1224         if (ent)
1225             ent->etype = XML_INTERNAL_GENERAL_ENTITY;
1226     }
1227
1228     return ent;
1229 }
1230
1231 static void startDocumentHandler(void* closure)
1232 {
1233     xmlParserCtxt* ctxt = static_cast<xmlParserCtxt*>(closure);
1234     switchToUTF16(ctxt);
1235     getParser(closure)->startDocument(ctxt->version, ctxt->encoding, ctxt->standalone);
1236     xmlSAX2StartDocument(closure);
1237 }
1238
1239 static void endDocumentHandler(void* closure)
1240 {
1241     getParser(closure)->endDocument();
1242     xmlSAX2EndDocument(closure);
1243 }
1244
1245 static void internalSubsetHandler(void* closure, const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
1246 {
1247     getParser(closure)->internalSubset(name, externalID, systemID);
1248     xmlSAX2InternalSubset(closure, name, externalID, systemID);
1249 }
1250
1251 static void externalSubsetHandler(void* closure, const xmlChar*, const xmlChar* externalId, const xmlChar*)
1252 {
1253     String extId = toString(externalId);
1254     if ((extId == "-//W3C//DTD XHTML 1.0 Transitional//EN")
1255         || (extId == "-//W3C//DTD XHTML 1.1//EN")
1256         || (extId == "-//W3C//DTD XHTML 1.0 Strict//EN")
1257         || (extId == "-//W3C//DTD XHTML 1.0 Frameset//EN")
1258         || (extId == "-//W3C//DTD XHTML Basic 1.0//EN")
1259         || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN")
1260         || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN")
1261         || (extId == "-//W3C//DTD MathML 2.0//EN")
1262         || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.0//EN")
1263         || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.1//EN")
1264         || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.2//EN"))
1265         getParser(closure)->setIsXHTMLDocument(true); // controls if we replace entities or not.
1266 }
1267
1268 static void ignorableWhitespaceHandler(void*, const xmlChar*, int)
1269 {
1270     // nothing to do, but we need this to work around a crasher
1271     // http://bugzilla.gnome.org/show_bug.cgi?id=172255
1272     // http://bugs.webkit.org/show_bug.cgi?id=5792
1273 }
1274
1275 void XMLDocumentParser::initializeParserContext(const CString& chunk)
1276 {
1277     xmlSAXHandler sax;
1278     memset(&sax, 0, sizeof(sax));
1279
1280     sax.error = normalErrorHandler;
1281     sax.fatalError = fatalErrorHandler;
1282     sax.characters = charactersHandler;
1283     sax.processingInstruction = processingInstructionHandler;
1284     sax.cdataBlock = cdataBlockHandler;
1285     sax.comment = commentHandler;
1286     sax.warning = warningHandler;
1287     sax.startElementNs = startElementNsHandler;
1288     sax.endElementNs = endElementNsHandler;
1289     sax.getEntity = getEntityHandler;
1290     sax.startDocument = startDocumentHandler;
1291     sax.endDocument = endDocumentHandler;
1292     sax.internalSubset = internalSubsetHandler;
1293     sax.externalSubset = externalSubsetHandler;
1294     sax.ignorableWhitespace = ignorableWhitespaceHandler;
1295     sax.entityDecl = entityDeclarationHandler;
1296     sax.initialized = XML_SAX2_MAGIC;
1297     DocumentParser::startParsing();
1298     m_sawError = false;
1299     m_sawCSS = false;
1300     m_sawXSLTransform = false;
1301     m_sawFirstElement = false;
1302
1303     XMLDocumentParserScope scope(&document()->cachedResourceLoader());
1304     if (m_parsingFragment)
1305         m_context = XMLParserContext::createMemoryParser(&sax, this, chunk);
1306     else {
1307         ASSERT(!chunk.data());
1308         m_context = XMLParserContext::createStringParser(&sax, this);
1309     }
1310 }
1311
1312 void XMLDocumentParser::doEnd()
1313 {
1314     if (!isStopped()) {
1315         if (m_context) {
1316             // Tell libxml we're done.
1317             {
1318                 XMLDocumentParserScope scope(&document()->cachedResourceLoader());
1319                 xmlParseChunk(context(), 0, 0, 1);
1320             }
1321
1322             m_context = nullptr;
1323         }
1324     }
1325
1326 #if ENABLE(XSLT)
1327     bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && shouldRenderInXMLTreeViewerMode(*document());
1328     if (xmlViewerMode) {
1329         XMLTreeViewer xmlTreeViewer(*document());
1330         xmlTreeViewer.transformDocumentToTreeView();
1331     } else if (m_sawXSLTransform) {
1332         xmlDocPtr doc = xmlDocPtrForString(document()->cachedResourceLoader(), m_originalSourceForTransform.toString(), document()->url().string());
1333         document()->setTransformSource(std::make_unique<TransformSource>(doc));
1334
1335         document()->setParsing(false); // Make the document think it's done, so it will apply XSL stylesheets.
1336         document()->styleScope().didChangeActiveStyleSheetCandidates();
1337
1338         // styleResolverChanged() call can detach the parser and null out its document.
1339         // In that case, we just bail out.
1340         if (isDetached())
1341             return;
1342
1343         document()->setParsing(true);
1344         DocumentParser::stopParsing();
1345     }
1346 #endif
1347 }
1348
1349 #if ENABLE(XSLT)
1350 static inline const char* nativeEndianUTF16Encoding()
1351 {
1352     const UChar BOM = 0xFEFF;
1353     const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
1354     return BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE";
1355 }
1356
1357 xmlDocPtr xmlDocPtrForString(CachedResourceLoader& cachedResourceLoader, const String& source, const String& url)
1358 {
1359     if (source.isEmpty())
1360         return nullptr;
1361
1362     // Parse in a single chunk into an xmlDocPtr
1363     // FIXME: Hook up error handlers so that a failure to parse the main document results in
1364     // good error messages.
1365
1366     const bool is8Bit = source.is8Bit();
1367     const char* characters = is8Bit ? reinterpret_cast<const char*>(source.characters8()) : reinterpret_cast<const char*>(source.characters16());
1368     size_t sizeInBytes = source.length() * (is8Bit ? sizeof(LChar) : sizeof(UChar));
1369     const char* encoding = is8Bit ? "iso-8859-1" : nativeEndianUTF16Encoding();
1370
1371     XMLDocumentParserScope scope(&cachedResourceLoader, errorFunc);
1372     return xmlReadMemory(characters, sizeInBytes, url.latin1().data(), encoding, XSLT_PARSE_OPTIONS);
1373 }
1374 #endif
1375
1376 TextPosition XMLDocumentParser::textPosition() const
1377 {
1378     xmlParserCtxtPtr context = this->context();
1379     if (!context)
1380         return TextPosition();
1381     return TextPosition(OrdinalNumber::fromOneBasedInt(context->input->line),
1382                         OrdinalNumber::fromOneBasedInt(context->input->col));
1383 }
1384
1385 bool XMLDocumentParser::shouldAssociateConsoleMessagesWithTextPosition() const
1386 {
1387     return !m_parserPaused && !m_requestingScript;
1388 }
1389
1390 void XMLDocumentParser::stopParsing()
1391 {
1392     DocumentParser::stopParsing();
1393     if (context())
1394         xmlStopParser(context());
1395 }
1396
1397 void XMLDocumentParser::resumeParsing()
1398 {
1399     ASSERT(!isDetached());
1400     ASSERT(m_parserPaused);
1401
1402     m_parserPaused = false;
1403
1404     // First, execute any pending callbacks
1405     while (!m_pendingCallbacks->isEmpty()) {
1406         m_pendingCallbacks->callAndRemoveFirstCallback(this);
1407
1408         // A callback paused the parser
1409         if (m_parserPaused)
1410             return;
1411     }
1412
1413     // There is normally only one string left, so toString() shouldn't copy.
1414     // In any case, the XML parser runs on the main thread and it's OK if
1415     // the passed string has more than one reference.
1416     auto rest = m_pendingSrc.toString();
1417     m_pendingSrc.clear();
1418     append(rest.impl());
1419
1420     // Finally, if finish() has been called and write() didn't result
1421     // in any further callbacks being queued, call end()
1422     if (m_finishCalled && m_pendingCallbacks->isEmpty())
1423         end();
1424 }
1425
1426 bool XMLDocumentParser::appendFragmentSource(const String& chunk)
1427 {
1428     ASSERT(!m_context);
1429     ASSERT(m_parsingFragment);
1430
1431     CString chunkAsUtf8 = chunk.utf8();
1432     
1433     // libxml2 takes an int for a length, and therefore can't handle XML chunks larger than 2 GiB.
1434     if (chunkAsUtf8.length() > INT_MAX)
1435         return false;
1436
1437     initializeParserContext(chunkAsUtf8);
1438     xmlParseContent(context());
1439     endDocument(); // Close any open text nodes.
1440
1441     // FIXME: If this code is actually needed, it should probably move to finish()
1442     // XMLDocumentParserQt has a similar check (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError) in doEnd().
1443     // Check if all the chunk has been processed.
1444     long bytesProcessed = xmlByteConsumed(context());
1445     if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length()) {
1446         // FIXME: I don't believe we can hit this case without also having seen an error or a null byte.
1447         // If we hit this ASSERT, we've found a test case which demonstrates the need for this code.
1448         ASSERT(m_sawError || (bytesProcessed >= 0 && !chunkAsUtf8.data()[bytesProcessed]));
1449         return false;
1450     }
1451
1452     // No error if the chunk is well formed or it is not but we have no error.
1453     return context()->wellFormed || !xmlCtxtGetLastError(context());
1454 }
1455
1456 // --------------------------------
1457
1458 struct AttributeParseState {
1459     HashMap<String, String> attributes;
1460     bool gotAttributes;
1461 };
1462
1463 static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLocalName, const xmlChar* /*xmlPrefix*/, const xmlChar* /*xmlURI*/, int /*numNamespaces*/, const xmlChar** /*namespaces*/, int numAttributes, int /*numDefaulted*/, const xmlChar** libxmlAttributes)
1464 {
1465     if (strcmp(reinterpret_cast<const char*>(xmlLocalName), "attrs") != 0)
1466         return;
1467
1468     xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure);
1469     AttributeParseState* state = static_cast<AttributeParseState*>(ctxt->_private);
1470
1471     state->gotAttributes = true;
1472
1473     xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes);
1474     for (int i = 0; i < numAttributes; i++) {
1475         String attrLocalName = toString(attributes[i].localname);
1476         int valueLength = (int) (attributes[i].end - attributes[i].value);
1477         String attrValue = toString(attributes[i].value, valueLength);
1478         String attrPrefix = toString(attributes[i].prefix);
1479         String attrQName = attrPrefix.isEmpty() ? attrLocalName : attrPrefix + ":" + attrLocalName;
1480
1481         state->attributes.set(attrQName, attrValue);
1482     }
1483 }
1484
1485 HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
1486 {
1487     String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
1488
1489     AttributeParseState state;
1490     state.gotAttributes = false;
1491
1492     xmlSAXHandler sax;
1493     memset(&sax, 0, sizeof(sax));
1494     sax.startElementNs = attributesStartElementNsHandler;
1495     sax.initialized = XML_SAX2_MAGIC;
1496
1497     RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state);
1498
1499     // FIXME: Can we parse 8-bit strings directly as Latin-1 instead of upconverting to UTF-16?
1500     xmlParseChunk(parser->context(), reinterpret_cast<const char*>(StringView(parseString).upconvertedCharacters().get()), parseString.length() * sizeof(UChar), 1);
1501
1502     attrsOK = state.gotAttributes;
1503     return WTFMove(state.attributes);
1504 }
1505
1506 }