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 "Document.h" 30#include "DOMWindow.h" 31#include "Frame.h" 32#include "SecurityOrigin.h" 33#include "TransformSource.h" 34#include "markup.h" 35#include <wtf/Assertions.h> 36#include <wtf/Vector.h> 37 38#include <qabstractmessagehandler.h> 39#include <qabstracturiresolver.h> 40#include <qbuffer.h> 41#include <qsourcelocation.h> 42#include <qxmlquery.h> 43 44namespace WebCore { 45 46class XSLTMessageHandler : public QAbstractMessageHandler { 47 48public: 49 XSLTMessageHandler(Document* document = 0); 50 virtual void handleMessage(QtMsgType type, const QString& description, 51 const QUrl& identifier, const QSourceLocation& sourceLocation); 52 53private: 54 Document* m_document; 55}; 56 57XSLTMessageHandler::XSLTMessageHandler(Document* document) 58 : QAbstractMessageHandler() 59 , m_document(document) 60{ 61} 62 63void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& description, 64 const QUrl&, const QSourceLocation& sourceLocation) 65{ 66 if (!m_document->frame()) 67 return; 68 69 MessageLevel level; 70 switch (type) { 71 case QtDebugMsg: 72 level = DebugMessageLevel; 73 break; 74 case QtWarningMsg: 75 level = WarningMessageLevel; 76 break; 77 case QtCriticalMsg: 78 case QtFatalMsg: 79 level = ErrorMessageLevel; 80 break; 81 default: 82 level = LogMessageLevel; 83 break; 84 } 85 86 Console* console = m_document->domWindow()->console(); 87 console->addMessage(XMLMessageSource, level, description, sourceLocation.uri().toString(), sourceLocation.line(), sourceLocation.column()); 88} 89 90class XSLTUriResolver : public QAbstractUriResolver { 91 92public: 93 XSLTUriResolver(Document* document); 94 virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const; 95 96private: 97 Document* m_document; 98}; 99 100XSLTUriResolver::XSLTUriResolver(Document* document) 101 : QAbstractUriResolver() 102 , m_document(document) 103{ 104} 105 106QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const 107{ 108 QUrl url = baseURI.resolved(relative); 109 110 if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url)) 111 return QUrl(); 112 return url; 113} 114 115bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&) 116{ 117 bool success = false; 118 119 RefPtr<XSLStyleSheet> stylesheet = m_stylesheet; 120 if (!stylesheet && m_stylesheetRootNode) { 121 Node* node = m_stylesheetRootNode.get(); 122 stylesheet = XSLStyleSheet::createForXSLTProcessor(node->parentNode() ? node->parentNode() : node, 123 node->document()->url().string(), 124 node->document()->url()); // FIXME: Should we use baseURL here? 125 126 // According to Mozilla documentation, the node must be a Document node, an xsl:stylesheet or xsl:transform element. 127 // But we just use text content regardless of node type. 128 stylesheet->parseString(createMarkup(node)); 129 } 130 131 if (!stylesheet || stylesheet->sheetString().isEmpty()) 132 return success; 133 134 RefPtr<Document> ownerDocument = sourceNode->document(); 135 bool sourceIsDocument = (sourceNode == ownerDocument.get()); 136 137 QXmlQuery query(QXmlQuery::XSLT20); 138 139 XSLTMessageHandler messageHandler(ownerDocument.get()); 140 XSLTUriResolver uriResolver(ownerDocument.get()); 141 query.setMessageHandler(&messageHandler); 142 143 XSLTProcessor::ParameterMap::iterator end = m_parameters.end(); 144 for (XSLTProcessor::ParameterMap::iterator it = m_parameters.begin(); it != end; ++it) 145 query.bindVariable(QString(it->key), QXmlItem(QVariant(QString(it->value)))); 146 147 QString source; 148 if (sourceIsDocument && ownerDocument->transformSource()) 149 source = ownerDocument->transformSource()->platformSource(); 150 if (!sourceIsDocument || source.isEmpty()) 151 source = createMarkup(sourceNode); 152 153 QBuffer inputBuffer; 154 QBuffer styleSheetBuffer; 155 QBuffer outputBuffer; 156 157 inputBuffer.setData(source.toUtf8()); 158 styleSheetBuffer.setData(QString(stylesheet->sheetString()).toUtf8()); 159 160 inputBuffer.open(QIODevice::ReadOnly); 161 styleSheetBuffer.open(QIODevice::ReadOnly); 162 outputBuffer.open(QIODevice::ReadWrite); 163 164 query.setFocus(&inputBuffer); 165 query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href())); 166 167 query.setUriResolver(&uriResolver); 168 169 success = query.evaluateTo(&outputBuffer); 170 outputBuffer.reset(); 171 resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed(); 172 173 if (m_stylesheet) { 174 m_stylesheet->clearDocuments(); 175 m_stylesheet = 0; 176 } 177 178 return success; 179} 180 181} // namespace WebCore 182 183#endif // ENABLE(XSLT) 184