1/*
2 * Copyright (C) 2000 Peter Kelly (pmk@post.com)
3 * Copyright (C) 2005-2016 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Samuel Weinig (sam@webkit.org)
5 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
6 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#pragma once
26
27#include "FragmentScriptingPermission.h"
28#include "PendingScriptClient.h"
29#include "ScriptableDocumentParser.h"
30#include "SegmentedString.h"
31#include "XMLErrors.h"
32#include <libxml/tree.h>
33#include <libxml/xmlstring.h>
34#include <wtf/HashMap.h>
35#include <wtf/text/AtomStringHash.h>
36#include <wtf/text/CString.h>
37
38namespace WebCore {
39
40class ContainerNode;
41class CachedResourceLoader;
42class DocumentFragment;
43class Element;
44class FrameView;
45class PendingCallbacks;
46class Text;
47
48class XMLParserContext : public RefCounted<XMLParserContext> {
49public:
50 static RefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void* userData, const CString& chunk);
51 static Ref<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void* userData);
52 ~XMLParserContext();
53 xmlParserCtxtPtr context() const { return m_context; }
54
55private:
56 XMLParserContext(xmlParserCtxtPtr context)
57 : m_context(context)
58 {
59 }
60 xmlParserCtxtPtr m_context;
61};
62
63class XMLDocumentParser final : public ScriptableDocumentParser, public PendingScriptClient {
64 WTF_MAKE_FAST_ALLOCATED;
65public:
66 static Ref<XMLDocumentParser> create(Document& document, FrameView* view)
67 {
68 return adoptRef(*new XMLDocumentParser(document, view));
69 }
70 static Ref<XMLDocumentParser> create(DocumentFragment& fragment, Element* element, ParserContentPolicy parserContentPolicy)
71 {
72 return adoptRef(*new XMLDocumentParser(fragment, element, parserContentPolicy));
73 }
74
75 ~XMLDocumentParser();
76
77 // Exposed for callbacks:
78 void handleError(XMLErrors::ErrorType, const char* message, TextPosition);
79
80 void setIsXHTMLDocument(bool isXHTML) { m_isXHTMLDocument = isXHTML; }
81 bool isXHTMLDocument() const { return m_isXHTMLDocument; }
82
83 static bool parseDocumentFragment(const String&, DocumentFragment&, Element* parent = nullptr, ParserContentPolicy = AllowScriptingContent);
84
85 // Used by XMLHttpRequest to check if the responseXML was well formed.
86 bool wellFormed() const final { return !m_sawError; }
87
88 static bool supportsXMLVersion(const String&);
89
90private:
91 explicit XMLDocumentParser(Document&, FrameView* = nullptr);
92 XMLDocumentParser(DocumentFragment&, Element*, ParserContentPolicy);
93
94 void insert(SegmentedString&&) final;
95 void append(RefPtr<StringImpl>&&) final;
96 void finish() final;
97 bool isWaitingForScripts() const final;
98 void stopParsing() final;
99 void detach() final;
100
101 TextPosition textPosition() const final;
102 bool shouldAssociateConsoleMessagesWithTextPosition() const final;
103
104 void notifyFinished(PendingScript&) final;
105
106 void end();
107
108 void pauseParsing();
109 void resumeParsing();
110
111 bool appendFragmentSource(const String&);
112
113public:
114 // Callbacks from parser SAX, and other functions needed inside
115 // the parser implementation, but outside this class.
116
117 void error(XMLErrors::ErrorType, const char* message, va_list args) WTF_ATTRIBUTE_PRINTF(3, 0);
118 void startElementNs(const xmlChar* xmlLocalName, const xmlChar* xmlPrefix, const xmlChar* xmlURI,
119 int numNamespaces, const xmlChar** namespaces,
120 int numAttributes, int numDefaulted, const xmlChar** libxmlAttributes);
121 void endElementNs();
122 void characters(const xmlChar*, int length);
123 void processingInstruction(const xmlChar* target, const xmlChar* data);
124 void cdataBlock(const xmlChar*, int length);
125 void comment(const xmlChar*);
126 void startDocument(const xmlChar* version, const xmlChar* encoding, int standalone);
127 void internalSubset(const xmlChar* name, const xmlChar* externalID, const xmlChar* systemID);
128 void endDocument();
129
130 bool isParsingEntityDeclaration() const { return m_isParsingEntityDeclaration; }
131 void setIsParsingEntityDeclaration(bool value) { m_isParsingEntityDeclaration = value; }
132
133 int depthTriggeringEntityExpansion() const { return m_depthTriggeringEntityExpansion; }
134 void setDepthTriggeringEntityExpansion(int depth) { m_depthTriggeringEntityExpansion = depth; }
135
136private:
137 void initializeParserContext(const CString& chunk = CString());
138
139 void pushCurrentNode(ContainerNode*);
140 void popCurrentNode();
141 void clearCurrentNodeStack();
142
143 void insertErrorMessageBlock();
144
145 void createLeafTextNode();
146 bool updateLeafTextNode();
147
148 void doWrite(const String&);
149 void doEnd();
150
151 xmlParserCtxtPtr context() const { return m_context ? m_context->context() : nullptr; };
152
153 FrameView* m_view { nullptr };
154
155 SegmentedString m_originalSourceForTransform;
156
157 RefPtr<XMLParserContext> m_context;
158 std::unique_ptr<PendingCallbacks> m_pendingCallbacks;
159 Vector<xmlChar> m_bufferedText;
160 int m_depthTriggeringEntityExpansion { -1 };
161 bool m_isParsingEntityDeclaration { false };
162
163 ContainerNode* m_currentNode { nullptr };
164 Vector<ContainerNode*> m_currentNodeStack;
165
166 RefPtr<Text> m_leafTextNode;
167
168 bool m_sawError { false };
169 bool m_sawCSS { false };
170 bool m_sawXSLTransform { false };
171 bool m_sawFirstElement { false };
172 bool m_isXHTMLDocument { false };
173 bool m_parserPaused { false };
174 bool m_requestingScript { false };
175 bool m_finishCalled { false };
176
177 std::unique_ptr<XMLErrors> m_xmlErrors;
178
179 RefPtr<PendingScript> m_pendingScript;
180 TextPosition m_scriptStartPosition;
181
182 bool m_parsingFragment { false };
183 AtomString m_defaultNamespaceURI;
184
185 HashMap<AtomString, AtomString> m_prefixToNamespaceMap;
186 SegmentedString m_pendingSrc;
187};
188
189#if ENABLE(XSLT)
190xmlDocPtr xmlDocPtrForString(CachedResourceLoader&, const String& source, const String& url);
191#endif
192
193Optional<HashMap<String, String>> parseAttributes(const String&);
194
195} // namespace WebCore
196