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