Changeset 31860 in webkit


Ignore:
Timestamp:
Apr 14, 2008 4:50:21 AM (16 years ago)
Author:
jchaffraix@webkit.org
Message:

2008-04-14 Julien Chaffraix <jchaffraix@webkit.org>

Reviewed by Ap.

Bug 17403: WebKit Creates Invalid Xhtml Links with Ajax
http://bugs.webkit.org/show_bug.cgi?id=17403

The previous code had callbacks for the normal parsing (full document) and fragment parsing.
The difference was induced by the method we were using which did not accept a xmlParserCtxt.
The code has been refactored to allow us to share the callbacks between the different cases.
A drawback is that we have to use xmlParseContent which is an internal libxml method and thus
some internal intialization is done in WebCore.

Test: fast/parser/ampersand-escaped-parseXMLFragment.xhtml

  • dom/XMLTokenizer.cpp: (WebCore::createStringParser): Moved didInit in the global scope as it is shared by the 2 create methods.

(WebCore::createMemoryParser): Create a memory parser similar to the previous code.
Initialize the xmlParserContext to call xmlParseContent in parseXMLDocumentFragment.

(WebCore::XMLTokenizer::initializeParserContext): Check m_parsingFragment to know
which create method to call.

  • dom/XMLTokenizer.h: Added parseXMLDocumentFragment as a friend of XMLTokenizer.

2008-04-14 Julien Chaffraix <jchaffraix@webkit.org>

Reviewed by Ap.

Layout test for http://bugs.webkit.org/show_bug.cgi?id=17403:
WebKit Creates Invalid Xhtml Links with Ajax

  • fast/parser/ampersand-escaped-parseXMLFragment-expected.txt: Added.
  • fast/parser/ampersand-escaped-parseXMLFragment.xhtml: Added.
