blob: b4f2c9d23c536dc07cb634133c03a2c85afabe49 [file] [log] [blame]
/*
* Copyright 2014 Canonical Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cordova_whitelist.hpp"
using namespace CordovaInternal;
WhiteList::WhiteList(): _unlimited(false), _empty(true) {
}
bool WhiteList::isUrlWhiteListed(const QString &uri) const {
// allow everything by default
if (_empty)
return true;
if (_unlimited)
return true;
QUrl parsedUri(uri);
for (const URLPattern &p: _whiteList) {
if (p.matches(parsedUri))
return true;
}
return false;
}
void WhiteList::addWhiteListEntry(const QString &origin, bool) {
_empty = false;
if (_unlimited)
return;
if (origin == "*") {
_unlimited = true;
return;
}
QRegExp parts("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
if (parts.indexIn(origin) == -1)
return;
QString scheme = parts.cap(2);
QString host = parts.cap(4);
// Special case for two urls which are allowed to have empty hosts
if (("file" == scheme || "content" == scheme) && !host.size()) host = "*";
QString port = parts.cap(8);
QString path = parts.cap(9);
if (!scheme.size()) {
_whiteList.append(URLPattern("http", host, port, path));
_whiteList.append(URLPattern("https", host, port, path));
} else {
_whiteList.append(URLPattern(scheme, host, port, path));
}
}
WhiteList::URLPattern::URLPattern(const QString &scheme, const QString &host,
const QString &port, const QString &path) {
if (scheme.size() && "*" != scheme)
_scheme = QRegExp(regexFromPattern(scheme, false), Qt::CaseInsensitive);
if ("*" != host) {
if (host.startsWith("*.")) {
_host = QRegExp("([a-z0-9.-]*\\.)?" + regexFromPattern(host.mid(2), false), Qt::CaseInsensitive);
} else {
_host = QRegExp(regexFromPattern(host, false), Qt::CaseInsensitive);
}
}
if (!port.size() || "*" == port) {
_port = 0;
} else {
_port = port.toInt(nullptr, 10);
}
if (path.size() && "/*" != path) {
_path = QRegExp(regexFromPattern(path, true));
}
}
bool WhiteList::URLPattern::matches(QUrl uri) const {
return ((_scheme.isEmpty() || _scheme.exactMatch(uri.scheme())) &&
(_host.isEmpty() || _host.exactMatch(uri.host())) &&
(_port == 0 || _port == uri.port()) &&
(_path.isEmpty() || _path.exactMatch(uri.path())));
}
QString WhiteList::URLPattern::regexFromPattern(const QString &pattern, bool allowWildcards) const {
QString toReplace("\\.[]{}()^$?+|");
QString regex;
for (int i=0; i < pattern.size(); i++) {
QChar c = pattern[i];
if (c == '*' && allowWildcards) {
regex.append(".");
} else if (toReplace.indexOf(c) > -1) {
regex.append('\\');
}
regex.append(c);
}
return regex;
}