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