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