2013-09-18 12:10:03 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Marco Martin <notmart@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Library General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this program; if not, write to the
|
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "packageurlinterceptor.h"
|
|
|
|
|
|
|
|
#include <QDebug>
|
2013-09-18 12:49:09 +02:00
|
|
|
#include <QQmlEngine>
|
2013-09-18 16:34:31 +02:00
|
|
|
#include <QFile>
|
|
|
|
|
2013-09-18 18:09:33 +02:00
|
|
|
#include <kdeclarative/kdeclarative.h>
|
2013-09-18 12:10:03 +02:00
|
|
|
|
2013-09-18 12:49:09 +02:00
|
|
|
PackageUrlInterceptor::PackageUrlInterceptor(QQmlEngine *engine, const Plasma::Package &p)
|
2013-09-18 12:10:03 +02:00
|
|
|
: QQmlAbstractUrlInterceptor(),
|
2013-09-18 12:49:09 +02:00
|
|
|
m_package(p),
|
|
|
|
m_engine(engine)
|
2013-09-18 12:10:03 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PackageUrlInterceptor::~PackageUrlInterceptor()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QUrl PackageUrlInterceptor::intercept(const QUrl &path, QQmlAbstractUrlInterceptor::DataType type)
|
|
|
|
{
|
|
|
|
//qDebug() << "Intercepted URL:" << path;
|
|
|
|
|
2013-10-24 12:47:17 +02:00
|
|
|
if (path.scheme() == QStringLiteral("plasmapackage")) {
|
|
|
|
QUrl pkgUrl;
|
|
|
|
pkgUrl.setScheme(QStringLiteral("file"));
|
|
|
|
pkgUrl.setPath(m_package.filePath(0, path.path()));
|
|
|
|
return pkgUrl;
|
|
|
|
}
|
|
|
|
|
2013-09-18 12:49:09 +02:00
|
|
|
//TODO: security: permission for remote urls
|
|
|
|
if (!path.isLocalFile() ) {
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2013-09-18 16:34:31 +02:00
|
|
|
//FIXME: probably needed for QmldirFile as well.
|
|
|
|
//at the moment a qt bug prevents intercept() working with qmldirs
|
|
|
|
//see https://codereview.qt-project.org/#change,61208
|
2013-09-18 15:41:21 +02:00
|
|
|
if (type != QQmlAbstractUrlInterceptor::QmldirFile) {
|
|
|
|
|
2013-09-18 14:11:16 +02:00
|
|
|
//asked a file inside a package: let's rewrite the url!
|
2013-09-18 12:49:09 +02:00
|
|
|
if (path.path().startsWith(m_package.path())) {
|
2013-09-18 15:41:21 +02:00
|
|
|
//qDebug() << "Found URL in package" << path;
|
2013-09-18 14:11:16 +02:00
|
|
|
|
|
|
|
//tries to isolate the relative path asked relative to the contentsPrefixPath: like ui/foo.qml
|
|
|
|
QString relativePath;
|
|
|
|
foreach (const QString &prefix, m_package.contentsPrefixPaths()) {
|
|
|
|
if (path.path().startsWith(m_package.path()+prefix)) {
|
|
|
|
//obtain a string in the form ui/foo/bar/baz.qml
|
|
|
|
relativePath = path.path().mid(QString(m_package.path()+prefix).length());
|
|
|
|
break;
|
|
|
|
}
|
2013-09-18 12:49:09 +02:00
|
|
|
}
|
2013-09-18 14:11:16 +02:00
|
|
|
//should never happen
|
|
|
|
Q_ASSERT(!relativePath.isEmpty());
|
|
|
|
|
2013-10-15 02:48:58 +02:00
|
|
|
QStringList components = relativePath.split(QLatin1Char('/'));
|
2013-09-18 16:34:31 +02:00
|
|
|
//a path with less than 2 items should ever happen
|
2013-09-18 14:11:16 +02:00
|
|
|
Q_ASSERT(components.count() >= 2);
|
|
|
|
|
|
|
|
components.pop_front();
|
2013-09-18 16:34:31 +02:00
|
|
|
//obtain a string in the form foo/bar/baz.qml: ui/ gets discarded
|
2013-10-15 02:48:58 +02:00
|
|
|
const QString &filename = components.join("/");
|
2013-09-18 14:11:16 +02:00
|
|
|
|
|
|
|
//qDebug() << "Returning" << QUrl::fromLocalFile(m_package.filePath(prefixForType(type, filename), filename));
|
|
|
|
return QUrl::fromLocalFile(m_package.filePath(prefixForType(type, filename), filename));
|
|
|
|
|
2013-09-18 12:49:09 +02:00
|
|
|
//forbid to load random absolute paths
|
|
|
|
} else {
|
|
|
|
foreach (const QString &import, m_engine->importPathList()) {
|
|
|
|
//it's from an import, good
|
|
|
|
//TODO: implement imports whitelist?
|
|
|
|
if (path.path().startsWith(import)) {
|
2013-10-15 02:58:15 +02:00
|
|
|
//qDebug() << "Found import, access granted" << path;
|
2013-09-18 16:34:31 +02:00
|
|
|
|
|
|
|
//check if there is a platform specific file that overrides this import
|
|
|
|
foreach (const QString &platform, KDeclarative::runtimePlatform()) {
|
2013-10-15 02:58:15 +02:00
|
|
|
//qDebug() << "Trying" << platform;
|
2013-09-18 16:34:31 +02:00
|
|
|
|
|
|
|
//search for a platformqml/ path sibling of this import path
|
2013-10-15 02:48:58 +02:00
|
|
|
const QString &platformPath = import+QStringLiteral("/../platformqml/")+platform+path.path().mid(import.length());
|
|
|
|
const QFile f(platformPath);
|
2013-09-18 16:34:31 +02:00
|
|
|
|
2013-10-15 02:58:15 +02:00
|
|
|
//qDebug() << "Found a platform specific file:" << QUrl::fromLocalFile(platformPath)<<f.exists();
|
2013-09-18 16:34:31 +02:00
|
|
|
if (f.exists()) {
|
|
|
|
return QUrl::fromLocalFile(platformPath);
|
|
|
|
}
|
|
|
|
}
|
2013-09-18 12:49:09 +02:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
}
|
2013-12-05 19:35:43 +01:00
|
|
|
qWarning() << "WARNING: Access denied for URL" << path << m_package.path();
|
2013-09-18 12:49:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-18 12:10:03 +02:00
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2013-10-24 13:27:02 +02:00
|
|
|
|
2013-09-18 12:10:03 +02:00
|
|
|
|
|
|
|
|