• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the XSL implementation.
3  *
4  * Copyright (C) 2009 Jakub Wieczorek <faw217@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "config.h"
23 
24 #if ENABLE(XSLT)
25 
26 #include "XSLTProcessor.h"
27 
28 #include "Console.h"
29 #include "DOMWindow.h"
30 #include "Frame.h"
31 #include "TransformSource.h"
32 #include "markup.h"
33 #include <wtf/Assertions.h>
34 #include <wtf/Vector.h>
35 
36 #include <qabstractmessagehandler.h>
37 #include <qabstracturiresolver.h>
38 #include <qbuffer.h>
39 #include <qsourcelocation.h>
40 #include <qxmlquery.h>
41 
42 namespace WebCore {
43 
44 class XSLTMessageHandler : public QAbstractMessageHandler {
45 
46 public:
47     XSLTMessageHandler(Document* document = 0);
48     virtual void handleMessage(QtMsgType type, const QString& description,
49                                const QUrl& identifier, const QSourceLocation& sourceLocation);
50 
51 private:
52     Document* m_document;
53 };
54 
XSLTMessageHandler(Document * document)55 XSLTMessageHandler::XSLTMessageHandler(Document* document)
56     : QAbstractMessageHandler()
57     , m_document(document)
58 {
59 }
60 
handleMessage(QtMsgType type,const QString & description,const QUrl &,const QSourceLocation & sourceLocation)61 void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& description,
62                                        const QUrl&, const QSourceLocation& sourceLocation)
63 {
64     if (!m_document->frame())
65         return;
66 
67     MessageLevel level;
68     switch (type) {
69     case QtDebugMsg:
70         level = TipMessageLevel;
71         break;
72     case QtWarningMsg:
73         level = WarningMessageLevel;
74         break;
75     case QtCriticalMsg:
76     case QtFatalMsg:
77         level = ErrorMessageLevel;
78         break;
79     default:
80         level = LogMessageLevel;
81         break;
82     }
83 
84     Console* console = m_document->frame()->domWindow()->console();
85     console->addMessage(XMLMessageSource, LogMessageType, level, description,
86                         sourceLocation.line(), sourceLocation.uri().toString());
87 }
88 
89 class XSLTUriResolver : public QAbstractUriResolver {
90 
91 public:
92     XSLTUriResolver(Document* document);
93     virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const;
94 
95 private:
96     Document* m_document;
97 };
98 
XSLTUriResolver(Document * document)99 XSLTUriResolver::XSLTUriResolver(Document* document)
100     : QAbstractUriResolver()
101     , m_document(document)
102 {
103 }
104 
resolve(const QUrl & relative,const QUrl & baseURI) const105 QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const
106 {
107     QUrl url = baseURI.resolved(relative);
108 
109     if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url))
110         return QUrl();
111     return url;
112 }
113 
transformToString(Node * sourceNode,String &,String & resultString,String &)114 bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&)
115 {
116     bool success = false;
117 
118     RefPtr<XSLStyleSheet> stylesheet = m_stylesheet;
119     if (!stylesheet && m_stylesheetRootNode) {
120         Node* node = m_stylesheetRootNode.get();
121         stylesheet = XSLStyleSheet::createForXSLTProcessor(node->parentNode() ? node->parentNode() : node,
122             node->document()->url().string(),
123             node->document()->url()); // FIXME: Should we use baseURL here?
124 
125         // According to Mozilla documentation, the node must be a Document node, an xsl:stylesheet or xsl:transform element.
126         // But we just use text content regardless of node type.
127         stylesheet->parseString(createMarkup(node));
128     }
129 
130     if (!stylesheet || stylesheet->sheetString().isEmpty())
131         return success;
132 
133     RefPtr<Document> ownerDocument = sourceNode->document();
134     bool sourceIsDocument = (sourceNode == ownerDocument.get());
135 
136     QXmlQuery query(QXmlQuery::XSLT20);
137 
138     XSLTMessageHandler messageHandler(ownerDocument.get());
139     XSLTUriResolver uriResolver(ownerDocument.get());
140     query.setMessageHandler(&messageHandler);
141 
142     XSLTProcessor::ParameterMap::iterator end = m_parameters.end();
143     for (XSLTProcessor::ParameterMap::iterator it = m_parameters.begin(); it != end; ++it)
144         query.bindVariable(QString(it->first), QXmlItem(QVariant(QString(it->second))));
145 
146     QString source;
147     if (sourceIsDocument && ownerDocument->transformSource())
148         source = ownerDocument->transformSource()->platformSource();
149     if (!sourceIsDocument || source.isEmpty())
150         source = createMarkup(sourceNode);
151 
152     QBuffer inputBuffer;
153     QBuffer styleSheetBuffer;
154     QBuffer outputBuffer;
155 
156     inputBuffer.setData(source.toUtf8());
157     styleSheetBuffer.setData(QString(stylesheet->sheetString()).toUtf8());
158 
159     inputBuffer.open(QIODevice::ReadOnly);
160     styleSheetBuffer.open(QIODevice::ReadOnly);
161     outputBuffer.open(QIODevice::ReadWrite);
162 
163     query.setFocus(&inputBuffer);
164     query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href()));
165 
166     query.setUriResolver(&uriResolver);
167 
168     success = query.evaluateTo(&outputBuffer);
169     outputBuffer.reset();
170     resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed();
171 
172     if (m_stylesheet) {
173         m_stylesheet->clearDocuments();
174         m_stylesheet = 0;
175     }
176 
177     return success;
178 }
179 
180 } // namespace WebCore
181 
182 #endif // ENABLE(XSLT)
183