1 | /* |
2 | * This file is part of the XSL implementation. |
3 | * |
4 | * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple, Inc. All rights reserved. |
5 | * Copyright (C) 2005, 2006 Alexey Proskuryakov <ap@webkit.org> |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Library General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2 of the License, or (at your option) any later version. |
11 | * |
12 | * This library is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Library General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Library General Public License |
18 | * along with this library; see the file COPYING.LIB. If not, write to |
19 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 | * Boston, MA 02110-1301, USA. |
21 | */ |
22 | |
23 | #include "config.h" |
24 | #include "XSLTProcessor.h" |
25 | |
26 | #if ENABLE(XSLT) |
27 | |
28 | #include "DOMImplementation.h" |
29 | #include "CachedResourceLoader.h" |
30 | #include "ContentSecurityPolicy.h" |
31 | #include "DocumentFragment.h" |
32 | #include "Frame.h" |
33 | #include "FrameLoader.h" |
34 | #include "FrameView.h" |
35 | #include "SecurityOrigin.h" |
36 | #include "SecurityOriginPolicy.h" |
37 | #include "Text.h" |
38 | #include "TextResourceDecoder.h" |
39 | #include "XMLDocument.h" |
40 | #include "markup.h" |
41 | #include <wtf/Assertions.h> |
42 | |
43 | namespace WebCore { |
44 | |
45 | static inline void transformTextStringToXHTMLDocumentString(String& text) |
46 | { |
47 | // Modify the output so that it is a well-formed XHTML document with a <pre> tag enclosing the text. |
48 | text.replaceWithLiteral('&', "&" ); |
49 | text.replaceWithLiteral('<', "<" ); |
50 | text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" |
51 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" |
52 | "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" |
53 | "<head><title/></head>\n" |
54 | "<body>\n" |
55 | "<pre>" + text + "</pre>\n" |
56 | "</body>\n" |
57 | "</html>\n" ; |
58 | } |
59 | |
60 | XSLTProcessor::~XSLTProcessor() |
61 | { |
62 | // Stylesheet shouldn't outlive its root node. |
63 | ASSERT(!m_stylesheetRootNode || !m_stylesheet || m_stylesheet->hasOneRef()); |
64 | } |
65 | |
66 | Ref<Document> XSLTProcessor::createDocumentFromSource(const String& sourceString, |
67 | const String& sourceEncoding, const String& sourceMIMEType, Node* sourceNode, Frame* frame) |
68 | { |
69 | Ref<Document> ownerDocument(sourceNode->document()); |
70 | bool sourceIsDocument = (sourceNode == &ownerDocument.get()); |
71 | String documentSource = sourceString; |
72 | |
73 | RefPtr<Document> result; |
74 | if (sourceMIMEType == "text/plain" ) { |
75 | result = XMLDocument::createXHTML(frame, sourceIsDocument ? ownerDocument->url() : URL()); |
76 | transformTextStringToXHTMLDocumentString(documentSource); |
77 | } else |
78 | result = DOMImplementation::createDocument(sourceMIMEType, frame, sourceIsDocument ? ownerDocument->url() : URL()); |
79 | |
80 | // Before parsing, we need to save & detach the old document and get the new document |
81 | // in place. We have to do this only if we're rendering the result document. |
82 | if (frame) { |
83 | if (FrameView* view = frame->view()) |
84 | view->clear(); |
85 | |
86 | if (Document* oldDocument = frame->document()) { |
87 | result->setTransformSourceDocument(oldDocument); |
88 | result->takeDOMWindowFrom(*oldDocument); |
89 | result->setSecurityOriginPolicy(oldDocument->securityOriginPolicy()); |
90 | result->setCookieURL(oldDocument->cookieURL()); |
91 | result->setFirstPartyForCookies(oldDocument->firstPartyForCookies()); |
92 | result->setSiteForCookies(oldDocument->siteForCookies()); |
93 | result->setStrictMixedContentMode(oldDocument->isStrictMixedContentMode()); |
94 | result->contentSecurityPolicy()->copyStateFrom(oldDocument->contentSecurityPolicy()); |
95 | result->contentSecurityPolicy()->copyUpgradeInsecureRequestStateFrom(*oldDocument->contentSecurityPolicy()); |
96 | } |
97 | |
98 | frame->setDocument(result.copyRef()); |
99 | } |
100 | |
101 | auto decoder = TextResourceDecoder::create(sourceMIMEType); |
102 | decoder->setEncoding(sourceEncoding.isEmpty() ? UTF8Encoding() : TextEncoding(sourceEncoding), TextResourceDecoder::EncodingFromXMLHeader); |
103 | result->setDecoder(WTFMove(decoder)); |
104 | |
105 | result->setContent(documentSource); |
106 | |
107 | return result.releaseNonNull(); |
108 | } |
109 | |
110 | RefPtr<Document> XSLTProcessor::transformToDocument(Node* sourceNode) |
111 | { |
112 | if (!sourceNode) |
113 | return nullptr; |
114 | |
115 | String resultMIMEType; |
116 | String resultString; |
117 | String resultEncoding; |
118 | if (!transformToString(*sourceNode, resultMIMEType, resultString, resultEncoding)) |
119 | return nullptr; |
120 | return createDocumentFromSource(resultString, resultEncoding, resultMIMEType, sourceNode, 0); |
121 | } |
122 | |
123 | RefPtr<DocumentFragment> XSLTProcessor::transformToFragment(Node* sourceNode, Document* outputDoc) |
124 | { |
125 | if (!sourceNode || !outputDoc) |
126 | return nullptr; |
127 | |
128 | String resultMIMEType; |
129 | String resultString; |
130 | String resultEncoding; |
131 | |
132 | // If the output document is HTML, default to HTML method. |
133 | if (outputDoc->isHTMLDocument()) |
134 | resultMIMEType = "text/html" ; |
135 | |
136 | if (!transformToString(*sourceNode, resultMIMEType, resultString, resultEncoding)) |
137 | return nullptr; |
138 | return createFragmentForTransformToFragment(*outputDoc, resultString, resultMIMEType); |
139 | } |
140 | |
141 | void XSLTProcessor::setParameter(const String& /*namespaceURI*/, const String& localName, const String& value) |
142 | { |
143 | if (localName.isNull() || value.isNull()) |
144 | return; |
145 | |
146 | // FIXME: namespace support? |
147 | // should make a QualifiedName here but we'd have to expose the impl |
148 | m_parameters.set(localName, value); |
149 | } |
150 | |
151 | String XSLTProcessor::getParameter(const String& /*namespaceURI*/, const String& localName) const |
152 | { |
153 | if (localName.isNull()) |
154 | return { }; |
155 | |
156 | // FIXME: namespace support? |
157 | // should make a QualifiedName here but we'd have to expose the impl |
158 | return m_parameters.get(localName); |
159 | } |
160 | |
161 | void XSLTProcessor::removeParameter(const String& /*namespaceURI*/, const String& localName) |
162 | { |
163 | if (localName.isNull()) |
164 | return; |
165 | |
166 | // FIXME: namespace support? |
167 | m_parameters.remove(localName); |
168 | } |
169 | |
170 | void XSLTProcessor::reset() |
171 | { |
172 | m_stylesheet = nullptr; |
173 | m_stylesheetRootNode = nullptr; |
174 | m_parameters.clear(); |
175 | } |
176 | |
177 | } // namespace WebCore |
178 | |
179 | #endif // ENABLE(XSLT) |
180 | |