OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2000 Peter Kelly (pmk@post.com) | 2 * Copyright (C) 2000 Peter Kelly (pmk@post.com) |
3 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. | 3 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. |
4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 4 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
5 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) | 5 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) |
6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 6 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
7 * Copyright (C) 2008 Holger Hans Peter Freyther | 7 * Copyright (C) 2008 Holger Hans Peter Freyther |
8 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 8 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
9 * | 9 * |
10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
11 * modify it under the terms of the GNU Library General Public | 11 * modify it under the terms of the GNU Library General Public |
12 * License as published by the Free Software Foundation; either | 12 * License as published by the Free Software Foundation; either |
13 * version 2 of the License, or (at your option) any later version. | 13 * version 2 of the License, or (at your option) any later version. |
14 * | 14 * |
15 * This library is distributed in the hope that it will be useful, | 15 * This library is distributed in the hope that it will be useful, |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 * Library General Public License for more details. | 18 * Library General Public License for more details. |
19 * | 19 * |
20 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
23 * Boston, MA 02110-1301, USA. | 23 * Boston, MA 02110-1301, USA. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 #include "core/xml/parser/XMLDocumentParser.h" | 27 #include "core/xml/parser/XMLDocumentParser.h" |
28 | 28 |
29 #include <libxml/catalog.h> | |
30 #include <libxml/parser.h> | |
31 #include <libxml/parserInternals.h> | |
32 #include <libxslt/xslt.h> | |
33 #include "bindings/v8/ExceptionState.h" | 29 #include "bindings/v8/ExceptionState.h" |
34 #include "bindings/v8/ExceptionStatePlaceholder.h" | 30 #include "bindings/v8/ExceptionStatePlaceholder.h" |
35 #include "bindings/v8/ScriptController.h" | 31 #include "bindings/v8/ScriptController.h" |
36 #include "bindings/v8/ScriptSourceCode.h" | 32 #include "bindings/v8/ScriptSourceCode.h" |
37 #include "core/FetchInitiatorTypeNames.h" | 33 #include "core/FetchInitiatorTypeNames.h" |
38 #include "core/HTMLNames.h" | 34 #include "core/HTMLNames.h" |
39 #include "core/XMLNSNames.h" | 35 #include "core/XMLNSNames.h" |
40 #include "core/dom/CDATASection.h" | 36 #include "core/dom/CDATASection.h" |
41 #include "core/dom/Comment.h" | 37 #include "core/dom/Comment.h" |
42 #include "core/dom/Document.h" | 38 #include "core/dom/Document.h" |
(...skipping 21 matching lines...) Expand all Loading... |
64 #include "platform/SharedBuffer.h" | 60 #include "platform/SharedBuffer.h" |
65 #include "platform/network/ResourceError.h" | 61 #include "platform/network/ResourceError.h" |
66 #include "platform/network/ResourceRequest.h" | 62 #include "platform/network/ResourceRequest.h" |
67 #include "platform/network/ResourceResponse.h" | 63 #include "platform/network/ResourceResponse.h" |
68 #include "platform/weborigin/SecurityOrigin.h" | 64 #include "platform/weborigin/SecurityOrigin.h" |
69 #include "wtf/StringExtras.h" | 65 #include "wtf/StringExtras.h" |
70 #include "wtf/TemporaryChange.h" | 66 #include "wtf/TemporaryChange.h" |
71 #include "wtf/Threading.h" | 67 #include "wtf/Threading.h" |
72 #include "wtf/Vector.h" | 68 #include "wtf/Vector.h" |
73 #include "wtf/unicode/UTF8.h" | 69 #include "wtf/unicode/UTF8.h" |
| 70 #include <libxml/catalog.h> |
| 71 #include <libxml/parser.h> |
| 72 #include <libxml/parserInternals.h> |
| 73 #include <libxslt/xslt.h> |
74 | 74 |
75 namespace WebCore { | 75 namespace WebCore { |
76 | 76 |
77 using namespace HTMLNames; | 77 using namespace HTMLNames; |
78 | 78 |
79 // FIXME: HTMLConstructionSite has a limit of 512, should these match? | 79 // FIXME: HTMLConstructionSite has a limit of 512, should these match? |
80 static const unsigned maxXMLTreeDepth = 5000; | 80 static const unsigned maxXMLTreeDepth = 5000; |
81 | 81 |
82 static inline String toString(const xmlChar* string, size_t length) | 82 static inline String toString(const xmlChar* string, size_t length) |
83 { | 83 { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 PendingStartElementNSCallback(const AtomicString& localName, const AtomicStr
ing& prefix, const AtomicString& uri, | 121 PendingStartElementNSCallback(const AtomicString& localName, const AtomicStr
ing& prefix, const AtomicString& uri, |
122 int namespaceCount, const xmlChar** namespaces, int attributeCount, int
defaultedCount, const xmlChar** attributes) | 122 int namespaceCount, const xmlChar** namespaces, int attributeCount, int
defaultedCount, const xmlChar** attributes) |
123 : m_localName(localName) | 123 : m_localName(localName) |
124 , m_prefix(prefix) | 124 , m_prefix(prefix) |
125 , m_uri(uri) | 125 , m_uri(uri) |
126 , m_namespaceCount(namespaceCount) | 126 , m_namespaceCount(namespaceCount) |
127 , m_attributeCount(attributeCount) | 127 , m_attributeCount(attributeCount) |
128 , m_defaultedCount(defaultedCount) | 128 , m_defaultedCount(defaultedCount) |
129 { | 129 { |
130 m_namespaces = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * names
paceCount * 2)); | 130 m_namespaces = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * names
paceCount * 2)); |
131 for (int i = 0; i < namespaceCount * 2 ; i++) | 131 for (int i = 0; i < namespaceCount * 2 ; ++i) |
132 m_namespaces[i] = xmlStrdup(namespaces[i]); | 132 m_namespaces[i] = xmlStrdup(namespaces[i]); |
133 m_attributes = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * attri
buteCount * 5)); | 133 m_attributes = static_cast<xmlChar**>(xmlMalloc(sizeof(xmlChar*) * attri
buteCount * 5)); |
134 for (int i = 0; i < attributeCount; i++) { | 134 for (int i = 0; i < attributeCount; ++i) { |
135 // Each attribute has 5 elements in the array: | 135 // Each attribute has 5 elements in the array: |
136 // name, prefix, uri, value and an end pointer. | 136 // name, prefix, uri, value and an end pointer. |
137 for (int j = 0; j < 3; j++) | 137 for (int j = 0; j < 3; ++j) |
138 m_attributes[i * 5 + j] = xmlStrdup(attributes[i * 5 + j]); | 138 m_attributes[i * 5 + j] = xmlStrdup(attributes[i * 5 + j]); |
139 int length = attributes[i * 5 + 4] - attributes[i * 5 + 3]; | 139 int length = attributes[i * 5 + 4] - attributes[i * 5 + 3]; |
140 m_attributes[i * 5 + 3] = xmlStrndup(attributes[i * 5 + 3], length); | 140 m_attributes[i * 5 + 3] = xmlStrndup(attributes[i * 5 + 3], length); |
141 m_attributes[i * 5 + 4] = m_attributes[i * 5 + 3] + length; | 141 m_attributes[i * 5 + 4] = m_attributes[i * 5 + 3] + length; |
142 } | 142 } |
143 } | 143 } |
144 | 144 |
145 virtual ~PendingStartElementNSCallback() | 145 virtual ~PendingStartElementNSCallback() |
146 { | 146 { |
147 for (int i = 0; i < m_namespaceCount * 2; i++) | 147 for (int i = 0; i < m_namespaceCount * 2; ++i) |
148 xmlFree(m_namespaces[i]); | 148 xmlFree(m_namespaces[i]); |
149 xmlFree(m_namespaces); | 149 xmlFree(m_namespaces); |
150 for (int i = 0; i < m_attributeCount; i++) | 150 for (int i = 0; i < m_attributeCount; ++i) |
151 for (int j = 0; j < 4; j++) | 151 for (int j = 0; j < 4; ++j) |
152 xmlFree(m_attributes[i * 5 + j]); | 152 xmlFree(m_attributes[i * 5 + j]); |
153 xmlFree(m_attributes); | 153 xmlFree(m_attributes); |
154 } | 154 } |
155 | 155 |
156 virtual void call(XMLDocumentParser* parser) OVERRIDE | 156 virtual void call(XMLDocumentParser* parser) OVERRIDE |
157 { | 157 { |
158 parser->startElementNs(m_localName, m_prefix, m_uri, | 158 parser->startElementNs(m_localName, m_prefix, m_uri, |
159 m_namespaceCount, const_cast<const xmlChar**>(
m_namespaces), | 159 m_namespaceCount, const_cast<const xmlChar**>(m_namespaces), |
160 m_attributeCount, m_defaultedCount, const_cast
<const xmlChar**>(m_attributes)); | 160 m_attributeCount, m_defaultedCount, const_cast<const xmlChar**>(m_at
tributes)); |
161 } | 161 } |
162 | 162 |
163 private: | 163 private: |
164 AtomicString m_localName; | 164 AtomicString m_localName; |
165 AtomicString m_prefix; | 165 AtomicString m_prefix; |
166 AtomicString m_uri; | 166 AtomicString m_uri; |
167 int m_namespaceCount; | 167 int m_namespaceCount; |
168 xmlChar** m_namespaces; | 168 xmlChar** m_namespaces; |
169 int m_attributeCount; | 169 int m_attributeCount; |
170 int m_defaultedCount; | 170 int m_defaultedCount; |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 { | 297 { |
298 ASSERT(n); | 298 ASSERT(n); |
299 ASSERT(m_currentNode); | 299 ASSERT(m_currentNode); |
300 #if !ENABLE(OILPAN) | 300 #if !ENABLE(OILPAN) |
301 if (n != document()) | 301 if (n != document()) |
302 n->ref(); | 302 n->ref(); |
303 #endif | 303 #endif |
304 m_currentNodeStack.append(m_currentNode); | 304 m_currentNodeStack.append(m_currentNode); |
305 m_currentNode = n; | 305 m_currentNode = n; |
306 if (m_currentNodeStack.size() > maxXMLTreeDepth) | 306 if (m_currentNodeStack.size() > maxXMLTreeDepth) |
307 handleError(XMLErrors::fatal, "Excessive node nesting.", textPosition())
; | 307 handleError(XMLErrors::ErrorTypeFatal, "Excessive node nesting.", textPo
sition()); |
308 } | 308 } |
309 | 309 |
310 void XMLDocumentParser::popCurrentNode() | 310 void XMLDocumentParser::popCurrentNode() |
311 { | 311 { |
312 if (!m_currentNode) | 312 if (!m_currentNode) |
313 return; | 313 return; |
314 ASSERT(m_currentNodeStack.size()); | 314 ASSERT(m_currentNodeStack.size()); |
315 #if !ENABLE(OILPAN) | 315 #if !ENABLE(OILPAN) |
316 if (m_currentNode != document()) | 316 if (m_currentNode != document()) |
317 m_currentNode->deref(); | 317 m_currentNode->deref(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 // JavaScript can detach the parser. Make sure this is not released | 362 // JavaScript can detach the parser. Make sure this is not released |
363 // before the end of this method. | 363 // before the end of this method. |
364 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); | 364 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); |
365 | 365 |
366 doWrite(source.toString()); | 366 doWrite(source.toString()); |
367 } | 367 } |
368 | 368 |
369 void XMLDocumentParser::handleError(XMLErrors::ErrorType type, const char* forma
ttedMessage, TextPosition position) | 369 void XMLDocumentParser::handleError(XMLErrors::ErrorType type, const char* forma
ttedMessage, TextPosition position) |
370 { | 370 { |
371 m_xmlErrors.handleError(type, formattedMessage, position); | 371 m_xmlErrors.handleError(type, formattedMessage, position); |
372 if (type != XMLErrors::warning) | 372 if (type != XMLErrors::ErrorTypeWarning) |
373 m_sawError = true; | 373 m_sawError = true; |
374 if (type == XMLErrors::fatal) | 374 if (type == XMLErrors::ErrorTypeFatal) |
375 stopParsing(); | 375 stopParsing(); |
376 } | 376 } |
377 | 377 |
378 void XMLDocumentParser::enterText() | 378 void XMLDocumentParser::enterText() |
379 { | 379 { |
380 ASSERT(m_bufferedText.size() == 0); | 380 ASSERT(m_bufferedText.size() == 0); |
381 ASSERT(!m_leafTextNode); | 381 ASSERT(!m_leafTextNode); |
382 m_leafTextNode = Text::create(m_currentNode->document(), ""); | 382 m_leafTextNode = Text::create(m_currentNode->document(), ""); |
383 m_currentNode->parserAppendChild(m_leafTextNode.get()); | 383 m_currentNode->parserAppendChild(m_leafTextNode.get()); |
384 } | 384 } |
(...skipping 27 matching lines...) Expand all Loading... |
412 | 412 |
413 // doEnd() call above can detach the parser and null out its document. | 413 // doEnd() call above can detach the parser and null out its document. |
414 // In that case, we just bail out. | 414 // In that case, we just bail out. |
415 if (isDetached()) | 415 if (isDetached()) |
416 return; | 416 return; |
417 | 417 |
418 // doEnd() could process a script tag, thus pausing parsing. | 418 // doEnd() could process a script tag, thus pausing parsing. |
419 if (m_parserPaused) | 419 if (m_parserPaused) |
420 return; | 420 return; |
421 | 421 |
422 if (m_sawError) | 422 if (m_sawError) { |
423 insertErrorMessageBlock(); | 423 insertErrorMessageBlock(); |
424 else { | 424 } else { |
425 exitText(); | 425 exitText(); |
426 document()->styleResolverChanged(); | 426 document()->styleResolverChanged(); |
427 } | 427 } |
428 | 428 |
429 if (isParsing()) | 429 if (isParsing()) |
430 prepareToStopParsing(); | 430 prepareToStopParsing(); |
431 document()->setReadyState(Document::Interactive); | 431 document()->setReadyState(Document::Interactive); |
432 clearCurrentNodeStack(); | 432 clearCurrentNodeStack(); |
433 document()->finishedParsing(); | 433 document()->finishedParsing(); |
434 } | 434 } |
(...skipping 25 matching lines...) Expand all Loading... |
460 | 460 |
461 m_pendingScript->removeClient(this); | 461 m_pendingScript->removeClient(this); |
462 m_pendingScript = 0; | 462 m_pendingScript = 0; |
463 | 463 |
464 RefPtrWillBeRawPtr<Element> e = m_scriptElement; | 464 RefPtrWillBeRawPtr<Element> e = m_scriptElement; |
465 m_scriptElement = nullptr; | 465 m_scriptElement = nullptr; |
466 | 466 |
467 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(e.get()); | 467 ScriptLoader* scriptLoader = toScriptLoaderIfPossible(e.get()); |
468 ASSERT(scriptLoader); | 468 ASSERT(scriptLoader); |
469 | 469 |
470 // JavaScript can detach this parser, make sure it's kept alive even if deta
ched. | 470 // JavaScript can detach this parser, make sure it's kept alive even if |
| 471 // detached. |
471 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); | 472 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); |
472 | 473 |
473 if (errorOccurred) | 474 if (errorOccurred) { |
474 scriptLoader->dispatchErrorEvent(); | 475 scriptLoader->dispatchErrorEvent(); |
475 else if (!wasCanceled) { | 476 } else if (!wasCanceled) { |
476 scriptLoader->executeScript(sourceCode); | 477 scriptLoader->executeScript(sourceCode); |
477 scriptLoader->dispatchLoadEvent(); | 478 scriptLoader->dispatchLoadEvent(); |
478 } | 479 } |
479 | 480 |
480 m_scriptElement = nullptr; | 481 m_scriptElement = nullptr; |
481 | 482 |
482 if (!isDetached() && !m_requestingScript) | 483 if (!isDetached() && !m_requestingScript) |
483 resumeParsing(); | 484 resumeParsing(); |
484 } | 485 } |
485 | 486 |
486 bool XMLDocumentParser::isWaitingForScripts() const | 487 bool XMLDocumentParser::isWaitingForScripts() const |
487 { | 488 { |
488 return m_pendingScript; | 489 return m_pendingScript; |
489 } | 490 } |
490 | 491 |
491 void XMLDocumentParser::pauseParsing() | 492 void XMLDocumentParser::pauseParsing() |
492 { | 493 { |
493 if (m_parsingFragment) | 494 if (!m_parsingFragment) |
494 return; | 495 m_parserPaused = true; |
495 | |
496 m_parserPaused = true; | |
497 } | 496 } |
498 | 497 |
499 bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragm
ent* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) | 498 bool XMLDocumentParser::parseDocumentFragment(const String& chunk, DocumentFragm
ent* fragment, Element* contextElement, ParserContentPolicy parserContentPolicy) |
500 { | 499 { |
501 if (!chunk.length()) | 500 if (!chunk.length()) |
502 return true; | 501 return true; |
503 | 502 |
504 // FIXME: We need to implement the HTML5 XML Fragment parsing algorithm: | 503 // FIXME: We need to implement the HTML5 XML Fragment parsing algorithm: |
505 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syn
tax.html#xml-fragment-parsing-algorithm | 504 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-xhtml-syn
tax.html#xml-fragment-parsing-algorithm |
506 // For now we have a hack for script/style innerHTML support: | 505 // For now we have a hack for script/style innerHTML support: |
507 if (contextElement && (contextElement->hasLocalName(HTMLNames::scriptTag) ||
contextElement->hasLocalName(HTMLNames::styleTag))) { | 506 if (contextElement && (contextElement->hasLocalName(HTMLNames::scriptTag) ||
contextElement->hasLocalName(HTMLNames::styleTag))) { |
508 fragment->parserAppendChild(fragment->document().createTextNode(chunk)); | 507 fragment->parserAppendChild(fragment->document().createTextNode(chunk)); |
509 return true; | 508 return true; |
510 } | 509 } |
511 | 510 |
512 RefPtrWillBeRawPtr<XMLDocumentParser> parser = XMLDocumentParser::create(fra
gment, contextElement, parserContentPolicy); | 511 RefPtrWillBeRawPtr<XMLDocumentParser> parser = XMLDocumentParser::create(fra
gment, contextElement, parserContentPolicy); |
513 bool wellFormed = parser->appendFragmentSource(chunk); | 512 bool wellFormed = parser->appendFragmentSource(chunk); |
514 // Do not call finish(). Current finish() and doEnd() implementations touch
the main Document/loader | 513 |
515 // and can cause crashes in the fragment case. | 514 // Do not call finish(). Current finish() and doEnd() implementations touch |
516 parser->detach(); // Allows ~DocumentParser to assert it was detached before
destruction. | 515 // the main Document/loader and can cause crashes in the fragment case. |
517 return wellFormed; // appendFragmentSource()'s wellFormed is more permissive
than wellFormed(). | 516 |
| 517 // Allows ~DocumentParser to assert it was detached before destruction. |
| 518 parser->detach(); |
| 519 // appendFragmentSource()'s wellFormed is more permissive than wellFormed(). |
| 520 return wellFormed; |
518 } | 521 } |
519 | 522 |
520 static int globalDescriptor = 0; | 523 static int globalDescriptor = 0; |
521 static ThreadIdentifier libxmlLoaderThread = 0; | 524 static ThreadIdentifier libxmlLoaderThread = 0; |
522 | 525 |
523 static int matchFunc(const char*) | 526 static int matchFunc(const char*) |
524 { | 527 { |
525 // Only match loads initiated due to uses of libxml2 from within XMLDocument
Parser to avoid | 528 // Only match loads initiated due to uses of libxml2 from within |
526 // interfering with client applications that also use libxml2. http://bugs.
webkit.org/show_bug.cgi?id=17353 | 529 // XMLDocumentParser to avoid interfering with client applications that also |
| 530 // use libxml2. http://bugs.webkit.org/show_bug.cgi?id=17353 |
527 return XMLDocumentParserScope::currentFetcher && currentThread() == libxmlLo
aderThread; | 531 return XMLDocumentParserScope::currentFetcher && currentThread() == libxmlLo
aderThread; |
528 } | 532 } |
529 | 533 |
530 static inline void setAttributes(Element* element, Vector<Attribute>& attributeV
ector, ParserContentPolicy parserContentPolicy) | 534 static inline void setAttributes(Element* element, Vector<Attribute>& attributeV
ector, ParserContentPolicy parserContentPolicy) |
531 { | 535 { |
532 if (!scriptingContentIsAllowed(parserContentPolicy)) | 536 if (!scriptingContentIsAllowed(parserContentPolicy)) |
533 element->stripScriptingAttributes(attributeVector); | 537 element->stripScriptingAttributes(attributeVector); |
534 element->parserSetAttributes(attributeVector); | 538 element->parserSetAttributes(attributeVector); |
535 } | 539 } |
536 | 540 |
537 static void switchEncoding(xmlParserCtxtPtr ctxt, bool is8Bit) | 541 static void switchEncoding(xmlParserCtxtPtr ctxt, bool is8Bit) |
538 { | 542 { |
539 // Hack around libxml2's lack of encoding overide support by manually | 543 // Hack around libxml2's lack of encoding overide support by manually |
540 // resetting the encoding to UTF-16 before every chunk. Otherwise libxml | 544 // resetting the encoding to UTF-16 before every chunk. Otherwise libxml |
541 // will detect <?xml version="1.0" encoding="<encoding name>"?> blocks | 545 // will detect <?xml version="1.0" encoding="<encoding name>"?> blocks and |
542 // and switch encodings, causing the parse to fail. | 546 // switch encodings, causing the parse to fail. |
543 if (is8Bit) { | 547 if (is8Bit) { |
544 xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1); | 548 xmlSwitchEncoding(ctxt, XML_CHAR_ENCODING_8859_1); |
545 return; | 549 return; |
546 } | 550 } |
547 | 551 |
548 const UChar BOM = 0xFEFF; | 552 const UChar BOM = 0xFEFF; |
549 const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&B
OM); | 553 const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&B
OM); |
550 xmlSwitchEncoding(ctxt, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XM
L_CHAR_ENCODING_UTF16BE); | 554 xmlSwitchEncoding(ctxt, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XM
L_CHAR_ENCODING_UTF16BE); |
551 } | 555 } |
552 | 556 |
(...skipping 29 matching lines...) Expand all Loading... |
582 | 586 |
583 static bool shouldAllowExternalLoad(const KURL& url) | 587 static bool shouldAllowExternalLoad(const KURL& url) |
584 { | 588 { |
585 String urlString = url.string(); | 589 String urlString = url.string(); |
586 | 590 |
587 // This isn't really necessary now that initializeLibXMLIfNecessary | 591 // This isn't really necessary now that initializeLibXMLIfNecessary |
588 // disables catalog support in libxml, but keeping it for defense in depth. | 592 // disables catalog support in libxml, but keeping it for defense in depth. |
589 if (isLibxmlDefaultCatalogFile(url)) | 593 if (isLibxmlDefaultCatalogFile(url)) |
590 return false; | 594 return false; |
591 | 595 |
592 // The most common DTD. There isn't much point in hammering www.w3c.org | 596 // The most common DTD. There isn't much point in hammering www.w3c.org by |
593 // by requesting this URL for every XHTML document. | 597 // requesting this URL for every XHTML document. |
594 if (urlString.startsWith("http://www.w3.org/TR/xhtml", false)) | 598 if (urlString.startsWith("http://www.w3.org/TR/xhtml", false)) |
595 return false; | 599 return false; |
596 | 600 |
597 // Similarly, there isn't much point in requesting the SVG DTD. | 601 // Similarly, there isn't much point in requesting the SVG DTD. |
598 if (urlString.startsWith("http://www.w3.org/Graphics/SVG", false)) | 602 if (urlString.startsWith("http://www.w3.org/Graphics/SVG", false)) |
599 return false; | 603 return false; |
600 | 604 |
601 // The libxml doesn't give us a lot of context for deciding whether to | 605 // The libxml doesn't give us a lot of context for deciding whether to allow |
602 // allow this request. In the worst case, this load could be for an | 606 // this request. In the worst case, this load could be for an external |
603 // external entity and the resulting document could simply read the | 607 // entity and the resulting document could simply read the retrieved |
604 // retrieved content. If we had more context, we could potentially allow | 608 // content. If we had more context, we could potentially allow the parser to |
605 // the parser to load a DTD. As things stand, we take the conservative | 609 // load a DTD. As things stand, we take the conservative route and allow |
606 // route and allow same-origin requests only. | 610 // same-origin requests only. |
607 if (!XMLDocumentParserScope::currentFetcher->document()->securityOrigin()->c
anRequest(url)) { | 611 if (!XMLDocumentParserScope::currentFetcher->document()->securityOrigin()->c
anRequest(url)) { |
608 XMLDocumentParserScope::currentFetcher->printAccessDeniedMessage(url); | 612 XMLDocumentParserScope::currentFetcher->printAccessDeniedMessage(url); |
609 return false; | 613 return false; |
610 } | 614 } |
611 | 615 |
612 return true; | 616 return true; |
613 } | 617 } |
614 | 618 |
615 static void* openFunc(const char* uri) | 619 static void* openFunc(const char* uri) |
616 { | 620 { |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 | 861 |
858 void XMLDocumentParser::doWrite(const String& parseString) | 862 void XMLDocumentParser::doWrite(const String& parseString) |
859 { | 863 { |
860 ASSERT(!isDetached()); | 864 ASSERT(!isDetached()); |
861 if (!m_context) | 865 if (!m_context) |
862 initializeParserContext(); | 866 initializeParserContext(); |
863 | 867 |
864 // Protect the libxml context from deletion during a callback | 868 // Protect the libxml context from deletion during a callback |
865 RefPtr<XMLParserContext> context = m_context; | 869 RefPtr<XMLParserContext> context = m_context; |
866 | 870 |
867 // libXML throws an error if you try to switch the encoding for an empty str
ing. | 871 // libXML throws an error if you try to switch the encoding for an empty |
| 872 // string. |
868 if (parseString.length()) { | 873 if (parseString.length()) { |
869 // JavaScript may cause the parser to detach during parseChunk | 874 // JavaScript may cause the parser to detach during parseChunk |
870 // keep this alive until this function is done. | 875 // keep this alive until this function is done. |
871 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); | 876 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); |
872 | 877 |
873 XMLDocumentParserScope scope(document()->fetcher()); | 878 XMLDocumentParserScope scope(document()->fetcher()); |
874 TemporaryChange<bool> encodingScope(m_isCurrentlyParsing8BitChunk, parse
String.is8Bit()); | 879 TemporaryChange<bool> encodingScope(m_isCurrentlyParsing8BitChunk, parse
String.is8Bit()); |
875 parseChunk(context->context(), parseString); | 880 parseChunk(context->context(), parseString); |
876 | 881 |
877 // JavaScript (which may be run under the parseChunk callstack) may | 882 // JavaScript (which may be run under the parseChunk callstack) may |
878 // cause the parser to be stopped or detached. | 883 // cause the parser to be stopped or detached. |
879 if (isStopped()) | 884 if (isStopped()) |
880 return; | 885 return; |
881 } | 886 } |
882 | 887 |
883 // FIXME: Why is this here? And why is it after we process the passed sourc
e? | 888 // FIXME: Why is this here? And why is it after we process the passed |
| 889 // source? |
884 if (document()->sawDecodingError()) { | 890 if (document()->sawDecodingError()) { |
885 // If the decoder saw an error, report it as fatal (stops parsing) | 891 // If the decoder saw an error, report it as fatal (stops parsing) |
886 TextPosition position(OrdinalNumber::fromOneBasedInt(context->context()-
>input->line), OrdinalNumber::fromOneBasedInt(context->context()->input->col)); | 892 TextPosition position(OrdinalNumber::fromOneBasedInt(context->context()-
>input->line), OrdinalNumber::fromOneBasedInt(context->context()->input->col)); |
887 handleError(XMLErrors::fatal, "Encoding error", position); | 893 handleError(XMLErrors::ErrorTypeFatal, "Encoding error", position); |
888 } | 894 } |
889 } | 895 } |
890 | 896 |
891 struct _xmlSAX2Namespace { | 897 struct xmlSAX2Namespace { |
892 const xmlChar* prefix; | 898 const xmlChar* prefix; |
893 const xmlChar* uri; | 899 const xmlChar* uri; |
894 }; | 900 }; |
895 typedef struct _xmlSAX2Namespace xmlSAX2Namespace; | |
896 | 901 |
897 static inline void handleNamespaceAttributes(Vector<Attribute>& prefixedAttribut
es, const xmlChar** libxmlNamespaces, int nbNamespaces, ExceptionState& exceptio
nState) | 902 static inline void handleNamespaceAttributes(Vector<Attribute>& prefixedAttribut
es, const xmlChar** libxmlNamespaces, int nbNamespaces, ExceptionState& exceptio
nState) |
898 { | 903 { |
899 xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNam
espaces); | 904 xmlSAX2Namespace* namespaces = reinterpret_cast<xmlSAX2Namespace*>(libxmlNam
espaces); |
900 for (int i = 0; i < nbNamespaces; i++) { | 905 for (int i = 0; i < nbNamespaces; ++i) { |
901 AtomicString namespaceQName = xmlnsAtom; | 906 AtomicString namespaceQName = xmlnsAtom; |
902 AtomicString namespaceURI = toAtomicString(namespaces[i].uri); | 907 AtomicString namespaceURI = toAtomicString(namespaces[i].uri); |
903 if (namespaces[i].prefix) | 908 if (namespaces[i].prefix) |
904 namespaceQName = "xmlns:" + toString(namespaces[i].prefix); | 909 namespaceQName = "xmlns:" + toString(namespaces[i].prefix); |
905 | 910 |
906 QualifiedName parsedName = anyName; | 911 QualifiedName parsedName = anyName; |
907 if (!Element::parseAttributeName(parsedName, XMLNSNames::xmlnsNamespaceU
RI, namespaceQName, exceptionState)) | 912 if (!Element::parseAttributeName(parsedName, XMLNSNames::xmlnsNamespaceU
RI, namespaceQName, exceptionState)) |
908 return; | 913 return; |
909 | 914 |
910 prefixedAttributes.append(Attribute(parsedName, namespaceURI)); | 915 prefixedAttributes.append(Attribute(parsedName, namespaceURI)); |
911 } | 916 } |
912 } | 917 } |
913 | 918 |
914 struct _xmlSAX2Attributes { | 919 struct xmlSAX2Attributes { |
915 const xmlChar* localname; | 920 const xmlChar* localname; |
916 const xmlChar* prefix; | 921 const xmlChar* prefix; |
917 const xmlChar* uri; | 922 const xmlChar* uri; |
918 const xmlChar* value; | 923 const xmlChar* value; |
919 const xmlChar* end; | 924 const xmlChar* end; |
920 }; | 925 }; |
921 typedef struct _xmlSAX2Attributes xmlSAX2Attributes; | |
922 | 926 |
923 static inline void handleElementAttributes(Vector<Attribute>& prefixedAttributes
, const xmlChar** libxmlAttributes, int nbAttributes, ExceptionState& exceptionS
tate) | 927 static inline void handleElementAttributes(Vector<Attribute>& prefixedAttributes
, const xmlChar** libxmlAttributes, int nbAttributes, ExceptionState& exceptionS
tate) |
924 { | 928 { |
925 xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlA
ttributes); | 929 xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlA
ttributes); |
926 for (int i = 0; i < nbAttributes; i++) { | 930 for (int i = 0; i < nbAttributes; ++i) { |
927 int valueLength = static_cast<int>(attributes[i].end - attributes[i].val
ue); | 931 int valueLength = static_cast<int>(attributes[i].end - attributes[i].val
ue); |
928 AtomicString attrValue = toAtomicString(attributes[i].value, valueLength
); | 932 AtomicString attrValue = toAtomicString(attributes[i].value, valueLength
); |
929 String attrPrefix = toString(attributes[i].prefix); | 933 String attrPrefix = toString(attributes[i].prefix); |
930 AtomicString attrURI = attrPrefix.isEmpty() ? AtomicString() : toAtomicS
tring(attributes[i].uri); | 934 AtomicString attrURI = attrPrefix.isEmpty() ? AtomicString() : toAtomicS
tring(attributes[i].uri); |
931 AtomicString attrQName = attrPrefix.isEmpty() ? toAtomicString(attribute
s[i].localname) : attrPrefix + ":" + toString(attributes[i].localname); | 935 AtomicString attrQName = attrPrefix.isEmpty() ? toAtomicString(attribute
s[i].localname) : attrPrefix + ":" + toString(attributes[i].localname); |
932 | 936 |
933 QualifiedName parsedName = anyName; | 937 QualifiedName parsedName = anyName; |
934 if (!Element::parseAttributeName(parsedName, attrURI, attrQName, excepti
onState)) | 938 if (!Element::parseAttributeName(parsedName, attrURI, attrQName, excepti
onState)) |
935 return; | 939 return; |
936 | 940 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 void XMLDocumentParser::endElementNs() | 1013 void XMLDocumentParser::endElementNs() |
1010 { | 1014 { |
1011 if (isStopped()) | 1015 if (isStopped()) |
1012 return; | 1016 return; |
1013 | 1017 |
1014 if (m_parserPaused) { | 1018 if (m_parserPaused) { |
1015 m_pendingCallbacks.append(adoptPtr(new PendingEndElementNSCallback())); | 1019 m_pendingCallbacks.append(adoptPtr(new PendingEndElementNSCallback())); |
1016 return; | 1020 return; |
1017 } | 1021 } |
1018 | 1022 |
1019 // JavaScript can detach the parser. Make sure this is not released | 1023 // JavaScript can detach the parser. Make sure this is not released before |
1020 // before the end of this method. | 1024 // the end of this method. |
1021 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); | 1025 RefPtrWillBeRawPtr<XMLDocumentParser> protect(this); |
1022 | 1026 |
1023 exitText(); | 1027 exitText(); |
1024 | 1028 |
1025 RefPtrWillBeRawPtr<ContainerNode> n = m_currentNode; | 1029 RefPtrWillBeRawPtr<ContainerNode> n = m_currentNode; |
1026 if (m_currentNode->isElementNode()) | 1030 if (m_currentNode->isElementNode()) |
1027 toElement(n.get())->finishParsingChildren(); | 1031 toElement(n.get())->finishParsingChildren(); |
1028 | 1032 |
1029 if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode()
&& toScriptLoaderIfPossible(toElement(n))) { | 1033 if (!scriptingContentIsAllowed(parserContentPolicy()) && n->isElementNode()
&& toScriptLoaderIfPossible(toElement(n))) { |
1030 popCurrentNode(); | 1034 popCurrentNode(); |
(...skipping 29 matching lines...) Expand all Loading... |
1060 // FIXME: Script execution should be shared between | 1064 // FIXME: Script execution should be shared between |
1061 // the libxml2 and Qt XMLDocumentParser implementations. | 1065 // the libxml2 and Qt XMLDocumentParser implementations. |
1062 | 1066 |
1063 if (scriptLoader->readyToBeParserExecuted()) { | 1067 if (scriptLoader->readyToBeParserExecuted()) { |
1064 scriptLoader->executeScript(ScriptSourceCode(scriptLoader->scriptCon
tent(), document()->url(), m_scriptStartPosition)); | 1068 scriptLoader->executeScript(ScriptSourceCode(scriptLoader->scriptCon
tent(), document()->url(), m_scriptStartPosition)); |
1065 } else if (scriptLoader->willBeParserExecuted()) { | 1069 } else if (scriptLoader->willBeParserExecuted()) { |
1066 m_pendingScript = scriptLoader->resource(); | 1070 m_pendingScript = scriptLoader->resource(); |
1067 m_scriptElement = element; | 1071 m_scriptElement = element; |
1068 m_pendingScript->addClient(this); | 1072 m_pendingScript->addClient(this); |
1069 | 1073 |
1070 // m_pendingScript will be 0 if script was already loaded and addCli
ent() executed it. | 1074 // m_pendingScript will be 0 if script was already loaded and |
| 1075 // addClient() executed it. |
1071 if (m_pendingScript) | 1076 if (m_pendingScript) |
1072 pauseParsing(); | 1077 pauseParsing(); |
1073 } else { | 1078 } else { |
1074 m_scriptElement = nullptr; | 1079 m_scriptElement = nullptr; |
1075 } | 1080 } |
1076 | 1081 |
1077 // JavaScript may have detached the parser | 1082 // JavaScript may have detached the parser |
1078 if (isDetached()) | 1083 if (isDetached()) |
1079 return; | 1084 return; |
1080 } | 1085 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 | 1117 |
1113 handleError(type, formattedMessage, textPosition()); | 1118 handleError(type, formattedMessage, textPosition()); |
1114 } | 1119 } |
1115 | 1120 |
1116 void XMLDocumentParser::processingInstruction(const String& target, const String
& data) | 1121 void XMLDocumentParser::processingInstruction(const String& target, const String
& data) |
1117 { | 1122 { |
1118 if (isStopped()) | 1123 if (isStopped()) |
1119 return; | 1124 return; |
1120 | 1125 |
1121 if (m_parserPaused) { | 1126 if (m_parserPaused) { |
1122 m_pendingCallbacks.append(adoptPtr(new PendingProcessingInstructionCallb
ack(target ,data))); | 1127 m_pendingCallbacks.append(adoptPtr(new PendingProcessingInstructionCallb
ack(target, data))); |
1123 return; | 1128 return; |
1124 } | 1129 } |
1125 | 1130 |
1126 exitText(); | 1131 exitText(); |
1127 | 1132 |
1128 // ### handle exceptions | 1133 // ### handle exceptions |
1129 TrackExceptionState exceptionState; | 1134 TrackExceptionState exceptionState; |
1130 RefPtrWillBeRawPtr<ProcessingInstruction> pi = m_currentNode->document().cre
ateProcessingInstruction(target, data, exceptionState); | 1135 RefPtrWillBeRawPtr<ProcessingInstruction> pi = m_currentNode->document().cre
ateProcessingInstruction(target, data, exceptionState); |
1131 if (exceptionState.hadException()) | 1136 if (exceptionState.hadException()) |
1132 return; | 1137 return; |
1133 | 1138 |
1134 pi->setCreatedByParser(true); | 1139 pi->setCreatedByParser(true); |
1135 | 1140 |
1136 m_currentNode->parserAppendChild(pi.get()); | 1141 m_currentNode->parserAppendChild(pi.get()); |
1137 | 1142 |
1138 pi->setCreatedByParser(false); | 1143 pi->setCreatedByParser(false); |
1139 | 1144 |
1140 if (pi->isCSS()) | 1145 if (pi->isCSS()) |
1141 m_sawCSS = true; | 1146 m_sawCSS = true; |
1142 | 1147 |
1143 if (!RuntimeEnabledFeatures::xsltEnabled()) | 1148 if (!RuntimeEnabledFeatures::xsltEnabled()) |
1144 return; | 1149 return; |
1145 | 1150 |
1146 m_sawXSLTransform = !m_sawFirstElement && pi->isXSL(); | 1151 m_sawXSLTransform = !m_sawFirstElement && pi->isXSL(); |
1147 if (m_sawXSLTransform && !document()->transformSourceDocument()) { | 1152 if (m_sawXSLTransform && !document()->transformSourceDocument()) { |
1148 // This behavior is very tricky. We call stopParsing() here because we w
ant to stop processing the document | 1153 // This behavior is very tricky. We call stopParsing() here because we |
1149 // until we're ready to apply the transform, but we actually still want
to be fed decoded string pieces to | 1154 // want to stop processing the document until we're ready to apply the |
1150 // accumulate in m_originalSourceForTransform. So, we call stopParsing()
here and | 1155 // transform, but we actually still want to be fed decoded string pieces |
1151 // check isStopped() in element callbacks. | 1156 // to accumulate in m_originalSourceForTransform. So, we call |
| 1157 // stopParsing() here and check isStopped() in element callbacks. |
1152 // FIXME: This contradicts the contract of DocumentParser. | 1158 // FIXME: This contradicts the contract of DocumentParser. |
1153 stopParsing(); | 1159 stopParsing(); |
1154 } | 1160 } |
1155 } | 1161 } |
1156 | 1162 |
1157 void XMLDocumentParser::cdataBlock(const String& text) | 1163 void XMLDocumentParser::cdataBlock(const String& text) |
1158 { | 1164 { |
1159 if (isStopped()) | 1165 if (isStopped()) |
1160 return; | 1166 return; |
1161 | 1167 |
(...skipping 24 matching lines...) Expand all Loading... |
1186 | 1192 |
1187 enum StandaloneInfo { | 1193 enum StandaloneInfo { |
1188 StandaloneUnspecified = -2, | 1194 StandaloneUnspecified = -2, |
1189 NoXMlDeclaration, | 1195 NoXMlDeclaration, |
1190 StandaloneNo, | 1196 StandaloneNo, |
1191 StandaloneYes | 1197 StandaloneYes |
1192 }; | 1198 }; |
1193 | 1199 |
1194 void XMLDocumentParser::startDocument(const String& version, const String& encod
ing, int standalone) | 1200 void XMLDocumentParser::startDocument(const String& version, const String& encod
ing, int standalone) |
1195 { | 1201 { |
1196 StandaloneInfo standaloneInfo = (StandaloneInfo)standalone; | 1202 StandaloneInfo standaloneInfo = static_cast<StandaloneInfo>(standalone); |
1197 if (standaloneInfo == NoXMlDeclaration) { | 1203 if (standaloneInfo == NoXMlDeclaration) { |
1198 document()->setHasXMLDeclaration(false); | 1204 document()->setHasXMLDeclaration(false); |
1199 return; | 1205 return; |
1200 } | 1206 } |
1201 | 1207 |
1202 if (!version.isNull()) | 1208 if (!version.isNull()) |
1203 document()->setXMLVersion(version, ASSERT_NO_EXCEPTION); | 1209 document()->setXMLVersion(version, ASSERT_NO_EXCEPTION); |
1204 if (standalone != StandaloneUnspecified) | 1210 if (standalone != StandaloneUnspecified) |
1205 document()->setXMLStandalone(standaloneInfo == StandaloneYes, ASSERT_NO_
EXCEPTION); | 1211 document()->setXMLStandalone(standaloneInfo == StandaloneYes, ASSERT_NO_
EXCEPTION); |
1206 if (!encoding.isNull()) | 1212 if (!encoding.isNull()) |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1261 static void commentHandler(void* closure, const xmlChar* text) | 1267 static void commentHandler(void* closure, const xmlChar* text) |
1262 { | 1268 { |
1263 getParser(closure)->comment(toString(text)); | 1269 getParser(closure)->comment(toString(text)); |
1264 } | 1270 } |
1265 | 1271 |
1266 WTF_ATTRIBUTE_PRINTF(2, 3) | 1272 WTF_ATTRIBUTE_PRINTF(2, 3) |
1267 static void warningHandler(void* closure, const char* message, ...) | 1273 static void warningHandler(void* closure, const char* message, ...) |
1268 { | 1274 { |
1269 va_list args; | 1275 va_list args; |
1270 va_start(args, message); | 1276 va_start(args, message); |
1271 getParser(closure)->error(XMLErrors::warning, message, args); | 1277 getParser(closure)->error(XMLErrors::ErrorTypeWarning, message, args); |
1272 va_end(args); | 1278 va_end(args); |
1273 } | 1279 } |
1274 | 1280 |
1275 WTF_ATTRIBUTE_PRINTF(2, 3) | 1281 WTF_ATTRIBUTE_PRINTF(2, 3) |
1276 static void fatalErrorHandler(void* closure, const char* message, ...) | 1282 static void fatalErrorHandler(void* closure, const char* message, ...) |
1277 { | 1283 { |
1278 va_list args; | 1284 va_list args; |
1279 va_start(args, message); | 1285 va_start(args, message); |
1280 getParser(closure)->error(XMLErrors::fatal, message, args); | 1286 getParser(closure)->error(XMLErrors::ErrorTypeFatal, message, args); |
1281 va_end(args); | 1287 va_end(args); |
1282 } | 1288 } |
1283 | 1289 |
1284 WTF_ATTRIBUTE_PRINTF(2, 3) | 1290 WTF_ATTRIBUTE_PRINTF(2, 3) |
1285 static void normalErrorHandler(void* closure, const char* message, ...) | 1291 static void normalErrorHandler(void* closure, const char* message, ...) |
1286 { | 1292 { |
1287 va_list args; | 1293 va_list args; |
1288 va_start(args, message); | 1294 va_start(args, message); |
1289 getParser(closure)->error(XMLErrors::nonFatal, message, args); | 1295 getParser(closure)->error(XMLErrors::ErrorTypeNonFatal, message, args); |
1290 va_end(args); | 1296 va_end(args); |
1291 } | 1297 } |
1292 | 1298 |
1293 // Using a static entity and marking it XML_INTERNAL_PREDEFINED_ENTITY is | 1299 // Using a static entity and marking it XML_INTERNAL_PREDEFINED_ENTITY is a hack |
1294 // a hack to avoid malloc/free. Using a global variable like this could cause tr
ouble | 1300 // to avoid malloc/free. Using a global variable like this could cause trouble |
1295 // if libxml implementation details were to change | 1301 // if libxml implementation details were to change |
1296 static xmlChar sharedXHTMLEntityResult[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; | 1302 static xmlChar sharedXHTMLEntityResult[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; |
1297 | 1303 |
1298 static xmlEntityPtr sharedXHTMLEntity() | 1304 static xmlEntityPtr sharedXHTMLEntity() |
1299 { | 1305 { |
1300 static xmlEntity entity; | 1306 static xmlEntity entity; |
1301 if (!entity.type) { | 1307 if (!entity.type) { |
1302 entity.type = XML_ENTITY_DECL; | 1308 entity.type = XML_ENTITY_DECL; |
1303 entity.orig = sharedXHTMLEntityResult; | 1309 entity.orig = sharedXHTMLEntityResult; |
1304 entity.content = sharedXHTMLEntityResult; | 1310 entity.content = sharedXHTMLEntityResult; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1376 | 1382 |
1377 static void internalSubsetHandler(void* closure, const xmlChar* name, const xmlC
har* externalID, const xmlChar* systemID) | 1383 static void internalSubsetHandler(void* closure, const xmlChar* name, const xmlC
har* externalID, const xmlChar* systemID) |
1378 { | 1384 { |
1379 getParser(closure)->internalSubset(toString(name), toString(externalID), toS
tring(systemID)); | 1385 getParser(closure)->internalSubset(toString(name), toString(externalID), toS
tring(systemID)); |
1380 xmlSAX2InternalSubset(closure, name, externalID, systemID); | 1386 xmlSAX2InternalSubset(closure, name, externalID, systemID); |
1381 } | 1387 } |
1382 | 1388 |
1383 static void externalSubsetHandler(void* closure, const xmlChar*, const xmlChar*
externalId, const xmlChar*) | 1389 static void externalSubsetHandler(void* closure, const xmlChar*, const xmlChar*
externalId, const xmlChar*) |
1384 { | 1390 { |
1385 String extId = toString(externalId); | 1391 String extId = toString(externalId); |
1386 if ((extId == "-//W3C//DTD XHTML 1.0 Transitional//EN") | 1392 if (extId == "-//W3C//DTD XHTML 1.0 Transitional//EN" |
1387 || (extId == "-//W3C//DTD XHTML 1.1//EN") | 1393 || extId == "-//W3C//DTD XHTML 1.1//EN" |
1388 || (extId == "-//W3C//DTD XHTML 1.0 Strict//EN") | 1394 || extId == "-//W3C//DTD XHTML 1.0 Strict//EN" |
1389 || (extId == "-//W3C//DTD XHTML 1.0 Frameset//EN") | 1395 || extId == "-//W3C//DTD XHTML 1.0 Frameset//EN" |
1390 || (extId == "-//W3C//DTD XHTML Basic 1.0//EN") | 1396 || extId == "-//W3C//DTD XHTML Basic 1.0//EN" |
1391 || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN") | 1397 || extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" |
1392 || (extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN") | 1398 || extId == "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" |
1393 || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.0//EN") | 1399 || extId == "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" |
1394 || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.1//EN") | 1400 || extId == "-//WAPFORUM//DTD XHTML Mobile 1.1//EN" |
1395 || (extId == "-//WAPFORUM//DTD XHTML Mobile 1.2//EN")) | 1401 || extId == "-//WAPFORUM//DTD XHTML Mobile 1.2//EN") { |
1396 getParser(closure)->setIsXHTMLDocument(true); // controls if we replace
entities or not. | 1402 // Controls if we replace entities or not. |
| 1403 getParser(closure)->setIsXHTMLDocument(true); |
| 1404 } |
1397 } | 1405 } |
1398 | 1406 |
1399 static void ignorableWhitespaceHandler(void*, const xmlChar*, int) | 1407 static void ignorableWhitespaceHandler(void*, const xmlChar*, int) |
1400 { | 1408 { |
1401 // nothing to do, but we need this to work around a crasher | 1409 // Nothing to do, but we need this to work around a crasher. |
1402 // http://bugzilla.gnome.org/show_bug.cgi?id=172255 | 1410 // http://bugzilla.gnome.org/show_bug.cgi?id=172255 |
1403 // http://bugs.webkit.org/show_bug.cgi?id=5792 | 1411 // http://bugs.webkit.org/show_bug.cgi?id=5792 |
1404 } | 1412 } |
1405 | 1413 |
1406 void XMLDocumentParser::initializeParserContext(const CString& chunk) | 1414 void XMLDocumentParser::initializeParserContext(const CString& chunk) |
1407 { | 1415 { |
1408 xmlSAXHandler sax; | 1416 xmlSAXHandler sax; |
1409 memset(&sax, 0, sizeof(sax)); | 1417 memset(&sax, 0, sizeof(sax)); |
1410 | 1418 |
1411 sax.error = normalErrorHandler; | 1419 sax.error = normalErrorHandler; |
(...skipping 13 matching lines...) Expand all Loading... |
1425 sax.ignorableWhitespace = ignorableWhitespaceHandler; | 1433 sax.ignorableWhitespace = ignorableWhitespaceHandler; |
1426 sax.entityDecl = xmlSAX2EntityDecl; | 1434 sax.entityDecl = xmlSAX2EntityDecl; |
1427 sax.initialized = XML_SAX2_MAGIC; | 1435 sax.initialized = XML_SAX2_MAGIC; |
1428 DocumentParser::startParsing(); | 1436 DocumentParser::startParsing(); |
1429 m_sawError = false; | 1437 m_sawError = false; |
1430 m_sawCSS = false; | 1438 m_sawCSS = false; |
1431 m_sawXSLTransform = false; | 1439 m_sawXSLTransform = false; |
1432 m_sawFirstElement = false; | 1440 m_sawFirstElement = false; |
1433 | 1441 |
1434 XMLDocumentParserScope scope(document()->fetcher()); | 1442 XMLDocumentParserScope scope(document()->fetcher()); |
1435 if (m_parsingFragment) | 1443 if (m_parsingFragment) { |
1436 m_context = XMLParserContext::createMemoryParser(&sax, this, chunk); | 1444 m_context = XMLParserContext::createMemoryParser(&sax, this, chunk); |
1437 else { | 1445 } else { |
1438 ASSERT(!chunk.data()); | 1446 ASSERT(!chunk.data()); |
1439 m_context = XMLParserContext::createStringParser(&sax, this); | 1447 m_context = XMLParserContext::createStringParser(&sax, this); |
1440 } | 1448 } |
1441 } | 1449 } |
1442 | 1450 |
1443 void XMLDocumentParser::doEnd() | 1451 void XMLDocumentParser::doEnd() |
1444 { | 1452 { |
1445 if (!isStopped()) { | 1453 if (!isStopped()) { |
1446 if (m_context) { | 1454 if (m_context) { |
1447 // Tell libxml we're done. | 1455 // Tell libxml we're done. |
1448 { | 1456 { |
1449 XMLDocumentParserScope scope(document()->fetcher()); | 1457 XMLDocumentParserScope scope(document()->fetcher()); |
1450 finishParsing(context()); | 1458 finishParsing(context()); |
1451 } | 1459 } |
1452 | 1460 |
1453 m_context = nullptr; | 1461 m_context = nullptr; |
1454 } | 1462 } |
1455 } | 1463 } |
1456 | 1464 |
1457 bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && hasNo
StyleInformation(document()); | 1465 bool xmlViewerMode = !m_sawError && !m_sawCSS && !m_sawXSLTransform && hasNo
StyleInformation(document()); |
1458 if (xmlViewerMode) { | 1466 if (xmlViewerMode) { |
1459 XMLTreeViewer xmlTreeViewer(document()); | 1467 XMLTreeViewer xmlTreeViewer(document()); |
1460 xmlTreeViewer.transformDocumentToTreeView(); | 1468 xmlTreeViewer.transformDocumentToTreeView(); |
1461 } else if (m_sawXSLTransform) { | 1469 } else if (m_sawXSLTransform) { |
1462 xmlDocPtr doc = xmlDocPtrForString(document()->fetcher(), m_originalSour
ceForTransform.toString(), document()->url().string()); | 1470 xmlDocPtr doc = xmlDocPtrForString(document()->fetcher(), m_originalSour
ceForTransform.toString(), document()->url().string()); |
1463 document()->setTransformSource(adoptPtr(new TransformSource(doc))); | 1471 document()->setTransformSource(adoptPtr(new TransformSource(doc))); |
1464 | 1472 // Make the document think it's done, so it will apply XSL stylesheets. |
1465 document()->setParsing(false); // Make the document think it's done, so
it will apply XSL stylesheets. | 1473 document()->setParsing(false); |
1466 document()->styleResolverChanged(); | 1474 document()->styleResolverChanged(); |
1467 | 1475 |
1468 // styleResolverChanged() call can detach the parser and null out its do
cument. | 1476 // styleResolverChanged() call can detach the parser and null out its |
1469 // In that case, we just bail out. | 1477 // document. In that case, we just bail out. |
1470 if (isDetached()) | 1478 if (isDetached()) |
1471 return; | 1479 return; |
1472 | 1480 |
1473 document()->setParsing(true); | 1481 document()->setParsing(true); |
1474 DocumentParser::stopParsing(); | 1482 DocumentParser::stopParsing(); |
1475 } | 1483 } |
1476 } | 1484 } |
1477 | 1485 |
1478 xmlDocPtr xmlDocPtrForString(ResourceFetcher* fetcher, const String& source, con
st String& url) | 1486 xmlDocPtr xmlDocPtrForString(ResourceFetcher* fetcher, const String& source, con
st String& url) |
1479 { | 1487 { |
1480 if (source.isEmpty()) | 1488 if (source.isEmpty()) |
1481 return 0; | 1489 return 0; |
1482 // Parse in a single chunk into an xmlDocPtr | 1490 // Parse in a single chunk into an xmlDocPtr |
1483 // FIXME: Hook up error handlers so that a failure to parse the main documen
t results in | 1491 // FIXME: Hook up error handlers so that a failure to parse the main |
1484 // good error messages. | 1492 // document results in good error messages. |
1485 XMLDocumentParserScope scope(fetcher, errorFunc, 0); | 1493 XMLDocumentParserScope scope(fetcher, errorFunc, 0); |
1486 XMLParserInput input(source); | 1494 XMLParserInput input(source); |
1487 return xmlReadMemory(input.data(), input.size(), url.latin1().data(), input.
encoding(), XSLT_PARSE_OPTIONS); | 1495 return xmlReadMemory(input.data(), input.size(), url.latin1().data(), input.
encoding(), XSLT_PARSE_OPTIONS); |
1488 } | 1496 } |
1489 | 1497 |
1490 OrdinalNumber XMLDocumentParser::lineNumber() const | 1498 OrdinalNumber XMLDocumentParser::lineNumber() const |
1491 { | 1499 { |
1492 return OrdinalNumber::fromOneBasedInt(context() ? context()->input->line : 1
); | 1500 return OrdinalNumber::fromOneBasedInt(context() ? context()->input->line : 1
); |
1493 } | 1501 } |
1494 | 1502 |
1495 OrdinalNumber XMLDocumentParser::columnNumber() const | 1503 OrdinalNumber XMLDocumentParser::columnNumber() const |
1496 { | 1504 { |
1497 return OrdinalNumber::fromOneBasedInt(context() ? context()->input->col : 1)
; | 1505 return OrdinalNumber::fromOneBasedInt(context() ? context()->input->col : 1)
; |
1498 } | 1506 } |
1499 | 1507 |
1500 TextPosition XMLDocumentParser::textPosition() const | 1508 TextPosition XMLDocumentParser::textPosition() const |
1501 { | 1509 { |
1502 xmlParserCtxtPtr context = this->context(); | 1510 xmlParserCtxtPtr context = this->context(); |
1503 if (!context) | 1511 if (!context) |
1504 return TextPosition::minimumPosition(); | 1512 return TextPosition::minimumPosition(); |
1505 return TextPosition(OrdinalNumber::fromOneBasedInt(context->input->line), | 1513 return TextPosition(OrdinalNumber::fromOneBasedInt(context->input->line), Or
dinalNumber::fromOneBasedInt(context->input->col)); |
1506 OrdinalNumber::fromOneBasedInt(context->input->col)); | |
1507 } | 1514 } |
1508 | 1515 |
1509 void XMLDocumentParser::stopParsing() | 1516 void XMLDocumentParser::stopParsing() |
1510 { | 1517 { |
1511 DocumentParser::stopParsing(); | 1518 DocumentParser::stopParsing(); |
1512 if (context()) | 1519 if (context()) |
1513 xmlStopParser(context()); | 1520 xmlStopParser(context()); |
1514 } | 1521 } |
1515 | 1522 |
1516 void XMLDocumentParser::resumeParsing() | 1523 void XMLDocumentParser::resumeParsing() |
(...skipping 27 matching lines...) Expand all Loading... |
1544 end(); | 1551 end(); |
1545 } | 1552 } |
1546 | 1553 |
1547 bool XMLDocumentParser::appendFragmentSource(const String& chunk) | 1554 bool XMLDocumentParser::appendFragmentSource(const String& chunk) |
1548 { | 1555 { |
1549 ASSERT(!m_context); | 1556 ASSERT(!m_context); |
1550 ASSERT(m_parsingFragment); | 1557 ASSERT(m_parsingFragment); |
1551 | 1558 |
1552 CString chunkAsUtf8 = chunk.utf8(); | 1559 CString chunkAsUtf8 = chunk.utf8(); |
1553 | 1560 |
1554 // libxml2 takes an int for a length, and therefore can't handle XML chunks
larger than 2 GiB. | 1561 // libxml2 takes an int for a length, and therefore can't handle XML chunks |
| 1562 // larger than 2 GiB. |
1555 if (chunkAsUtf8.length() > INT_MAX) | 1563 if (chunkAsUtf8.length() > INT_MAX) |
1556 return false; | 1564 return false; |
1557 | 1565 |
1558 initializeParserContext(chunkAsUtf8); | 1566 initializeParserContext(chunkAsUtf8); |
1559 xmlParseContent(context()); | 1567 xmlParseContent(context()); |
1560 endDocument(); // Close any open text nodes. | 1568 endDocument(); // Close any open text nodes. |
1561 | 1569 |
1562 // FIXME: If this code is actually needed, it should probably move to finish
() | 1570 // FIXME: If this code is actually needed, it should probably move to |
1563 // XMLDocumentParserQt has a similar check (m_stream.error() == QXmlStreamRe
ader::PrematureEndOfDocumentError) in doEnd(). | 1571 // finish() |
1564 // Check if all the chunk has been processed. | 1572 // XMLDocumentParserQt has a similar check (m_stream.error() == |
| 1573 // QXmlStreamReader::PrematureEndOfDocumentError) in doEnd(). Check if all |
| 1574 // the chunk has been processed. |
1565 long bytesProcessed = xmlByteConsumed(context()); | 1575 long bytesProcessed = xmlByteConsumed(context()); |
1566 if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.l
ength()) { | 1576 if (bytesProcessed == -1 || static_cast<unsigned long>(bytesProcessed) != ch
unkAsUtf8.length()) { |
1567 // FIXME: I don't believe we can hit this case without also having seen
an error or a null byte. | 1577 // FIXME: I don't believe we can hit this case without also having seen |
1568 // If we hit this ASSERT, we've found a test case which demonstrates the
need for this code. | 1578 // an error or a null byte. If we hit this ASSERT, we've found a test |
| 1579 // case which demonstrates the need for this code. |
1569 ASSERT(m_sawError || (bytesProcessed >= 0 && !chunkAsUtf8.data()[bytesPr
ocessed])); | 1580 ASSERT(m_sawError || (bytesProcessed >= 0 && !chunkAsUtf8.data()[bytesPr
ocessed])); |
1570 return false; | 1581 return false; |
1571 } | 1582 } |
1572 | 1583 |
1573 // No error if the chunk is well formed or it is not but we have no error. | 1584 // No error if the chunk is well formed or it is not but we have no error. |
1574 return context()->wellFormed || !xmlCtxtGetLastError(context()); | 1585 return context()->wellFormed || !xmlCtxtGetLastError(context()); |
1575 } | 1586 } |
1576 | 1587 |
1577 // -------------------------------- | 1588 // -------------------------------- |
1578 | 1589 |
1579 struct AttributeParseState { | 1590 struct AttributeParseState { |
1580 HashMap<String, String> attributes; | 1591 HashMap<String, String> attributes; |
1581 bool gotAttributes; | 1592 bool gotAttributes; |
1582 }; | 1593 }; |
1583 | 1594 |
1584 static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLoc
alName, const xmlChar* /*xmlPrefix*/, | 1595 static void attributesStartElementNsHandler(void* closure, const xmlChar* xmlLoc
alName, const xmlChar* /*xmlPrefix*/, |
1585 const xmlChar* /*xmlURI*/, int /*nbNamespaces*/, const xmlChar** /*namespace
s*/, | 1596 const xmlChar* /*xmlURI*/, int /*nbNamespaces*/, const xmlChar** /*namespace
s*/, |
1586 int nbAttributes, int /*nbDefaulted*/, const xmlChar** libxmlAttributes) | 1597 int nbAttributes, int /*nbDefaulted*/, const xmlChar** libxmlAttributes) |
1587 { | 1598 { |
1588 if (strcmp(reinterpret_cast<const char*>(xmlLocalName), "attrs") != 0) | 1599 if (strcmp(reinterpret_cast<const char*>(xmlLocalName), "attrs") != 0) |
1589 return; | 1600 return; |
1590 | 1601 |
1591 xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure); | 1602 xmlParserCtxtPtr ctxt = static_cast<xmlParserCtxtPtr>(closure); |
1592 AttributeParseState* state = static_cast<AttributeParseState*>(ctxt->_privat
e); | 1603 AttributeParseState* state = static_cast<AttributeParseState*>(ctxt->_privat
e); |
1593 | 1604 |
1594 state->gotAttributes = true; | 1605 state->gotAttributes = true; |
1595 | 1606 |
1596 xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlA
ttributes); | 1607 xmlSAX2Attributes* attributes = reinterpret_cast<xmlSAX2Attributes*>(libxmlA
ttributes); |
1597 for (int i = 0; i < nbAttributes; i++) { | 1608 for (int i = 0; i < nbAttributes; ++i) { |
1598 String attrLocalName = toString(attributes[i].localname); | 1609 String attrLocalName = toString(attributes[i].localname); |
1599 int valueLength = (int) (attributes[i].end - attributes[i].value); | 1610 int valueLength = (int) (attributes[i].end - attributes[i].value); |
1600 String attrValue = toString(attributes[i].value, valueLength); | 1611 String attrValue = toString(attributes[i].value, valueLength); |
1601 String attrPrefix = toString(attributes[i].prefix); | 1612 String attrPrefix = toString(attributes[i].prefix); |
1602 String attrQName = attrPrefix.isEmpty() ? attrLocalName : attrPrefix + "
:" + attrLocalName; | 1613 String attrQName = attrPrefix.isEmpty() ? attrLocalName : attrPrefix + "
:" + attrLocalName; |
1603 | 1614 |
1604 state->attributes.set(attrQName, attrValue); | 1615 state->attributes.set(attrQName, attrValue); |
1605 } | 1616 } |
1606 } | 1617 } |
1607 | 1618 |
1608 HashMap<String, String> parseAttributes(const String& string, bool& attrsOK) | 1619 HashMap<String, String> parseAttributes(const String& string, bool& attrsOK) |
1609 { | 1620 { |
1610 AttributeParseState state; | 1621 AttributeParseState state; |
1611 state.gotAttributes = false; | 1622 state.gotAttributes = false; |
1612 | 1623 |
1613 xmlSAXHandler sax; | 1624 xmlSAXHandler sax; |
1614 memset(&sax, 0, sizeof(sax)); | 1625 memset(&sax, 0, sizeof(sax)); |
1615 sax.startElementNs = attributesStartElementNsHandler; | 1626 sax.startElementNs = attributesStartElementNsHandler; |
1616 sax.initialized = XML_SAX2_MAGIC; | 1627 sax.initialized = XML_SAX2_MAGIC; |
1617 RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax,
&state); | 1628 RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax,
&state); |
1618 String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; | 1629 String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; |
1619 parseChunk(parser->context(), parseString); | 1630 parseChunk(parser->context(), parseString); |
1620 finishParsing(parser->context()); | 1631 finishParsing(parser->context()); |
1621 attrsOK = state.gotAttributes; | 1632 attrsOK = state.gotAttributes; |
1622 return state.attributes; | 1633 return state.attributes; |
1623 } | 1634 } |
1624 | 1635 |
1625 } // namespace WebCore | 1636 } // namespace WebCore |
OLD | NEW |