Fix entity handling in the main document content (attributes still broken)
[WebKit-https.git] / WebCore / dom / XMLTokenizer.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 2000 Peter Kelly (pmk@post.com)
5  * Copyright (C) 2005, 2006 Apple Computer, Inc.
6  * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
7  * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
8  * Copyright (C) 2007 Trolltech ASA
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */
25
26 #include "config.h"
27 #include "XMLTokenizer.h"
28
29 #include "CDATASection.h"
30 #include "CString.h"
31 #include "Cache.h"
32 #include "CachedScript.h"
33 #include "Comment.h"
34 #include "DocLoader.h"
35 #include "Document.h"
36 #include "DocumentFragment.h"
37 #include "DocumentType.h"
38 #include "EventNames.h"
39 #include "Frame.h"
40 #include "FrameLoader.h"
41 #include "FrameView.h"
42 #include "HTMLNames.h"
43 #include "HTMLScriptElement.h"
44 #include "HTMLTableSectionElement.h"
45 #include "HTMLTokenizer.h"
46 #include "ProcessingInstruction.h"
47 #include "ResourceHandle.h"
48 #include "ResourceRequest.h"
49 #include "ResourceResponse.h"
50 #ifndef USE_QXMLSTREAM
51 #include <libxml/parser.h>
52 #include <libxml/parserInternals.h>
53 #else
54 #include <QDebug>
55 #endif
56 #include <wtf/Platform.h>
57 #include <wtf/Vector.h>
58
59 #if ENABLE(XSLT)
60 #include <libxslt/xslt.h>
61 #endif
62
63 #if ENABLE(SVG)
64 #include "SVGNames.h"
65 #include "XLinkNames.h"
66 #endif
67
68 using namespace std;
69
70 namespace WebCore {
71
72 using namespace EventNames;
73 using namespace HTMLNames;
74
75 const int maxErrors = 25;
76
77 #ifndef USE_QXMLSTREAM
78 class PendingCallbacks {
79 public:
80     PendingCallbacks()
81     {
82         m_callbacks.setAutoDelete(true);
83     }
84     
85     void appendStartElementNSCallback(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces,
86                                       const xmlChar** namespaces, int nb_attributes, int nb_defaulted, const xmlChar** attributes)
87     {
88         PendingStartElementNSCallback* callback = new PendingStartElementNSCallback;
89         
90         callback->xmlLocalName = xmlStrdup(xmlLocalName);
91         callback->xmlPrefix = xmlStrdup(xmlPrefix);
92         callback->xmlURI = xmlStrdup(xmlURI);
93         callback->nb_namespaces = nb_namespaces;
94         callback->namespaces = reinterpret_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * nb_namespaces * 2));
95         for (int i = 0; i < nb_namespaces * 2 ; i++)
96             callback->namespaces[i] = xmlStrdup(namespaces[i]);
97         callback->nb_attributes = nb_attributes;
98         callback->nb_defaulted = nb_defaulted;
99         callback->attributes =  reinterpret_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * nb_attributes * 5));
100         for (int i = 0; i < nb_attributes; i++) {
101             // Each attribute has 5 elements in the array:
102             // name, prefix, uri, value and an end pointer.
103             
104             for (int j = 0; j < 3; j++)
105                 callback->attributes[i * 5 + j] = xmlStrdup(attributes[i * 5 + j]);
106             
107             int len = attributes[i * 5 + 4] - attributes[i * 5 + 3];
108
109             callback->attributes[i * 5 + 3] = xmlStrndup(attributes[i * 5 + 3], len);
110             callback->attributes[i * 5 + 4] = callback->attributes[i * 5 + 3] + len;
111         }
112         
113         m_callbacks.append(callback);
114     }
115
116     void appendEndElementNSCallback()
117     {
118         PendingEndElementNSCallback* callback = new PendingEndElementNSCallback;
119         
120         m_callbacks.append(callback);
121     }
122     
123     void appendCharactersCallback(const xmlChar* s, int len)
124     {
125         PendingCharactersCallback* callback = new PendingCharactersCallback;
126         
127         callback->s = xmlStrndup(s, len);
128         callback->len = len;
129         
130         m_callbacks.append(callback);        
131     }
132     
133     void appendProcessingInstructionCallback(const xmlChar* target, const xmlChar* data)
134     {
135         PendingProcessingInstructionCallback* callback = new PendingProcessingInstructionCallback;
136         
137         callback->target = xmlStrdup(target);
138         callback->data = xmlStrdup(data);
139         
140         m_callbacks.append(callback);
141     }
142     
143     void appendCDATABlockCallback(const xmlChar* s, int len)
144     {
145         PendingCDATABlockCallback* callback = new PendingCDATABlockCallback;
146         
147         callback->s = xmlStrndup(s, len);
148         callback->len = len;
149         
150         m_callbacks.append(callback);        
151     }
152
153     void appendCommentCallback(const xmlChar* s)
154     {
155         PendingCommentCallback* callback = new PendingCommentCallback;
156         
157         callback->s = xmlStrdup(s);
158         
159         m_callbacks.append(callback);        
160     }
161
162     void appendInternalSubsetCallback(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
163     {
164         PendingInternalSubsetCallback* callback = new PendingInternalSubsetCallback;
165         
166         callback->name = xmlStrdup(name);
167         callback->externalID = xmlStrdup(externalID);
168         callback->systemID = xmlStrdup(systemID);
169         
170         m_callbacks.append(callback);        
171     }
172     
173     void appendErrorCallback(XMLTokenizer::ErrorType type, const char* message, int lineNumber, int columnNumber)
174     {
175         PendingErrorCallback* callback = new PendingErrorCallback;
176         
177         callback->message = strdup(message);
178         callback->type = type;
179         callback->lineNumber = lineNumber;
180         callback->columnNumber = columnNumber;
181         
182         m_callbacks.append(callback);
183     }
184
185     void callAndRemoveFirstCallback(XMLTokenizer* tokenizer)
186     {
187         PendingCallback* cb = m_callbacks.getFirst();
188             
189         cb->call(tokenizer);
190         m_callbacks.removeFirst();
191     }
192     
193     bool isEmpty() const { return m_callbacks.isEmpty(); }
194     
195 private:    
196     struct PendingCallback {        
197         
198         virtual ~PendingCallback() { } 
199
200         virtual void call(XMLTokenizer* tokenizer) = 0;
201     };  
202     
203     struct PendingStartElementNSCallback : public PendingCallback {        
204         virtual ~PendingStartElementNSCallback() {
205             xmlFree(xmlLocalName);
206             xmlFree(xmlPrefix);
207             xmlFree(xmlURI);
208             for (int i = 0; i < nb_namespaces * 2; i++)
209                 xmlFree(namespaces[i]);
210             xmlFree(namespaces);
211             for (int i = 0; i < nb_attributes; i++)
212                 for (int j = 0; j < 4; j++) 
213                     xmlFree(attributes[i * 5 + j]);
214             xmlFree(attributes);
215         }
216         
217         virtual void call(XMLTokenizer* tokenizer) {
218             tokenizer->startElementNs(xmlLocalName, xmlPrefix, xmlURI, 
219                                       nb_namespaces, (const xmlChar**)namespaces,
220                                       nb_attributes, nb_defaulted, (const xmlChar**)(attributes));
221         }
222
223         xmlChar* xmlLocalName;
224         xmlChar* xmlPrefix;
225         xmlChar* xmlURI;
226         int nb_namespaces;
227         xmlChar** namespaces;
228         int nb_attributes;
229         int nb_defaulted;
230         xmlChar** attributes;
231     };
232     
233     struct PendingEndElementNSCallback : public PendingCallback {
234         virtual void call(XMLTokenizer* tokenizer) 
235         {
236             tokenizer->endElementNs();
237         }
238     };
239     
240     struct PendingCharactersCallback : public PendingCallback {
241         virtual ~PendingCharactersCallback() 
242         {
243             xmlFree(s);
244         }
245     
246         virtual void call(XMLTokenizer* tokenizer) 
247         {
248             tokenizer->characters(s, len);
249         }
250         
251         xmlChar* s;
252         int len;
253     };
254
255     struct PendingProcessingInstructionCallback : public PendingCallback {
256         virtual ~PendingProcessingInstructionCallback() 
257         {
258             xmlFree(target);
259             xmlFree(data);
260         }
261         
262         virtual void call(XMLTokenizer* tokenizer) 
263         {
264             tokenizer->processingInstruction(target, data);
265         }
266         
267         xmlChar* target;
268         xmlChar* data;
269     };
270     
271     struct PendingCDATABlockCallback : public PendingCallback {
272         virtual ~PendingCDATABlockCallback() 
273         {
274             xmlFree(s);
275         }
276         
277         virtual void call(XMLTokenizer* tokenizer) 
278         {
279             tokenizer->cdataBlock(s, len);
280         }
281         
282         xmlChar* s;
283         int len;
284     };
285
286     struct PendingCommentCallback : public PendingCallback {
287         virtual ~PendingCommentCallback() 
288         {
289             xmlFree(s);
290         }
291         
292         virtual void call(XMLTokenizer* tokenizer) 
293         {
294             tokenizer->comment(s);
295         }
296
297         xmlChar* s;
298     };
299     
300     struct PendingInternalSubsetCallback : public PendingCallback {
301         virtual ~PendingInternalSubsetCallback() 
302         {
303             xmlFree(name);
304             xmlFree(externalID);
305             xmlFree(systemID);
306         }
307         
308         virtual void call(XMLTokenizer* tokenizer)
309         {
310             tokenizer->internalSubset(name, externalID, systemID);
311         }
312         
313         xmlChar* name;
314         xmlChar* externalID;
315         xmlChar* systemID;        
316     };
317     
318     struct PendingErrorCallback: public PendingCallback {
319         virtual ~PendingErrorCallback() 
320         {
321             free (message);
322         }
323         
324         virtual void call(XMLTokenizer* tokenizer) 
325         {
326             tokenizer->handleError(type, message, lineNumber, columnNumber);
327         }
328         
329         XMLTokenizer::ErrorType type;
330         char* message;
331         int lineNumber;
332         int columnNumber;
333     };
334     
335 public:
336     DeprecatedPtrList<PendingCallback> m_callbacks;
337 };
338 #endif
339 // --------------------------------
340
341 static int globalDescriptor = 0;
342
343 static int matchFunc(const char* uri)
344 {
345     return 1; // Match everything.
346 }
347
348 static DocLoader* globalDocLoader = 0;
349
350 class OffsetBuffer {
351 public:
352     OffsetBuffer(const Vector<char>& b) : m_buffer(b), m_currentOffset(0) { }
353     
354     int readOutBytes(char* outputBuffer, unsigned askedToRead) {
355         unsigned bytesLeft = m_buffer.size() - m_currentOffset;
356         unsigned lenToCopy = min(askedToRead, bytesLeft);
357         if (lenToCopy) {
358             memcpy(outputBuffer, m_buffer.data() + m_currentOffset, lenToCopy);
359             m_currentOffset += lenToCopy;
360         }
361         return lenToCopy;
362     }
363
364 private:
365     Vector<char> m_buffer;
366     unsigned m_currentOffset;
367 };
368
369 #ifndef USE_QXMLSTREAM
370 static bool shouldAllowExternalLoad(const char* inURI)
371 {
372     if (strstr(inURI, "/etc/xml/catalog")
373             || strstr(inURI, "http://www.w3.org/Graphics/SVG") == inURI
374             || strstr(inURI, "http://www.w3.org/TR/xhtml") == inURI)
375         return false;
376     return true;
377 }
378 static void* openFunc(const char* uri)
379 {
380     if (!globalDocLoader || !shouldAllowExternalLoad(uri))
381         return &globalDescriptor;
382
383     ResourceError error;
384     ResourceResponse response;
385     Vector<char> data;
386     
387     if (globalDocLoader->frame()) 
388         globalDocLoader->frame()->loader()->loadResourceSynchronously(KURL(uri), error, response, data);
389
390     return new OffsetBuffer(data);
391 }
392
393 static int readFunc(void* context, char* buffer, int len)
394 {
395     // Do 0-byte reads in case of a null descriptor
396     if (context == &globalDescriptor)
397         return 0;
398         
399     OffsetBuffer* data = static_cast<OffsetBuffer*>(context);
400     return data->readOutBytes(buffer, len);
401 }
402
403 static int writeFunc(void* context, const char* buffer, int len)
404 {
405     // Always just do 0-byte writes
406     return 0;
407 }
408
409 static int closeFunc(void* context)
410 {
411     if (context != &globalDescriptor) {
412         OffsetBuffer* data = static_cast<OffsetBuffer*>(context);
413         delete data;
414     }
415     return 0;
416 }
417
418 static void errorFunc(void*, const char*, ...)
419 {
420     // FIXME: It would be nice to display error messages somewhere.
421 }
422
423 void setLoaderForLibXMLCallbacks(DocLoader* docLoader)
424 {
425     globalDocLoader = docLoader;
426 }
427
428 static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* userData)
429 {
430     static bool didInit = false;
431     if (!didInit) {
432         xmlInitParser();
433         xmlRegisterInputCallbacks(matchFunc, openFunc, readFunc, closeFunc);
434         xmlRegisterOutputCallbacks(matchFunc, openFunc, writeFunc, closeFunc);
435         didInit = true;
436     }
437
438     xmlParserCtxtPtr parser = xmlCreatePushParserCtxt(handlers, 0, 0, 0, 0);
439     parser->_private = userData;
440     parser->replaceEntities = true;
441     const UChar BOM = 0xFEFF;
442     const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
443     xmlSwitchEncoding(parser, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
444     return parser;
445 }
446 #endif
447
448 // --------------------------------
449
450 XMLTokenizer::XMLTokenizer(Document* _doc, FrameView* _view)
451     : m_doc(_doc)
452     , m_view(_view)
453 #ifndef USE_QXMLSTREAM
454     , m_context(0)
455 #endif
456     , m_currentNode(_doc)
457     , m_currentNodeIsReferenced(false)
458     , m_sawError(false)
459     , m_sawXSLTransform(false)
460     , m_sawFirstElement(false)
461     , m_isXHTMLDocument(false)
462     , m_parserPaused(false)
463     , m_requestingScript(false)
464     , m_finishCalled(false)
465     , m_errorCount(0)
466     , m_lastErrorLine(0)
467     , m_lastErrorColumn(0)
468     , m_pendingScript(0)
469     , m_scriptStartLine(0)
470     , m_parsingFragment(false)
471 #ifndef USE_QXMLSTREAM
472     , m_pendingCallbacks(new PendingCallbacks)
473 #endif
474 {
475 }
476
477 XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement)
478     : m_doc(fragment->document())
479     , m_view(0)
480 #ifndef USE_QXMLSTREAM
481     , m_context(0)
482 #endif
483     , m_currentNode(fragment)
484     , m_currentNodeIsReferenced(fragment)
485     , m_sawError(false)
486     , m_sawXSLTransform(false)
487     , m_sawFirstElement(false)
488     , m_isXHTMLDocument(false)
489     , m_parserPaused(false)
490     , m_requestingScript(false)
491     , m_finishCalled(false)
492     , m_errorCount(0)
493     , m_lastErrorLine(0)
494     , m_lastErrorColumn(0)
495     , m_pendingScript(0)
496     , m_scriptStartLine(0)
497     , m_parsingFragment(true)
498 #ifndef USE_QXMLSTREAM
499     , m_pendingCallbacks(new PendingCallbacks)
500 #endif
501 {
502     if (fragment)
503         fragment->ref();
504     if (m_doc)
505         m_doc->ref();
506           
507     // Add namespaces based on the parent node
508     Vector<Element*> elemStack;
509     while (parentElement) {
510         elemStack.append(parentElement);
511         
512         Node* n = parentElement->parentNode();
513         if (!n || !n->isElementNode())
514             break;
515         parentElement = static_cast<Element*>(n);
516     }
517     
518     if (elemStack.isEmpty())
519         return;
520     
521     for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) {
522         if (NamedAttrMap* attrs = element->attributes()) {
523             for (unsigned i = 0; i < attrs->length(); i++) {
524                 Attribute* attr = attrs->attributeItem(i);
525                 if (attr->localName() == "xmlns")
526                     m_defaultNamespaceURI = attr->value();
527                 else if (attr->prefix() == "xmlns")
528                     m_prefixToNamespaceMap.set(attr->localName(), attr->value());
529             }
530         }
531     }
532 }
533
534 XMLTokenizer::~XMLTokenizer()
535 {
536     setCurrentNode(0);
537     if (m_parsingFragment && m_doc)
538         m_doc->deref();
539     if (m_pendingScript)
540         m_pendingScript->deref(this);
541 }
542
543 void XMLTokenizer::setCurrentNode(Node* n)
544 {
545     bool nodeNeedsReference = n && n != m_doc;
546     if (nodeNeedsReference)
547         n->ref(); 
548     if (m_currentNodeIsReferenced) 
549         m_currentNode->deref(); 
550     m_currentNode = n;
551     m_currentNodeIsReferenced = nodeNeedsReference;
552 }
553
554 bool XMLTokenizer::write(const SegmentedString& s, bool /*appendData*/)
555 {
556     String parseString = s.toString();
557     
558     if (m_sawXSLTransform || !m_sawFirstElement)
559         m_originalSourceForTransform += parseString;
560
561     if (m_parserStopped || m_sawXSLTransform)
562         return false;
563     
564     if (m_parserPaused) {
565         m_pendingSrc.append(s);
566         return false;
567     }
568     
569 #ifndef USE_QXMLSTREAM
570     if (!m_context)
571         initializeParserContext();
572     
573     // libXML throws an error if you try to switch the encoding for an empty string.
574     if (parseString.length()) {
575         // Hack around libxml2's lack of encoding overide support by manually
576         // resetting the encoding to UTF-16 before every chunk.  Otherwise libxml
577         // will detect <?xml version="1.0" encoding="<encoding name>"?> blocks 
578         // and switch encodings, causing the parse to fail.
579         const UChar BOM = 0xFEFF;
580         const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
581         xmlSwitchEncoding(m_context, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
582
583         xmlParseChunk(m_context, reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
584     }
585 #else
586     QString data(parseString);
587     if (!data.isEmpty()) {
588         if (!m_sawFirstElement) {
589             int idx = data.indexOf(QLatin1String("<?xml"));
590             if (idx != -1) {
591                 int start = idx + 5;
592                 int end = data.indexOf(QLatin1String("?>"), start);
593                 QString content = data.mid(start, end-start);
594                 bool ok = true;
595                 HashMap<String, String> attrs = parseAttributes(content, ok);
596                 String version = attrs.get("version");
597                 String encoding = attrs.get("encoding");
598                 ExceptionCode ec = 0;
599                 if (!version.isEmpty())
600                     m_doc->setXMLVersion(version, ec);
601                 if (!encoding.isEmpty())
602                     m_doc->setXMLEncoding(encoding);
603             }
604         }
605         m_stream.addData(data);
606         parse();
607     }
608 #endif
609     
610     return false;
611 }
612 #ifndef USE_QXMLSTREAM
613 inline String toString(const xmlChar* str, unsigned len)
614 {
615     return UTF8Encoding().decode(reinterpret_cast<const char*>(str), len);
616 }
617
618 inline String toString(const xmlChar* str)
619 {
620     if (!str)
621         return String();
622     
623     return UTF8Encoding().decode(reinterpret_cast<const char*>(str), strlen(reinterpret_cast<const char*>(str)));
624 }
625
626 struct _xmlSAX2Namespace {
627     const xmlChar* prefix;
628     const xmlChar* uri;
629 };
630 typedef struct _xmlSAX2Namespace xmlSAX2Namespace;
631
632 static inline void handleElementNamespaces(Element* newElement, const xmlChar** libxmlNamespaces, int nb_namespaces, ExceptionCode& ec)
633 {
634     xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNamespaces);
635     for(int i = 0; i < nb_namespaces; i++) {
636         String namespaceQName = "xmlns";
637         String namespaceURI = toString(namespaces[i].uri);
638         if (namespaces[i].prefix)
639             namespaceQName = "xmlns:" + toString(namespaces[i].prefix);
640         newElement->setAttributeNS("http://www.w3.org/2000/xmlns/", namespaceQName, namespaceURI, ec);
641         if (ec) // exception setting attributes
642             return;
643     }
644 }
645
646 struct _xmlSAX2Attributes {
647     const xmlChar* localname;
648     const xmlChar* prefix;
649     const xmlChar* uri;
650     const xmlChar* value;
651     const xmlChar* end;
652 };
653 typedef struct _xmlSAX2Attributes xmlSAX2Attributes;
654
655 static inline void handleElementAttributes(Element* newElement, const xmlChar** libxmlAttributes, int nb_attributes, ExceptionCode& ec)
656 {
657     xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes);
658     for(int i = 0; i < nb_attributes; i++) {
659         String attrLocalName = toString(attributes[i].localname);
660         int valueLength = (int) (attributes[i].end - attributes[i].value);
661         String attrValue = toString(attributes[i].value, valueLength);
662         String attrPrefix = toString(attributes[i].prefix);
663         String attrURI = attrPrefix.isEmpty() ? String() : toString(attributes[i].uri);
664         String attrQName = attrPrefix.isEmpty() ? attrLocalName : attrPrefix + ":" + attrLocalName;
665         
666         newElement->setAttributeNS(attrURI, attrQName, attrValue, ec);
667         if (ec) // exception setting attributes
668             return;
669     }
670 }
671
672 void XMLTokenizer::startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI, int nb_namespaces,
673                                   const xmlChar** libxmlNamespaces, int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes)
674 {
675     if (m_parserStopped)
676         return;
677     
678     if (m_parserPaused) {
679         m_pendingCallbacks->appendStartElementNSCallback(xmlLocalName, xmlPrefix, xmlURI, nb_namespaces, libxmlNamespaces,
680                                                          nb_attributes, nb_defaulted, libxmlAttributes);
681         return;
682     }
683     
684     m_sawFirstElement = true;
685
686     exitText();
687
688     String localName = toString(xmlLocalName);
689     String uri = toString(xmlURI);
690     String prefix = toString(xmlPrefix);
691     
692     if (m_parsingFragment && uri.isNull()) {
693         if (!prefix.isNull())
694             uri = m_prefixToNamespaceMap.get(prefix);
695         else
696             uri = m_defaultNamespaceURI;
697     }
698
699     ExceptionCode ec = 0;
700     QualifiedName qName(prefix, localName, uri);
701     RefPtr<Element> newElement = m_doc->createElement(qName, true, ec);
702     if (!newElement) {
703         stopParsing();
704         return;
705     }
706     
707     handleElementNamespaces(newElement.get(), libxmlNamespaces, nb_namespaces, ec);
708     if (ec) {
709         stopParsing();
710         return;
711     }
712     
713     handleElementAttributes(newElement.get(), libxmlAttributes, nb_attributes, ec);
714     if (ec) {
715         stopParsing();
716         return;
717     }
718
719     if (newElement->hasTagName(scriptTag))
720         static_cast<HTMLScriptElement*>(newElement.get())->setCreatedByParser(true);
721     
722     if (newElement->hasTagName(HTMLNames::scriptTag)
723 #if ENABLE(SVG)
724         || newElement->hasTagName(SVGNames::scriptTag)
725 #endif
726         )
727         m_scriptStartLine = lineNumber();
728     
729     if (!m_currentNode->addChild(newElement.get())) {
730         stopParsing();
731         return;
732     }
733     
734     setCurrentNode(newElement.get());
735     if (m_view && !newElement->attached())
736         newElement->attach();
737 }
738
739 void XMLTokenizer::endElementNs()
740 {
741     if (m_parserStopped)
742         return;
743
744     if (m_parserPaused) {
745         m_pendingCallbacks->appendEndElementNSCallback();
746         return;
747     }
748     
749     exitText();
750
751     Node* n = m_currentNode;
752     RefPtr<Node> parent = n->parentNode();
753     n->closeRenderer();
754     
755     // don't load external scripts for standalone documents (for now)
756     if (n->isElementNode() && m_view && (static_cast<Element*>(n)->hasTagName(scriptTag) 
757 #if ENABLE(SVG)
758                                          || static_cast<Element*>(n)->hasTagName(SVGNames::scriptTag)
759 #endif
760                                          )) {
761
762                                          
763         ASSERT(!m_pendingScript);
764         
765         m_requestingScript = true;
766         
767         Element* scriptElement = static_cast<Element*>(n);        
768         String scriptHref;
769         
770         if (static_cast<Element*>(n)->hasTagName(scriptTag))
771             scriptHref = scriptElement->getAttribute(srcAttr);
772 #if ENABLE(SVG)
773         else if (static_cast<Element*>(n)->hasTagName(SVGNames::scriptTag))
774             scriptHref = scriptElement->getAttribute(XLinkNames::hrefAttr);
775 #endif
776         
777         if (!scriptHref.isEmpty()) {
778             // we have a src attribute 
779             const AtomicString& charset = scriptElement->getAttribute(charsetAttr);
780             if ((m_pendingScript = m_doc->docLoader()->requestScript(scriptHref, charset))) {
781                 m_scriptElement = scriptElement;
782                 m_pendingScript->ref(this);
783                     
784                 // m_pendingScript will be 0 if script was already loaded and ref() executed it
785                 if (m_pendingScript)
786                     pauseParsing();
787             } else 
788                 m_scriptElement = 0;
789
790         } else {
791             String scriptCode = "";
792             for (Node* child = scriptElement->firstChild(); child; child = child->nextSibling()) {
793                 if (child->isTextNode() || child->nodeType() == Node::CDATA_SECTION_NODE)
794                     scriptCode += static_cast<CharacterData*>(child)->data();
795             }
796             m_view->frame()->loader()->executeScript(m_doc->URL(), m_scriptStartLine - 1, scriptCode);
797         }
798         
799         m_requestingScript = false;
800     }
801
802     setCurrentNode(parent.get());
803 }
804
805 void XMLTokenizer::characters(const xmlChar* s, int len)
806 {
807     if (m_parserStopped)
808         return;
809     
810     if (m_parserPaused) {
811         m_pendingCallbacks->appendCharactersCallback(s, len);
812         return;
813     }
814     
815     if (m_currentNode->isTextNode() || enterText()) {
816         ExceptionCode ec = 0;
817         static_cast<Text*>(m_currentNode)->appendData(toString(s, len), ec);
818     }
819 }
820
821 void XMLTokenizer::error(ErrorType type, const char* message, va_list args)
822 {
823     if (m_parserStopped)
824         return;
825
826 #if PLATFORM(WIN_OS)
827     char m[1024];
828     vsnprintf(m, sizeof(m) - 1, message, args);
829 #else
830     char* m;
831     vasprintf(&m, message, args);
832 #endif
833     
834     if (m_parserPaused)
835         m_pendingCallbacks->appendErrorCallback(type, m, lineNumber(), columnNumber());
836     else
837         handleError(type, m, lineNumber(), columnNumber());
838
839 #if !PLATFORM(WIN_OS)
840     free(m);
841 #endif
842 }
843
844 void XMLTokenizer::processingInstruction(const xmlChar* target, const xmlChar* data)
845 {
846     if (m_parserStopped)
847         return;
848
849     if (m_parserPaused) {
850         m_pendingCallbacks->appendProcessingInstructionCallback(target, data);
851         return;
852     }
853     
854     exitText();
855
856     // ### handle exceptions
857     int exception = 0;
858     RefPtr<ProcessingInstruction> pi = m_doc->createProcessingInstruction(
859         toString(target), toString(data), exception);
860     if (exception)
861         return;
862
863     if (!m_currentNode->addChild(pi.get()))
864         return;
865     if (m_view && !pi->attached())
866         pi->attach();
867
868     // don't load stylesheets for standalone documents
869     if (m_doc->frame()) {
870         m_sawXSLTransform = !m_sawFirstElement && !pi->checkStyleSheet();
871 #if ENABLE(XSLT)
872         // Pretend we didn't see this PI if we're the result of a transform.
873         if (m_sawXSLTransform && !m_doc->transformSourceDocument())
874 #else
875         if (m_sawXSLTransform)
876 #endif
877             // Stop the SAX parser.
878             stopParsing();
879     }
880 }
881
882 void XMLTokenizer::cdataBlock(const xmlChar* s, int len)
883 {
884     if (m_parserStopped)
885         return;
886
887     if (m_parserPaused) {
888         m_pendingCallbacks->appendCDATABlockCallback(s, len);
889         return;
890     }
891     
892     exitText();
893
894     RefPtr<Node> newNode = new CDATASection(m_doc, toString(s, len));
895     if (!m_currentNode->addChild(newNode.get()))
896         return;
897     if (m_view && !newNode->attached())
898         newNode->attach();
899 }
900
901 void XMLTokenizer::comment(const xmlChar* s)
902 {
903     if (m_parserStopped)
904         return;
905
906     if (m_parserPaused) {
907         m_pendingCallbacks->appendCommentCallback(s);
908         return;
909     }
910     
911     exitText();
912
913     RefPtr<Node> newNode = new Comment(m_doc, toString(s));
914     m_currentNode->addChild(newNode.get());
915     if (m_view && !newNode->attached())
916         newNode->attach();
917 }
918
919 void XMLTokenizer::startDocument(const xmlChar* version, const xmlChar* encoding, int standalone)
920 {
921     ExceptionCode ec = 0;
922     
923     if (version)
924         m_doc->setXMLVersion(toString(version), ec);
925     m_doc->setXMLStandalone(standalone == 1, ec); // possible values are 0, 1, and -1
926     if (encoding)
927         m_doc->setXMLEncoding(toString(encoding));
928 }
929
930 void XMLTokenizer::internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
931 {
932     if (m_parserStopped)
933         return;
934
935     if (m_parserPaused) {
936         m_pendingCallbacks->appendInternalSubsetCallback(name, externalID, systemID);
937         return;
938     }
939     
940     Document* doc = m_doc;
941     if (!doc)
942         return;
943
944     doc->setDocType(new DocumentType(doc, toString(name), toString(externalID), toString(systemID)));
945 }
946
947 inline XMLTokenizer* getTokenizer(void* closure)
948 {
949     xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure);
950     return static_cast<XMLTokenizer*>(ctxt->_private);
951 }
952
953 // This is a hack around http://bugzilla.gnome.org/show_bug.cgi?id=159219
954 // Otherwise libxml seems to call all the SAX callbacks twice for any replaced entity.
955 static inline bool hackAroundLibXMLEntityBug(void* closure)
956 {
957 #if LIBXML_VERSION >= 20627
958     // This bug has been fixed in libxml 2.6.27.
959     return false;
960 #else
961     return static_cast<xmlParserCtxtPtr>(closure)->node;
962 #endif
963 }
964
965 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)
966 {
967     if (hackAroundLibXMLEntityBug(closure))
968         return;
969
970     getTokenizer(closure)->startElementNs(localname, prefix, uri, nb_namespaces, namespaces, nb_attributes, nb_defaulted, libxmlAttributes);
971 }
972
973 static void endElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix, const xmlChar* uri)
974 {
975     if (hackAroundLibXMLEntityBug(closure))
976         return;
977     
978     getTokenizer(closure)->endElementNs();
979 }
980
981 static void charactersHandler(void* closure, const xmlChar* s, int len)
982 {
983     if (hackAroundLibXMLEntityBug(closure))
984         return;
985     
986     getTokenizer(closure)->characters(s, len);
987 }
988
989 static void processingInstructionHandler(void* closure, const xmlChar* target, const xmlChar* data)
990 {
991     if (hackAroundLibXMLEntityBug(closure))
992         return;
993     
994     getTokenizer(closure)->processingInstruction(target, data);
995 }
996
997 static void cdataBlockHandler(void* closure, const xmlChar* s, int len)
998 {
999     if (hackAroundLibXMLEntityBug(closure))
1000         return;
1001     
1002     getTokenizer(closure)->cdataBlock(s, len);
1003 }
1004
1005 static void commentHandler(void* closure, const xmlChar* comment)
1006 {
1007     if (hackAroundLibXMLEntityBug(closure))
1008         return;
1009     
1010     getTokenizer(closure)->comment(comment);
1011 }
1012
1013 static void warningHandler(void* closure, const char* message, ...)
1014 {
1015     va_list args;
1016     va_start(args, message);
1017     getTokenizer(closure)->error(XMLTokenizer::warning, message, args);
1018     va_end(args);
1019 }
1020
1021 static void fatalErrorHandler(void* closure, const char* message, ...)
1022 {
1023     va_list args;
1024     va_start(args, message);
1025     getTokenizer(closure)->error(XMLTokenizer::fatal, message, args);
1026     va_end(args);
1027 }
1028
1029 static void normalErrorHandler(void* closure, const char* message, ...)
1030 {
1031     va_list args;
1032     va_start(args, message);
1033     getTokenizer(closure)->error(XMLTokenizer::nonFatal, message, args);
1034     va_end(args);
1035 }
1036
1037 // Using a global variable entity and marking it XML_INTERNAL_PREDEFINED_ENTITY is
1038 // a hack to avoid malloc/free. Using a global variable like this could cause trouble
1039 // if libxml implementation details were to change
1040 static xmlChar sharedXHTMLEntityResult[5] = {0,0,0,0,0};
1041 static xmlEntity sharedXHTMLEntity = {
1042     0, XML_ENTITY_DECL, 0, 0, 0, 0, 0, 0, 0, 
1043     sharedXHTMLEntityResult, sharedXHTMLEntityResult, 0,
1044     XML_INTERNAL_PREDEFINED_ENTITY, 0, 0, 0, 0, 0
1045 };
1046
1047 static xmlEntityPtr getXHTMLEntity(const xmlChar* name)
1048 {
1049     UChar c = decodeNamedEntity(reinterpret_cast<const char*>(name));
1050     if (!c)
1051         return 0;
1052
1053     CString value = String(&c, 1).utf8();
1054     ASSERT(value.length() < 5);
1055     sharedXHTMLEntity.length = value.length();
1056     sharedXHTMLEntity.name = name;
1057     memcpy(sharedXHTMLEntityResult, value.data(), sharedXHTMLEntity.length + 1);
1058
1059     return &sharedXHTMLEntity;
1060 }
1061
1062 static xmlEntityPtr getEntityHandler(void* closure, const xmlChar* name)
1063 {
1064     xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure);
1065     xmlEntityPtr ent = xmlGetPredefinedEntity(name);
1066     if (ent) {
1067         ent->etype = XML_INTERNAL_PREDEFINED_ENTITY;
1068         return ent;
1069     }
1070
1071     ent = xmlGetDocEntity(ctxt->myDoc, name);
1072     if (!ent && getTokenizer(closure)->isXHTMLDocument()) {
1073         ent = getXHTMLEntity(name);
1074         if (ent)
1075             ent->etype = XML_INTERNAL_GENERAL_ENTITY;
1076     }
1077     
1078     return ent;
1079 }
1080
1081 static void startDocumentHandler(void* closure)
1082 {
1083     xmlParserCtxt* ctxt = static_cast<xmlParserCtxt*>(closure);
1084     getTokenizer(closure)->startDocument(ctxt->version, ctxt->encoding, ctxt->standalone);
1085     xmlSAX2StartDocument(closure);
1086 }
1087
1088 static void internalSubsetHandler(void* closure, const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID)
1089 {
1090     getTokenizer(closure)->internalSubset(name, externalID, systemID);
1091     xmlSAX2InternalSubset(closure, name, externalID, systemID);
1092 }
1093
1094 static void externalSubsetHandler(void* closure, const xmlChar* name, const xmlChar* externalId, const xmlChar* systemId)
1095 {
1096     String extId = toString(externalId);
1097     if ((extId == "-//W3C//DTD XHTML 1.0 Transitional//EN")
1098         || (extId == "-//W3C//DTD XHTML 1.1//EN")
1099         || (extId == "-//W3C//DTD XHTML 1.0 Strict//EN")
1100         || (extId == "-//W3C//DTD XHTML 1.0 Frameset//EN")
1101         || (extId == "-//W3C//DTD XHTML Basic 1.0//EN")
1102         || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN")
1103         || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN")
1104         || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"))
1105         getTokenizer(closure)->setIsXHTMLDocument(true); // controls if we replace entities or not.
1106 }
1107
1108 static void ignorableWhitespaceHandler(void* ctx, const xmlChar* ch, int len)
1109 {
1110     // nothing to do, but we need this to work around a crasher
1111     // http://bugzilla.gnome.org/show_bug.cgi?id=172255
1112     // http://bugs.webkit.org/show_bug.cgi?id=5792
1113 }
1114 #endif
1115
1116 void XMLTokenizer::handleError(ErrorType type, const char* m, int lineNumber, int columnNumber)
1117 {
1118     if (type == fatal || (m_errorCount < maxErrors && m_lastErrorLine != lineNumber && m_lastErrorColumn != columnNumber)) {
1119         switch (type) {
1120             case warning:
1121                 m_errorMessages += String::format("warning on line %d at column %d: %s", lineNumber, columnNumber, m);
1122                 break;
1123             case fatal:
1124             case nonFatal:
1125                 m_errorMessages += String::format("error on line %d at column %d: %s", lineNumber, columnNumber, m);
1126         }
1127         
1128         m_lastErrorLine = lineNumber;
1129         m_lastErrorColumn = columnNumber;
1130         ++m_errorCount;
1131     }
1132     
1133     if (type != warning)
1134         m_sawError = true;
1135     
1136     if (type == fatal)
1137         stopParsing();    
1138 }
1139
1140 bool XMLTokenizer::enterText()
1141 {
1142     RefPtr<Node> newNode = new Text(m_doc, "");
1143     if (!m_currentNode->addChild(newNode.get()))
1144         return false;
1145     setCurrentNode(newNode.get());
1146     return true;
1147 }
1148
1149 void XMLTokenizer::exitText()
1150 {
1151     if (m_parserStopped)
1152         return;
1153
1154     if (!m_currentNode || !m_currentNode->isTextNode())
1155         return;
1156
1157     if (m_view && m_currentNode && !m_currentNode->attached())
1158         m_currentNode->attach();
1159
1160     // FIXME: What's the right thing to do if the parent is really 0?
1161     // Just leaving the current node set to the text node doesn't make much sense.
1162     if (Node* par = m_currentNode->parentNode())
1163         setCurrentNode(par);
1164 }
1165
1166 void XMLTokenizer::initializeParserContext()
1167 {
1168 #ifndef USE_QXMLSTREAM
1169     xmlSAXHandler sax;
1170     memset(&sax, 0, sizeof(sax));
1171     sax.error = normalErrorHandler;
1172     sax.fatalError = fatalErrorHandler;
1173     sax.characters = charactersHandler;
1174     sax.processingInstruction = processingInstructionHandler;
1175     sax.cdataBlock = cdataBlockHandler;
1176     sax.comment = commentHandler;
1177     sax.warning = warningHandler;
1178     sax.startElementNs = startElementNsHandler;
1179     sax.endElementNs = endElementNsHandler;
1180     sax.getEntity = getEntityHandler;
1181     sax.startDocument = startDocumentHandler;
1182     sax.internalSubset = internalSubsetHandler;
1183     sax.externalSubset = externalSubsetHandler;
1184     sax.ignorableWhitespace = ignorableWhitespaceHandler;
1185     sax.entityDecl = xmlSAX2EntityDecl;
1186     sax.initialized = XML_SAX2_MAGIC;
1187 #endif
1188     m_parserStopped = false;
1189     m_sawError = false;
1190     m_sawXSLTransform = false;
1191     m_sawFirstElement = false;
1192     
1193 #ifndef USE_QXMLSTREAM
1194     m_context = createStringParser(&sax, this);
1195 #endif
1196 }
1197
1198 void XMLTokenizer::end()
1199 {
1200 #if ENABLE(XSLT)
1201     if (m_sawXSLTransform) {
1202         m_doc->setTransformSource(xmlDocPtrForString(m_doc->docLoader(), m_originalSourceForTransform, m_doc->URL()));
1203         
1204         m_doc->setParsing(false); // Make the doc think it's done, so it will apply xsl sheets.
1205         m_doc->updateStyleSelector();
1206         m_doc->setParsing(true);
1207         m_parserStopped = true;
1208     }
1209 #endif
1210
1211 #ifndef USE_QXMLSTREAM
1212     if (m_context) {
1213         // Tell libxml we're done.
1214         xmlParseChunk(m_context, 0, 0, 1);
1215         
1216         if (m_context->myDoc)
1217             xmlFreeDoc(m_context->myDoc);
1218         xmlFreeParserCtxt(m_context);
1219         m_context = 0;
1220     }
1221 #else
1222     if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError) {
1223         handleError(warning, qPrintable(m_stream.errorString()), lineNumber(),
1224                     columnNumber());
1225     }
1226 #endif
1227     
1228     if (m_sawError)
1229         insertErrorMessageBlock();
1230     else {
1231         exitText();
1232         m_doc->updateStyleSelector();
1233     }
1234     
1235     setCurrentNode(0);
1236     m_doc->finishedParsing();    
1237 }
1238
1239 void XMLTokenizer::finish()
1240 {
1241     if (m_parserPaused)
1242         m_finishCalled = true;
1243     else
1244         end();
1245 }
1246
1247 static inline RefPtr<Element> createXHTMLParserErrorHeader(Document* doc, const String& errorMessages) 
1248 {
1249     ExceptionCode ec = 0;
1250     RefPtr<Element> reportElement = doc->createElementNS(xhtmlNamespaceURI, "parsererror", ec);
1251     reportElement->setAttribute(styleAttr, "white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black");
1252     
1253     RefPtr<Element> h3 = doc->createElementNS(xhtmlNamespaceURI, "h3", ec);
1254     reportElement->appendChild(h3.get(), ec);
1255     h3->appendChild(doc->createTextNode("This page contains the following errors:"), ec);
1256     
1257     RefPtr<Element> fixed = doc->createElementNS(xhtmlNamespaceURI, "div", ec);
1258     reportElement->appendChild(fixed.get(), ec);
1259     fixed->setAttribute(styleAttr, "font-family:monospace;font-size:12px");
1260     fixed->appendChild(doc->createTextNode(errorMessages), ec);
1261     
1262     h3 = doc->createElementNS(xhtmlNamespaceURI, "h3", ec);
1263     reportElement->appendChild(h3.get(), ec);
1264     h3->appendChild(doc->createTextNode("Below is a rendering of the page up to the first error."), ec);
1265     
1266     return reportElement;
1267 }
1268
1269 void XMLTokenizer::insertErrorMessageBlock()
1270 {
1271     // One or more errors occurred during parsing of the code. Display an error block to the user above
1272     // the normal content (the DOM tree is created manually and includes line/col info regarding 
1273     // where the errors are located)
1274
1275     // Create elements for display
1276     ExceptionCode ec = 0;
1277     Document* doc = m_doc;
1278     Node* documentElement = doc->documentElement();
1279     if (!documentElement) {
1280         RefPtr<Node> rootElement = doc->createElementNS(xhtmlNamespaceURI, "html", ec);
1281         doc->appendChild(rootElement, ec);
1282         RefPtr<Node> body = doc->createElementNS(xhtmlNamespaceURI, "body", ec);
1283         rootElement->appendChild(body, ec);
1284         documentElement = body.get();
1285     }
1286 #if ENABLE(SVG)
1287     else if (documentElement->namespaceURI() == SVGNames::svgNamespaceURI) {
1288         // Until our SVG implementation has text support, it is best if we 
1289         // wrap the erroneous SVG document in an xhtml document and render
1290         // the combined document with error messages.
1291         RefPtr<Node> rootElement = doc->createElementNS(xhtmlNamespaceURI, "html", ec);
1292         RefPtr<Node> body = doc->createElementNS(xhtmlNamespaceURI, "body", ec);
1293         rootElement->appendChild(body, ec);
1294         body->appendChild(documentElement, ec);
1295         doc->appendChild(rootElement.get(), ec);
1296         documentElement = body.get();
1297     }
1298 #endif
1299
1300     RefPtr<Element> reportElement = createXHTMLParserErrorHeader(doc, m_errorMessages);
1301     documentElement->insertBefore(reportElement, documentElement->firstChild(), ec);
1302 #if ENABLE(XSLT)
1303     if (doc->transformSourceDocument()) {
1304         RefPtr<Element> par = doc->createElementNS(xhtmlNamespaceURI, "p", ec);
1305         reportElement->appendChild(par, ec);
1306         par->setAttribute(styleAttr, "white-space: normal");
1307         par->appendChild(doc->createTextNode("This document was created as the result of an XSL transformation. The line and column numbers given are from the transformed result."), ec);
1308     }
1309 #endif
1310     doc->updateRendering();
1311 }
1312
1313 void XMLTokenizer::notifyFinished(CachedResource* finishedObj)
1314 {
1315     ASSERT(m_pendingScript == finishedObj);
1316     ASSERT(m_pendingScript->accessCount() > 0);
1317         
1318     String cachedScriptUrl = m_pendingScript->url();
1319     String scriptSource = m_pendingScript->script();
1320     bool errorOccurred = m_pendingScript->errorOccurred();
1321     m_pendingScript->deref(this);
1322     m_pendingScript = 0;
1323     
1324     RefPtr<Element> e = m_scriptElement;
1325     m_scriptElement = 0;
1326     
1327     if (errorOccurred) 
1328         EventTargetNodeCast(e.get())->dispatchHTMLEvent(errorEvent, true, false);
1329     else {
1330         m_view->frame()->loader()->executeScript(cachedScriptUrl, 0, scriptSource);
1331         EventTargetNodeCast(e.get())->dispatchHTMLEvent(loadEvent, false, false);
1332     }
1333     
1334     m_scriptElement = 0;
1335     
1336     if (!m_requestingScript)
1337         resumeParsing();
1338 }
1339
1340 bool XMLTokenizer::isWaitingForScripts() const
1341 {
1342     return m_pendingScript != 0;
1343 }
1344
1345 #if ENABLE(XSLT)
1346 void* xmlDocPtrForString(DocLoader* docLoader, const String& source, const DeprecatedString& url)
1347 {
1348     if (source.isEmpty())
1349         return 0;
1350
1351     // Parse in a single chunk into an xmlDocPtr
1352     // FIXME: Hook up error handlers so that a failure to parse the main document results in
1353     // good error messages.
1354     const UChar BOM = 0xFEFF;
1355     const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
1356
1357     xmlGenericErrorFunc oldErrorFunc = xmlGenericError;
1358     void* oldErrorContext = xmlGenericErrorContext;
1359     
1360     setLoaderForLibXMLCallbacks(docLoader);        
1361     xmlSetGenericErrorFunc(0, errorFunc);
1362     
1363     xmlDocPtr sourceDoc = xmlReadMemory(reinterpret_cast<const char*>(source.characters()),
1364                                         source.length() * sizeof(UChar),
1365                                         url.ascii(),
1366                                         BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE", 
1367                                         XSLT_PARSE_OPTIONS);
1368     
1369     setLoaderForLibXMLCallbacks(0);
1370     xmlSetGenericErrorFunc(oldErrorContext, oldErrorFunc);
1371     
1372     return sourceDoc;
1373 }
1374 #endif
1375
1376 int XMLTokenizer::lineNumber() const
1377 {
1378 #ifndef USE_QXMLSTREAM
1379     return m_context->input->line;
1380 #else
1381     return m_stream.lineNumber();
1382 #endif
1383 }
1384
1385 int XMLTokenizer::columnNumber() const
1386 {
1387 #ifndef USE_QXMLSTREAM
1388     return m_context->input->col;
1389 #else
1390     return m_stream.columnNumber();
1391 #endif
1392 }
1393
1394 void XMLTokenizer::stopParsing()
1395 {
1396     Tokenizer::stopParsing();
1397 #ifndef USE_QXMLSTREAM
1398     xmlStopParser(m_context);
1399 #endif
1400 }
1401
1402 void XMLTokenizer::pauseParsing()
1403 {
1404     if (m_parsingFragment)
1405         return;
1406     
1407     m_parserPaused = true;
1408 }
1409
1410 void XMLTokenizer::resumeParsing()
1411 {
1412     ASSERT(m_parserPaused);
1413     
1414     m_parserPaused = false;
1415
1416     // First, execute any pending callbacks
1417 #ifndef USE_QXMLSTREAM
1418     while (!m_pendingCallbacks->isEmpty()) {
1419         m_pendingCallbacks->callAndRemoveFirstCallback(this);
1420         
1421         // A callback paused the parser
1422         if (m_parserPaused)
1423             return;
1424     }
1425 #else
1426     parse();
1427     if (m_parserPaused)
1428         return;
1429 #endif
1430
1431     // Then, write any pending data
1432     SegmentedString rest = m_pendingSrc;
1433     m_pendingSrc.clear();
1434     write(rest, false);
1435
1436     // Finally, if finish() has been called and write() didn't result
1437     // in any further callbacks being queued, call end()
1438     if (m_finishCalled
1439 #ifndef USE_QXMLSTREAM
1440         && m_pendingCallbacks->isEmpty())
1441 #else
1442         )
1443 #endif
1444         end();
1445 }
1446
1447 #ifndef USE_QXMLSTREAM
1448 static void balancedStartElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix,
1449                                           const xmlChar* uri, int nb_namespaces, const xmlChar** namespaces,
1450                                           int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes)
1451 {
1452    static_cast<XMLTokenizer*>(closure)->startElementNs(localname, prefix, uri, nb_namespaces, namespaces, nb_attributes, nb_defaulted, libxmlAttributes);
1453 }
1454
1455 static void balancedEndElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix, const xmlChar* uri)
1456 {
1457     static_cast<XMLTokenizer*>(closure)->endElementNs();
1458 }
1459
1460 static void balancedCharactersHandler(void* closure, const xmlChar* s, int len)
1461 {
1462     static_cast<XMLTokenizer*>(closure)->characters(s, len);
1463 }
1464
1465 static void balancedProcessingInstructionHandler(void* closure, const xmlChar* target, const xmlChar* data)
1466 {
1467     static_cast<XMLTokenizer*>(closure)->processingInstruction(target, data);
1468 }
1469
1470 static void balancedCdataBlockHandler(void* closure, const xmlChar* s, int len)
1471 {
1472     static_cast<XMLTokenizer*>(closure)->cdataBlock(s, len);
1473 }
1474
1475 static void balancedCommentHandler(void* closure, const xmlChar* comment)
1476 {
1477     static_cast<XMLTokenizer*>(closure)->comment(comment);
1478 }
1479
1480 static void balancedWarningHandler(void* closure, const char* message, ...)
1481 {
1482     va_list args;
1483     va_start(args, message);
1484     static_cast<XMLTokenizer*>(closure)->error(XMLTokenizer::warning, message, args);
1485     va_end(args);
1486 }
1487 #endif
1488 bool parseXMLDocumentFragment(const String& string, DocumentFragment* fragment, Element* parent)
1489 {
1490     XMLTokenizer tokenizer(fragment, parent);
1491     
1492 #ifndef USE_QXMLSTREAM
1493     xmlSAXHandler sax;
1494     memset(&sax, 0, sizeof(sax));
1495
1496     sax.characters = balancedCharactersHandler;
1497     sax.processingInstruction = balancedProcessingInstructionHandler;
1498     sax.startElementNs = balancedStartElementNsHandler;
1499     sax.endElementNs = balancedEndElementNsHandler;
1500     sax.cdataBlock = balancedCdataBlockHandler;
1501     sax.ignorableWhitespace = balancedCdataBlockHandler;
1502     sax.comment = balancedCommentHandler;
1503     sax.warning = balancedWarningHandler;
1504     sax.initialized = XML_SAX2_MAGIC;
1505     
1506     int result = xmlParseBalancedChunkMemory(0, &sax, &tokenizer, 0, (const xmlChar*)string.utf8().data(), 0);
1507     return result == 0;
1508 #else
1509     tokenizer.write(string, false);
1510     tokenizer.finish();
1511     return tokenizer.hasError();
1512 #endif
1513 }
1514
1515 // --------------------------------
1516
1517 struct AttributeParseState {
1518     HashMap<String, String> attributes;
1519     bool gotAttributes;
1520 };
1521
1522 #ifndef USE_QXMLSTREAM
1523 static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLocalName, const xmlChar* xmlPrefix,
1524                                             const xmlChar* xmlURI, int nb_namespaces, const xmlChar** namespaces,
1525                                             int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes)
1526 {
1527     if (strcmp(reinterpret_cast<const char*>(xmlLocalName), "attrs") != 0)
1528         return;
1529     
1530     xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure);
1531     AttributeParseState* state = static_cast<AttributeParseState*>(ctxt->_private);
1532     
1533     state->gotAttributes = true;
1534     
1535     xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlAttributes);
1536     for(int i = 0; i < nb_attributes; i++) {
1537         String attrLocalName = toString(attributes[i].localname);
1538         int valueLength = (int) (attributes[i].end - attributes[i].value);
1539         String attrValue = toString(attributes[i].value, valueLength);
1540         String attrPrefix = toString(attributes[i].prefix);
1541         String attrQName = attrPrefix.isEmpty() ? attrLocalName : attrPrefix + ":" + attrLocalName;
1542         
1543         state->attributes.set(attrQName, attrValue);
1544     }
1545 }
1546 #else
1547 static void attributesStartElementNsHandler(AttributeParseState* state, const QXmlStreamAttributes& attrs)
1548 {
1549     if (attrs.count() <= 0)
1550         return;
1551
1552     state->gotAttributes = true;
1553
1554     for(int i = 0; i < attrs.count(); i++) {
1555         const QXmlStreamAttribute& attr = attrs[i];
1556         String attrLocalName = attr.name().toString();
1557         String attrValue     = attr.value().toString();
1558         String attrURI       = attr.namespaceUri().toString();
1559         String attrQName     = attr.qualifiedName().toString();
1560         state->attributes.set(attrQName, attrValue);
1561     }
1562 }
1563 #endif
1564
1565 HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
1566 {
1567     AttributeParseState state;
1568     state.gotAttributes = false;
1569
1570 #ifndef USE_QXMLSTREAM
1571     xmlSAXHandler sax;
1572     memset(&sax, 0, sizeof(sax));
1573     sax.startElementNs = attributesStartElementNsHandler;
1574     sax.initialized = XML_SAX2_MAGIC;
1575     xmlParserCtxtPtr parser = createStringParser(&sax, &state);
1576     String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
1577     xmlParseChunk(parser, reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
1578     if (parser->myDoc)
1579         xmlFreeDoc(parser->myDoc);
1580     xmlFreeParserCtxt(parser);
1581 #else
1582     QXmlStreamReader stream;
1583     QString dummy = QString("<?xml version=\"1.0\"?><attrs %1 />").arg(string);
1584     stream.addData(dummy);
1585     while (!stream.atEnd()) {
1586         stream.readNext();
1587         if (stream.isStartElement()) {
1588             attributesStartElementNsHandler(&state, stream.attributes());
1589         }
1590     }
1591 #endif
1592     attrsOK = state.gotAttributes;
1593     return state.attributes;
1594 }
1595
1596 #ifdef USE_QXMLSTREAM
1597 static inline String prefixFromQName(const QString& qName)
1598 {
1599     const int offset = qName.indexOf(QLatin1Char(':'));
1600     if (offset <= 0)
1601         return String();
1602     else
1603         return qName.left(offset);
1604 }
1605 static inline void handleElementNamespaces(Element* newElement, const QXmlStreamNamespaceDeclarations &ns,
1606                                            ExceptionCode& ec)
1607 {
1608     for (int i = 0; i < ns.count(); ++i) {
1609         const QXmlStreamNamespaceDeclaration &decl = ns[i];
1610         String namespaceQName = "xmlns";
1611         String namespaceURI = decl.namespaceUri().toString();
1612         if (!decl.prefix().isEmpty())
1613             namespaceQName = QLatin1String("xmlns:") + decl.prefix().toString();
1614         newElement->setAttributeNS("http://www.w3.org/2000/xmlns/", namespaceQName, namespaceURI, ec);
1615         if (ec) // exception setting attributes
1616             return;
1617     }
1618 }
1619
1620 static inline void handleElementAttributes(Element* newElement, const QXmlStreamAttributes &attrs, ExceptionCode& ec)
1621 {
1622     for (int i = 0; i < attrs.count(); ++i) {
1623         const QXmlStreamAttribute &attr = attrs[i];
1624         String attrLocalName = attr.name().toString();
1625         String attrValue     = attr.value().toString();
1626         String attrURI       = attr.namespaceUri().isEmpty() ? String() : String(attr.namespaceUri().toString());
1627         String attrQName     = attr.qualifiedName().toString();
1628         newElement->setAttributeNS(attrURI, attrQName, attrValue, ec);
1629         if (ec) // exception setting attributes
1630             return;
1631     }
1632 }
1633
1634 void XMLTokenizer::parse()
1635 {
1636     while (!m_parserStopped && !m_parserPaused && !m_stream.atEnd()) {
1637         m_stream.readNext();
1638         switch (m_stream.tokenType()) {
1639         case QXmlStreamReader::StartDocument: {
1640             startDocument();
1641         }
1642             break;
1643         case QXmlStreamReader::EndDocument: {
1644             endDocument();
1645         }
1646             break;
1647         case QXmlStreamReader::StartElement: {
1648             parseStartElement();
1649         }
1650             break;
1651         case QXmlStreamReader::EndElement: {
1652             parseEndElement();
1653         }
1654             break;
1655         case QXmlStreamReader::Characters: {
1656             if (m_stream.isCDATA()) {
1657                 //cdata
1658                 parseCdata();
1659             } else {
1660                 //characters
1661                 parseCharacters();
1662             }
1663         }
1664             break;
1665         case QXmlStreamReader::Comment: {
1666             parseComment();
1667         }
1668             break;
1669         case QXmlStreamReader::DTD: {
1670             //qDebug()<<"------------- DTD";
1671             parseDtd();
1672         }
1673             break;
1674         case QXmlStreamReader::EntityReference: {
1675             //qDebug()<<"---------- ENTITY = "<<m_stream.name().toString()
1676             //        <<", t = "<<m_stream.text().toString();
1677             if (isXHTMLDocument()) {
1678                 QString entity = m_stream.name().toString();
1679                 UChar c = decodeNamedEntity(entity.toUtf8().constData());
1680                 if (m_currentNode->isTextNode() || enterText()) {
1681                     ExceptionCode ec = 0;
1682                     String str(&c, 1);
1683                     //qDebug()<<" ------- adding entity "<<str;
1684                     static_cast<Text*>(m_currentNode)->appendData(str, ec);
1685                 }
1686             }
1687         }
1688             break;
1689         case QXmlStreamReader::ProcessingInstruction: {
1690             parseProcessingInstruction();
1691         }
1692             break;
1693         default: {
1694             if (m_stream.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
1695                 ErrorType type = (m_stream.error() == QXmlStreamReader::NotWellFormedError) ?
1696                                  fatal : warning;
1697                 handleError(type, qPrintable(m_stream.errorString()), lineNumber(),
1698                             columnNumber());
1699             }
1700         }
1701             break;
1702         }
1703     }
1704 }
1705
1706 void XMLTokenizer::startDocument()
1707 {
1708     initializeParserContext();
1709     ExceptionCode ec = 0;
1710
1711     m_doc->setXMLStandalone(m_stream.isStandaloneDocument(), ec);
1712 }
1713
1714 void XMLTokenizer::parseStartElement()
1715 {
1716     m_sawFirstElement = true;
1717
1718     exitText();
1719
1720     String localName = m_stream.name().toString();
1721     String uri       = m_stream.namespaceUri().toString();
1722     String prefix    = prefixFromQName(m_stream.qualifiedName().toString());
1723
1724     if (m_parsingFragment && uri.isNull()) {
1725         if (!prefix.isNull())
1726             uri = m_prefixToNamespaceMap.get(prefix);
1727         else
1728             uri = m_defaultNamespaceURI;
1729     }
1730
1731     ExceptionCode ec = 0;
1732     qDebug() << prefix << prefix.isNull() << localName << localName.isNull() << uri;
1733     QualifiedName qName(prefix, localName, uri);
1734     RefPtr<Element> newElement = m_doc->createElement(qName, true, ec);
1735     if (!newElement) {
1736         stopParsing();
1737         return;
1738     }
1739
1740     handleElementNamespaces(newElement.get(), m_stream.namespaceDeclarations(), ec);
1741     if (ec) {
1742         stopParsing();
1743         return;
1744     }
1745
1746     handleElementAttributes(newElement.get(), m_stream.attributes(), ec);
1747     if (ec) {
1748         stopParsing();
1749         return;
1750     }
1751
1752     if (newElement->hasTagName(scriptTag))
1753         static_cast<HTMLScriptElement*>(newElement.get())->setCreatedByParser(true);
1754
1755     if (newElement->hasTagName(HTMLNames::scriptTag)
1756 #if ENABLE(SVG)
1757         || newElement->hasTagName(SVGNames::scriptTag)
1758 #endif
1759         )
1760         m_scriptStartLine = lineNumber();
1761
1762     if (!m_currentNode->addChild(newElement.get())) {
1763         stopParsing();
1764         return;
1765     }
1766
1767     setCurrentNode(newElement.get());
1768     if (m_view && !newElement->attached())
1769         newElement->attach();
1770 }
1771
1772 void XMLTokenizer::parseEndElement()
1773 {
1774     exitText();
1775
1776     Node* n = m_currentNode;
1777     RefPtr<Node> parent = n->parentNode();
1778     n->closeRenderer();
1779
1780     // don't load external scripts for standalone documents (for now)
1781     if (n->isElementNode() && m_view && (static_cast<Element*>(n)->hasTagName(scriptTag) 
1782 #if ENABLE(SVG)
1783                                          || static_cast<Element*>(n)->hasTagName(SVGNames::scriptTag)
1784 #endif
1785                                          )) {
1786
1787
1788         ASSERT(!m_pendingScript);
1789
1790         m_requestingScript = true;
1791
1792         Element* scriptElement = static_cast<Element*>(n);
1793         String scriptHref;
1794
1795         if (static_cast<Element*>(n)->hasTagName(scriptTag))
1796             scriptHref = scriptElement->getAttribute(srcAttr);
1797 #if ENABLE(SVG)
1798         else if (static_cast<Element*>(n)->hasTagName(SVGNames::scriptTag))
1799             scriptHref = scriptElement->getAttribute(XLinkNames::hrefAttr);
1800 #endif
1801         if (!scriptHref.isEmpty()) {
1802             // we have a src attribute
1803             const AtomicString& charset = scriptElement->getAttribute(charsetAttr);
1804             if ((m_pendingScript = m_doc->docLoader()->requestScript(scriptHref, charset))) {
1805                 m_scriptElement = scriptElement;
1806                 m_pendingScript->ref(this);
1807
1808                 // m_pendingScript will be 0 if script was already loaded and ref() executed it
1809                 if (m_pendingScript)
1810                     pauseParsing();
1811             } else
1812                 m_scriptElement = 0;
1813
1814         } else {
1815             String scriptCode = "";
1816             for (Node* child = scriptElement->firstChild(); child; child = child->nextSibling()) {
1817                 if (child->isTextNode() || child->nodeType() == Node::CDATA_SECTION_NODE)
1818                     scriptCode += static_cast<CharacterData*>(child)->data();
1819             }
1820             m_view->frame()->loader()->executeScript(m_doc->URL(), m_scriptStartLine - 1, scriptCode);
1821         }
1822         m_requestingScript = false;
1823     }
1824
1825     setCurrentNode(parent.get());
1826 }
1827
1828 void XMLTokenizer::parseCharacters()
1829 {
1830     if (m_currentNode->isTextNode() || enterText()) {
1831         ExceptionCode ec = 0;
1832         static_cast<Text*>(m_currentNode)->appendData(m_stream.text().toString(), ec);
1833     }
1834 }
1835
1836 void XMLTokenizer::parseProcessingInstruction()
1837 {
1838     exitText();
1839
1840     // ### handle exceptions
1841     int exception = 0;
1842     RefPtr<ProcessingInstruction> pi = m_doc->createProcessingInstruction(
1843         m_stream.processingInstructionTarget().toString(),
1844         m_stream.processingInstructionData().toString(), exception);
1845     if (exception)
1846         return;
1847
1848     if (!m_currentNode->addChild(pi.get()))
1849         return;
1850     if (m_view && !pi->attached())
1851         pi->attach();
1852
1853     // don't load stylesheets for standalone documents
1854     if (m_doc->frame()) {
1855         m_sawXSLTransform = !m_sawFirstElement && !pi->checkStyleSheet();
1856         if (m_sawXSLTransform)
1857             stopParsing();
1858     }
1859 }
1860
1861 void XMLTokenizer::parseCdata()
1862 {
1863     exitText();
1864
1865     RefPtr<Node> newNode = new CDATASection(m_doc, m_stream.text().toString());
1866     if (!m_currentNode->addChild(newNode.get()))
1867         return;
1868     if (m_view && !newNode->attached())
1869         newNode->attach();
1870 }
1871
1872 void XMLTokenizer::parseComment()
1873 {
1874     exitText();
1875
1876     RefPtr<Node> newNode = new Comment(m_doc, m_stream.text().toString());
1877     m_currentNode->addChild(newNode.get());
1878     if (m_view && !newNode->attached())
1879         newNode->attach();
1880 }
1881
1882 void XMLTokenizer::endDocument()
1883 {
1884 }
1885
1886 bool XMLTokenizer::hasError() const
1887 {
1888     return m_stream.hasError();
1889 }
1890
1891 static QString parseId(const QString &dtd, int *pos, bool *ok)
1892 {
1893     *ok = true;
1894     int start = *pos + 1;
1895     int end = start;
1896     if (dtd.at(*pos) == QLatin1Char('\''))
1897         while (start < dtd.length() && dtd.at(end) != QLatin1Char('\''))
1898             ++end;
1899     else if (dtd.at(*pos) == QLatin1Char('\"'))
1900         while (start < dtd.length() && dtd.at(end) != QLatin1Char('\"'))
1901             ++end;
1902     else {
1903         *ok = false;
1904         return QString();
1905     }
1906     *pos = end + 1;
1907     return dtd.mid(start, end - start);
1908 }
1909
1910 void XMLTokenizer::parseDtd()
1911 {
1912     QString dtd = m_stream.text().toString();
1913
1914     int start = dtd.indexOf("<!DOCTYPE ") + 10;
1915     while (start < dtd.length() && dtd.at(start).isSpace())
1916         ++start;
1917     int end = start;
1918     while (start < dtd.length() && !dtd.at(end).isSpace())
1919         ++end;
1920     QString name = dtd.mid(start, end - start);
1921
1922     start = end;
1923     while (start < dtd.length() && dtd.at(start).isSpace())
1924         ++start;
1925     end = start;
1926     while (start < dtd.length() && !dtd.at(end).isSpace())
1927         ++end;
1928     QString id = dtd.mid(start, end - start);
1929     start = end;
1930     while (start < dtd.length() && dtd.at(start).isSpace())
1931         ++start;
1932     QString publicId;
1933     QString systemId;
1934     if (id == QLatin1String("PUBLIC")) {
1935         bool ok;
1936         publicId = parseId(dtd, &start, &ok);
1937         if (!ok) {
1938             handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber());
1939             return;
1940         }
1941         while (start < dtd.length() && dtd.at(start).isSpace())
1942             ++start;
1943         systemId = parseId(dtd, &start, &ok);
1944         if (!ok) {
1945             handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber());
1946             return;
1947         }
1948     } else if (id == QLatin1String("SYSTEM")) {
1949         bool ok;
1950         systemId = parseId(dtd, &start, &ok);
1951         if (!ok) {
1952             handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber());
1953             return;
1954         }
1955     } else if (id == QLatin1String("[") || id == QLatin1String(">")) {
1956     } else {
1957         handleError(fatal, "Invalid DOCTYPE", lineNumber(), columnNumber());
1958         return;
1959     }
1960     
1961     //qDebug() << dtd << name << publicId << systemId;
1962     const QXmlStreamNotationDeclarations& decls = m_stream.notationDeclarations();
1963
1964     if ((publicId == "-//W3C//DTD XHTML 1.0 Transitional//EN")
1965         || (publicId == "-//W3C//DTD XHTML 1.1//EN")
1966         || (publicId == "-//W3C//DTD XHTML 1.0 Strict//EN")
1967         || (publicId == "-//W3C//DTD XHTML 1.0 Frameset//EN")
1968         || (publicId == "-//W3C//DTD XHTML Basic 1.0//EN")
1969         || (publicId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN")
1970         || (publicId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN")
1971         || (publicId == "-//WAPFORUM//DTD XHTML Mobile 1.0//EN")) {
1972         setIsXHTMLDocument(true); // controls if we replace entities or not.
1973     }
1974     m_doc->setDocType(new DocumentType(m_doc, name, publicId, systemId));
1975     
1976 }
1977 #endif
1978 }
1979
1980