diff options
Diffstat (limited to 'WebCore/dom/XMLTokenizerLibxml2.cpp')
-rw-r--r-- | WebCore/dom/XMLTokenizerLibxml2.cpp | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/WebCore/dom/XMLTokenizerLibxml2.cpp b/WebCore/dom/XMLTokenizerLibxml2.cpp index 9aa0961..42c8b9b 100644 --- a/WebCore/dom/XMLTokenizerLibxml2.cpp +++ b/WebCore/dom/XMLTokenizerLibxml2.cpp @@ -465,7 +465,7 @@ static void errorFunc(void*, const char*, ...) static bool didInit = false; -static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* userData) +PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData) { if (!didInit) { xmlInitParser(); @@ -482,12 +482,12 @@ static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* user const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM); xmlSwitchEncoding(parser, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE); - return parser; + return adoptRef(new XMLParserContext(parser)); } // Chunk should be encoded in UTF-8 -static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk) +PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk) { if (!didInit) { xmlInitParser(); @@ -518,8 +518,8 @@ static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* user parser->str_xmlns = xmlDictLookup(parser->dict, BAD_CAST "xmlns", 5); parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36); parser->_private = userData; - - return parser; + + return adoptRef(new XMLParserContext(parser)); } // -------------------------------- @@ -609,6 +609,13 @@ XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement) m_defaultNamespaceURI = parentElement->namespaceURI(); } +XMLParserContext::~XMLParserContext() +{ + if (m_context->myDoc) + xmlFreeDoc(m_context->myDoc); + xmlFreeParserCtxt(m_context); +} + XMLTokenizer::~XMLTokenizer() { clearCurrentNodeStack(); @@ -616,15 +623,16 @@ XMLTokenizer::~XMLTokenizer() m_doc->deref(); if (m_pendingScript) m_pendingScript->removeClient(this); - if (m_context) - xmlFreeParserCtxt(m_context); } void XMLTokenizer::doWrite(const String& parseString) { if (!m_context) initializeParserContext(); - + + // Protect the libxml context from deletion during a callback + RefPtr<XMLParserContext> context = m_context; + // libXML throws an error if you try to switch the encoding for an empty string. if (parseString.length()) { // Hack around libxml2's lack of encoding overide support by manually @@ -633,15 +641,15 @@ void XMLTokenizer::doWrite(const String& parseString) // and switch encodings, causing the parse to fail. const UChar BOM = 0xFEFF; const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM); - xmlSwitchEncoding(m_context, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE); + xmlSwitchEncoding(context->context(), BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE); XMLTokenizerScope scope(m_doc->docLoader()); - xmlParseChunk(m_context, reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0); + xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0); } if (m_doc->decoder() && m_doc->decoder()->sawError()) { // If the decoder saw an error, report it as fatal (stops parsing) - handleError(fatal, "Encoding error", lineNumber(), columnNumber()); + handleError(fatal, "Encoding error", context->context()->input->line, context->context()->input->col); } return; @@ -1277,9 +1285,9 @@ void XMLTokenizer::initializeParserContext(const char* chunk) XMLTokenizerScope scope(m_doc->docLoader()); if (m_parsingFragment) - m_context = createMemoryParser(&sax, this, chunk); + m_context = XMLParserContext::createMemoryParser(&sax, this, chunk); else - m_context = createStringParser(&sax, this); + m_context = XMLParserContext::createStringParser(&sax, this); } void XMLTokenizer::doEnd() @@ -1300,12 +1308,9 @@ void XMLTokenizer::doEnd() // Tell libxml we're done. { XMLTokenizerScope scope(m_doc->docLoader()); - xmlParseChunk(m_context, 0, 0, 1); + xmlParseChunk(context(), 0, 0, 1); } - if (m_context->myDoc) - xmlFreeDoc(m_context->myDoc); - xmlFreeParserCtxt(m_context); m_context = 0; } } @@ -1334,18 +1339,19 @@ void* xmlDocPtrForString(DocLoader* docLoader, const String& source, const Strin int XMLTokenizer::lineNumber() const { - return m_context ? m_context->input->line : 1; + return context() ? context()->input->line : 1; } int XMLTokenizer::columnNumber() const { - return m_context ? m_context->input->col : 1; + return context() ? context()->input->col : 1; } void XMLTokenizer::stopParsing() { Tokenizer::stopParsing(); - xmlStopParser(m_context); + if (context()) + xmlStopParser(context()); } void XMLTokenizer::resumeParsing() @@ -1384,17 +1390,17 @@ bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, E CString chunkAsUtf8 = chunk.utf8(); tokenizer.initializeParserContext(chunkAsUtf8.data()); - xmlParseContent(tokenizer.m_context); + xmlParseContent(tokenizer.context()); tokenizer.endDocument(); // Check if all the chunk has been processed. - long bytesProcessed = xmlByteConsumed(tokenizer.m_context); + long bytesProcessed = xmlByteConsumed(tokenizer.context()); if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length()) return false; // No error if the chunk is well formed or it is not but we have no error. - return tokenizer.m_context->wellFormed || xmlCtxtGetLastError(tokenizer.m_context) == 0; + return tokenizer.context()->wellFormed || xmlCtxtGetLastError(tokenizer.context()) == 0; } // -------------------------------- @@ -1437,12 +1443,9 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK) memset(&sax, 0, sizeof(sax)); sax.startElementNs = attributesStartElementNsHandler; sax.initialized = XML_SAX2_MAGIC; - xmlParserCtxtPtr parser = createStringParser(&sax, &state); + RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state); String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />"; - xmlParseChunk(parser, reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1); - if (parser->myDoc) - xmlFreeDoc(parser->myDoc); - xmlFreeParserCtxt(parser); + xmlParseChunk(parser->context(), reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1); attrsOK = state.gotAttributes; return state.attributes; } |