Location:
trunk
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r31859 r31860  
     12008-04-14  Julien Chaffraix  <jchaffraix@webkit.org>
     2
     3        Reviewed by Ap.
     4
     5        Layout test for http://bugs.webkit.org/show_bug.cgi?id=17403:
     6        WebKit Creates Invalid Xhtml Links with Ajax
     7
     8        * fast/parser/ampersand-escaped-parseXMLFragment-expected.txt: Added.
     9        * fast/parser/ampersand-escaped-parseXMLFragment.xhtml: Added.
     10
    1112008-04-14  Rob Buis  <buis@kde.org>
    212
  • trunk/WebCore/ChangeLog

    r31859 r31860  
     12008-04-14  Julien Chaffraix  <jchaffraix@webkit.org>
     2
     3        Reviewed by Ap.
     4
     5        Bug 17403: WebKit Creates Invalid Xhtml Links with Ajax
     6        http://bugs.webkit.org/show_bug.cgi?id=17403
     7
     8        The previous code had callbacks for the normal parsing (full document) and fragment parsing.
     9        The difference was induced by the method we were using which did not accept a xmlParserCtxt.
     10        The code has been refactored to allow us to share the callbacks between the different cases.
     11        A drawback is that we have to use xmlParseContent which is an internal libxml method and thus
     12        some internal intialization is done in WebCore.
     13
     14        Test: fast/parser/ampersand-escaped-parseXMLFragment.xhtml
     15
     16        * dom/XMLTokenizer.cpp:
     17        (WebCore::createStringParser): Moved didInit in the global scope as it is shared by the
     18        2 create methods.
     19
     20        (WebCore::createMemoryParser): Create a memory parser similar to the previous code.
     21        Initialize the xmlParserContext to call xmlParseContent in parseXMLDocumentFragment.
     22
     23        (WebCore::XMLTokenizer::initializeParserContext): Check m_parsingFragment to know
     24        which create method to call.
     25
     26        * dom/XMLTokenizer.h: Added parseXMLDocumentFragment as a friend of XMLTokenizer.
     27
    1282008-04-14  Rob Buis  <buis@kde.org>
    229
  • trunk/WebCore/dom/XMLTokenizer.cpp

    r31848 r31860  
    438438}
    439439
     440static bool didInit = false;
     441
    440442static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* userData)
    441443{
    442     static bool didInit = false;
    443444    if (!didInit) {
    444445        xmlInitParser();
     
    455456    const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
    456457    xmlSwitchEncoding(parser, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
     458
     459    return parser;
     460}
     461
     462
     463// Chunk should be encoded in UTF-8
     464static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk)
     465{
     466    if (!didInit) {
     467        xmlInitParser();
     468        xmlRegisterInputCallbacks(matchFunc, openFunc, readFunc, closeFunc);
     469        xmlRegisterOutputCallbacks(matchFunc, openFunc, writeFunc, closeFunc);
     470        libxmlLoaderThread = currentThread();
     471        didInit = true;
     472    }
     473
     474    xmlParserCtxtPtr parser = xmlCreateMemoryParserCtxt(chunk, xmlStrlen((const xmlChar*)chunk));
     475
     476    if (!parser)
     477        return 0;
     478
     479    // Copy the sax handler
     480    memcpy(parser->sax, handlers, sizeof(xmlSAXHandler));
     481
     482    // Set parser options.
     483    // XML_PARSE_NODICT: default dictionary option.
     484    // XML_PARSE_NOENT: force entities substitutions.
     485    xmlCtxtUseOptions(parser, XML_PARSE_NODICT | XML_PARSE_NOENT);
     486
     487    // Internal initialization
     488    parser->sax2 = 1;
     489    parser->instate = XML_PARSER_CONTENT; // We are parsing a CONTENT
     490    parser->depth = 0;
     491    parser->str_xml = xmlDictLookup(parser->dict, BAD_CAST "xml", 3);
     492    parser->str_xmlns = xmlDictLookup(parser->dict, BAD_CAST "xmlns", 5);
     493    parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36);
     494    parser->_private = userData;
     495
    457496    return parser;
    458497}
     
    595634#if defined(USE_QXMLSTREAM) && QT_VERSION >= 0x040400
    596635    delete m_stream.entityResolver();
     636#endif
     637#ifndef USE_QXMLSTREAM
     638    if (m_context)
     639        xmlFreeParserCtxt(m_context);
    597640#endif
    598641}
     
    12581301}
    12591302
    1260 void XMLTokenizer::initializeParserContext()
     1303void XMLTokenizer::initializeParserContext(const char* chunk)
    12611304{
    12621305#ifndef USE_QXMLSTREAM
    12631306    xmlSAXHandler sax;
    12641307    memset(&sax, 0, sizeof(sax));
     1308
    12651309    sax.error = normalErrorHandler;
    12661310    sax.fatalError = fatalErrorHandler;
     
    12851329    m_sawXSLTransform = false;
    12861330    m_sawFirstElement = false;
    1287    
     1331
    12881332#ifndef USE_QXMLSTREAM
    1289     m_context = createStringParser(&sax, this);
     1333    if (m_parsingFragment)
     1334        m_context = createMemoryParser(&sax, this, chunk);
     1335    else
     1336        m_context = createStringParser(&sax, this);
    12901337#endif
    12911338}
     
    15451592}
    15461593
     1594bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, Element* parent)
     1595{
     1596    if (!chunk.length())
     1597        return true;
     1598
     1599    XMLTokenizer tokenizer(fragment, parent);
     1600   
    15471601#ifndef USE_QXMLSTREAM
    1548 static void balancedStartElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix,
    1549                                           const xmlChar* uri, int nb_namespaces, const xmlChar** namespaces,
    1550                                           int nb_attributes, int nb_defaulted, const xmlChar** libxmlAttributes)
    1551 {
    1552    static_cast<XMLTokenizer*>(closure)->startElementNs(localname, prefix, uri, nb_namespaces, namespaces, nb_attributes, nb_defaulted, libxmlAttributes);
    1553 }
    1554 
    1555 static void balancedEndElementNsHandler(void* closure, const xmlChar* localname, const xmlChar* prefix, const xmlChar* uri)
    1556 {
    1557     static_cast<XMLTokenizer*>(closure)->endElementNs();
    1558 }
    1559 
    1560 static void balancedCharactersHandler(void* closure, const xmlChar* s, int len)
    1561 {
    1562     static_cast<XMLTokenizer*>(closure)->characters(s, len);
    1563 }
    1564 
    1565 static void balancedProcessingInstructionHandler(void* closure, const xmlChar* target, const xmlChar* data)
    1566 {
    1567     static_cast<XMLTokenizer*>(closure)->processingInstruction(target, data);
    1568 }
    1569 
    1570 static void balancedCdataBlockHandler(void* closure, const xmlChar* s, int len)
    1571 {
    1572     static_cast<XMLTokenizer*>(closure)->cdataBlock(s, len);
    1573 }
    1574 
    1575 static void balancedCommentHandler(void* closure, const xmlChar* comment)
    1576 {
    1577     static_cast<XMLTokenizer*>(closure)->comment(comment);
    1578 }
    1579 
    1580 WTF_ATTRIBUTE_PRINTF(2, 3)
    1581 static void balancedWarningHandler(void* closure, const char* message, ...)
    1582 {
    1583     va_list args;
    1584     va_start(args, message);
    1585     static_cast<XMLTokenizer*>(closure)->error(XMLTokenizer::warning, message, args);
    1586     va_end(args);
    1587 }
    1588 #endif
    1589 bool parseXMLDocumentFragment(const String& string, DocumentFragment* fragment, Element* parent)
    1590 {
    1591     if (!string.length())
    1592         return true;
    1593 
    1594     XMLTokenizer tokenizer(fragment, parent);
    1595    
    1596 #ifndef USE_QXMLSTREAM
    1597     xmlSAXHandler sax;
    1598     memset(&sax, 0, sizeof(sax));
    1599 
    1600     sax.characters = balancedCharactersHandler;
    1601     sax.processingInstruction = balancedProcessingInstructionHandler;
    1602     sax.startElementNs = balancedStartElementNsHandler;
    1603     sax.endElementNs = balancedEndElementNsHandler;
    1604     sax.cdataBlock = balancedCdataBlockHandler;
    1605     sax.ignorableWhitespace = balancedCharactersHandler;
    1606     sax.comment = balancedCommentHandler;
    1607     sax.warning = balancedWarningHandler;
    1608     sax.initialized = XML_SAX2_MAGIC;
    1609    
    1610     int result = xmlParseBalancedChunkMemory(0, &sax, &tokenizer, 0, (const xmlChar*)string.utf8().data(), 0);
     1602    tokenizer.initializeParserContext(chunk.utf8().data());
     1603
     1604    xmlParseContent(tokenizer.m_context);
     1605
    16111606    tokenizer.endDocument();
    1612     return result == 0;
     1607
     1608    // Check if all the chunk has been processed.
     1609    long bytesProcessed = xmlByteConsumed(tokenizer.m_context);
     1610    if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) == sizeof(UChar) * chunk.length())
     1611        return false;
     1612
     1613    // No error if the chunk is well formed or it is not but we have no error.
     1614    return tokenizer.m_context->wellFormed || xmlCtxtGetLastError(tokenizer.m_context) == 0;
    16131615#else
    16141616    tokenizer.write(String("<qxmlstreamdummyelement>"), false);
    1615     tokenizer.write(string, false);
     1617    tokenizer.write(chunk, false);
    16161618    tokenizer.write(String("</qxmlstreamdummyelement>"), false);
    16171619    tokenizer.finish();
  • trunk/WebCore/dom/XMLTokenizer.h

    r30243 r31860  
    8282
    8383#ifndef USE_QXMLSTREAM
     84
     85        friend bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, Element* parent);
     86
    8487        // callbacks from parser SAX
    8588        void error(ErrorType, const char* message, va_list args) WTF_ATTRIBUTE_PRINTF(3, 0);
     
    116119
    117120    private:
    118         void initializeParserContext();
     121        void initializeParserContext(const char* chunk = 0);
    119122        void setCurrentNode(Node*);
    120123
Note: See TracChangeset for help on using the changeset viewer.