[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings.changes
|
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings.spec
^
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -2,6 +2,6 @@
<service name="tar_git">
<param name="url">https://github.com/sailfishos-oneplus5/nemo-qml-plugin-systemsettings.git</param>
<param name="branch">partitions-fix</param>
- <param name="revision">0.5.24.op5</param>
+ <param name="revision">0.5.34.op5</param>
</service>
</services>
\ No newline at end of file
|
[-]
[+]
|
Deleted |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.24.op5.tar.bz2/src/qdbusxml2cpp_dbus_types.h
^
|
@@ -1,14 +0,0 @@
-#ifndef QDBUSXML2CPP_DBUS_TYPES
-#define QDBUSXML2CPP_DBUS_TYPES
-
-#include <QPair>
-#include <QList>
-#include <QDBusMetaType>
-
-typedef QPair<QDBusObjectPath, QVariantMap> PathProperties;
-Q_DECLARE_METATYPE(PathProperties);
-
-typedef QList<PathProperties> PathPropertiesArray;
-Q_DECLARE_METATYPE(PathPropertiesArray);
-
-#endif
|
[-]
[+]
|
Deleted |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.24.op5.tar.bz2/src/vpnmodel.cpp
^
|
@@ -1,1220 +0,0 @@
-/*
- * Copyright (C) 2016 Jolla Ltd.
- * Contact: Matt Vogt <matthew.vogt@jollamobile.com>
- *
- * You may use this file under the terms of the BSD license as follows:
- *
- * "Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Nemo Mobile nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- */
-
-#include "vpnmodel.h"
-#include "logging_p.h"
-#include "connmanvpnconnectionproxy.h"
-#include "connmanserviceproxy.h"
-
-#include <QStandardPaths>
-#include <QCryptographicHash>
-#include <QDBusPendingCallWatcher>
-#include <QDBusServiceWatcher>
-#include <QRegularExpression>
-
-#include <nemo-dbus/dbus.h>
-
-namespace {
-
-const auto defaultDomain = QStringLiteral("sailfishos.org");
-const auto legacyDefaultDomain(QStringLiteral("merproject.org"));
-const auto connmanService = QStringLiteral("net.connman");
-const auto connmanVpnService = QStringLiteral("net.connman.vpn");
-const auto autoConnectKey = QStringLiteral("AutoConnect");
-
-QString vpnServicePath(QString connectionPath)
-{
- return QString("/net/connman/service/vpn_%1").arg(connectionPath.section("/", 5));
-}
-
-// Conversion to/from DBus/QML
-QHash<QString, QList<QPair<QVariant, QVariant> > > propertyConversions()
-{
- QHash<QString, QList<QPair<QVariant, QVariant> > > rv;
-
- QList<QPair<QVariant, QVariant> > states;
- states.push_back(qMakePair(QVariant::fromValue(QString("idle")), QVariant::fromValue(static_cast<int>(VpnModel::Idle))));
- states.push_back(qMakePair(QVariant::fromValue(QString("failure")), QVariant::fromValue(static_cast<int>(VpnModel::Failure))));
- states.push_back(qMakePair(QVariant::fromValue(QString("configuration")), QVariant::fromValue(static_cast<int>(VpnModel::Configuration))));
- states.push_back(qMakePair(QVariant::fromValue(QString("ready")), QVariant::fromValue(static_cast<int>(VpnModel::Ready))));
- states.push_back(qMakePair(QVariant::fromValue(QString("disconnect")), QVariant::fromValue(static_cast<int>(VpnModel::Disconnect))));
- rv.insert(QString("state"), states);
-
- return rv;
-}
-
-QVariant convertValue(const QString &key, const QVariant &value, bool toDBus)
-{
- static const QHash<QString, QList<QPair<QVariant, QVariant> > > conversions(propertyConversions());
-
- auto it = conversions.find(key.toLower());
- if (it != conversions.end()) {
- const QList<QPair<QVariant, QVariant> > &list(it.value());
- auto lit = std::find_if(list.cbegin(), list.cend(), [value, toDBus](const QPair<QVariant, QVariant> &pair) { return value == (toDBus ? pair.second : pair.first); });
- if (lit != list.end()) {
- return toDBus ? (*lit).first : (*lit).second;
- } else {
- qCWarning(lcVpnLog) << "No conversion found for" << (toDBus ? "QML" : "DBus") << "value:" << value << key;
- }
- }
-
- return value;
-}
-
-QVariant convertToQml(const QString &key, const QVariant &value)
-{
- return convertValue(key, value, false);
-}
-
-QVariant convertToDBus(const QString &key, const QVariant &value)
-{
- return convertValue(key, value, true);
-}
-
-QVariantMap propertiesToDBus(const QVariantMap &fromQml)
-{
- QVariantMap rv;
-
- for (QVariantMap::const_iterator it = fromQml.cbegin(), end = fromQml.cend(); it != end; ++it) {
- QString key(it.key());
- QVariant value(it.value());
-
- if (key == QStringLiteral("providerProperties")) {
- const QVariantMap providerProperties(value.value<QVariantMap>());
- for (QVariantMap::const_iterator pit = providerProperties.cbegin(), pend = providerProperties.cend(); pit != pend; ++pit) {
- rv.insert(pit.key(), pit.value());
- }
- continue;
- }
-
- // The DBus properties are capitalized
- QChar &initial(*key.begin());
- initial = initial.toUpper();
-
- rv.insert(key, convertToDBus(key, value));
- }
-
- return rv;
-}
-
-template<typename T>
-QVariant extract(const QDBusArgument &arg)
-{
- T rv;
- arg >> rv;
- return QVariant::fromValue(rv);
-}
-
-template<typename T>
-QVariant extractArray(const QDBusArgument &arg)
-{
- QVariantList rv;
-
- arg.beginArray();
- while (!arg.atEnd()) {
- rv.append(extract<T>(arg));
- }
- arg.endArray();
-
- return QVariant::fromValue(rv);
-}
-
-QVariantMap propertiesToQml(const QVariantMap &fromDBus)
-{
- QVariantMap rv;
-
- QVariantMap providerProperties;
-
- for (QVariantMap::const_iterator it = fromDBus.cbegin(), end = fromDBus.cend(); it != end; ++it) {
- QString key(it.key());
- QVariant value(it.value());
-
- if (key.indexOf(QChar('.')) != -1) {
- providerProperties.insert(key, value);
- continue;
- }
-
- // QML properties must be lowercased
- QChar &initial(*key.begin());
- initial = initial.toLower();
-
- // Some properties must be extracted manually
- if (key == QStringLiteral("iPv4") ||
- key == QStringLiteral("iPv6")) {
- value = extract<QVariantMap>(value.value<QDBusArgument>());
- } else if (key == QStringLiteral("serverRoutes") ||
- key == QStringLiteral("userRoutes")) {
- value = extractArray<QVariantMap>(value.value<QDBusArgument>());
- }
-
- rv.insert(key, convertToQml(key, value));
- }
-
- if (!providerProperties.isEmpty()) {
- rv.insert(QStringLiteral("providerProperties"), QVariant::fromValue(providerProperties));
- }
-
- return rv;
-}
-
-int numericValue(VpnModel::ConnectionState state)
-{
- return (state == VpnModel::Ready ? 3 : (state == VpnModel::Configuration ? 2 : (state == VpnModel::Failure ? 1 : 0)));
-}
-
-} // end anonymous namespace
-
-VpnModel::CredentialsRepository::CredentialsRepository(const QString &path)
- : baseDir_(path)
-{
- if (!baseDir_.exists() && !baseDir_.mkpath(path)) {
- qCWarning(lcVpnLog) << "Unable to create base directory for VPN credentials:" << path;
- }
-}
-
-QString VpnModel::CredentialsRepository::locationForObjectPath(const QString &path)
-{
- int index = path.lastIndexOf(QChar('/'));
- if (index != -1) {
- return path.mid(index + 1);
- }
-
- return QString();
-}
-
-bool VpnModel::CredentialsRepository::credentialsExist(const QString &location) const
-{
- // Test the FS, as another process may store/remove the credentials
- return baseDir_.exists(location);
-}
-
-bool VpnModel::CredentialsRepository::storeCredentials(const QString &location, const QVariantMap &credentials)
-{
- QFile credentialsFile(baseDir_.absoluteFilePath(location));
- if (!credentialsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- qCWarning(lcVpnLog) << "Unable to write credentials file:" << credentialsFile.fileName();
- return false;
- } else {
- credentialsFile.write(encodeCredentials(credentials));
- credentialsFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ReadOther | QFileDevice::WriteOther);
- credentialsFile.close();
- }
-
- return true;
-}
-
-bool VpnModel::CredentialsRepository::removeCredentials(const QString &location)
-{
- if (baseDir_.exists(location)) {
- if (!baseDir_.remove(location)) {
- qCWarning(lcVpnLog) << "Unable to delete credentials file:" << location;
- return false;
- }
- }
-
- return true;
-}
-
-QVariantMap VpnModel::CredentialsRepository::credentials(const QString &location) const
-{
- QVariantMap rv;
-
- QFile credentialsFile(baseDir_.absoluteFilePath(location));
- if (!credentialsFile.open(QIODevice::ReadOnly)) {
- qCWarning(lcVpnLog) << "Unable to read credentials file:" << credentialsFile.fileName();
- } else {
- const QByteArray encoded = credentialsFile.readAll();
- credentialsFile.close();
-
- rv = decodeCredentials(encoded);
- }
-
- return rv;
-}
-
-QByteArray VpnModel::CredentialsRepository::encodeCredentials(const QVariantMap &credentials)
-{
- // We can't store these values securely, but we may as well encode them to protect from grep, at least...
- QByteArray encoded;
-
- QDataStream os(&encoded, QIODevice::WriteOnly);
- os.setVersion(QDataStream::Qt_5_6);
-
- const quint32 version = 1u;
- os << version;
-
- const quint32 items = credentials.size();
- os << items;
-
- for (auto it = credentials.cbegin(), end = credentials.cend(); it != end; ++it) {
- os << it.key();
- os << it.value().toString();
- }
-
- return encoded.toBase64();
-}
-
-QVariantMap VpnModel::CredentialsRepository::decodeCredentials(const QByteArray &encoded)
-{
- QVariantMap rv;
-
- QByteArray decoded(QByteArray::fromBase64(encoded));
-
- QDataStream is(decoded);
- is.setVersion(QDataStream::Qt_5_6);
-
- quint32 version;
- is >> version;
-
- if (version != 1u) {
- qCWarning(lcVpnLog) << "Invalid version for stored credentials:" << version;
- } else {
- quint32 items;
- is >> items;
-
- for (quint32 i = 0; i < items; ++i) {
- QString key, value;
- is >> key;
- is >> value;
- rv.insert(key, QVariant::fromValue(value));
- }
- }
-
- return rv;
-}
-
-
-VpnModel::VpnModel(QObject *parent)
- : ObjectListModel(parent, true, false)
- , connmanVpn_(connmanVpnService, "/", QDBusConnection::systemBus(), this)
- , credentials_(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/system/privileged/vpn-data"))
- , provisioningOutputPath_(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/system/privileged/vpn-provisioning"))
- , bestState_(VpnModel::Idle)
- , autoConnect_(false)
- , orderByConnected_(false)
-{
- qDBusRegisterMetaType<PathProperties>();
- qDBusRegisterMetaType<PathPropertiesArray>();
-
- connect(&connmanVpn_, &ConnmanVpnProxy::ConnectionAdded, [this](const QDBusObjectPath &objectPath, const QVariantMap &properties) {
- const QString path(objectPath.path());
- VpnConnection *conn = connection(path);
- if (!conn) {
- qCDebug(lcVpnLog) << "Adding connection:" << path;
- conn = newConnection(path);
- }
-
- QVariantMap qmlProperties(propertiesToQml(properties));
- qmlProperties.insert(QStringLiteral("storeCredentials"), credentials_.credentialsExist(CredentialsRepository::locationForObjectPath(path)));
- updateConnection(conn, qmlProperties);
- });
-
- connect(&connmanVpn_, &ConnmanVpnProxy::ConnectionRemoved, [this](const QDBusObjectPath &objectPath) {
- const QString path(objectPath.path());
- if (VpnConnection *conn = connection(path)) {
- qCDebug(lcVpnLog) << "Removing obsolete connection:" << path;
- removeItem(conn);
- delete conn;
- } else {
- qCWarning(lcVpnLog) << "Unable to remove unknown connection:" << path;
- }
-
- // Remove the proxy if present
- auto it = connections_.find(path);
- if (it != connections_.end()) {
- ConnmanVpnConnectionProxy *proxy(*it);
- connections_.erase(it);
- delete proxy;
- }
-
- auto vpnServiceIterator = vpnServices_.find(path);
- if (vpnServiceIterator != vpnServices_.end()) {
- ConnmanServiceProxy *proxy(*vpnServiceIterator);
- vpnServices_.erase(vpnServiceIterator);
- delete proxy;
- }
- });
-
- // If connman-vpn restarts, we need to discard and re-read the state
- QDBusServiceWatcher *watcher = new QDBusServiceWatcher(connmanVpnService, QDBusConnection::systemBus(), QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration, this);
- connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](const QString &) {
- for (int i = 0, n = count(); i < n; ++i) {
- get(i)->deleteLater();
- }
- clear();
- setPopulated(false);
-
- qDeleteAll(connections_);
- connections_.clear();
-
- qDeleteAll(vpnServices_);
- vpnServices_.clear();
- });
- connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, [this](const QString &) {
- fetchVpnList();
- });
-
- fetchVpnList();
-}
-
-VpnModel::~VpnModel()
-{
- deleteAll();
-}
-
-int VpnModel::bestState() const
-{
- return static_cast<int>(bestState_);
-}
-
-bool VpnModel::autoConnect() const
-{
- return autoConnect_;
-}
-
-bool VpnModel::orderByConnected() const
-{
- return orderByConnected_;
-}
-
-void VpnModel::setOrderByConnected(bool orderByConnected)
-{
- if (orderByConnected != orderByConnected_) {
- orderByConnected_ = orderByConnected;
-
- // Update the ordering; only the connected connections need to move
- // In practice only one VPN can be connected, so full sort is overkill
- const int itemCount(count());
- for (int index = 0; index < itemCount; ++index) {
- VpnConnection *conn = get<VpnConnection>(index);
- if (conn->connected()) {
- reorderConnection(conn);
- }
- }
-
- emit orderByConnectedChanged();
- }
-}
-
-void VpnModel::createConnection(const QVariantMap &createProperties)
-{
- const QString path(createProperties.value(QString("path")).toString());
- if (path.isEmpty()) {
- const QString host(createProperties.value(QString("host")).toString());
- const QString name(createProperties.value(QString("name")).toString());
-
- if (!host.isEmpty() && !name.isEmpty()) {
- // Connman requires a domain value, but doesn't seem to use it...
- QVariantMap properties(createProperties);
- const QString domain(properties.value(QString("domain")).toString());
- if (domain.isEmpty()) {
- properties.insert(QString("domain"), QVariant::fromValue(createDefaultDomain()));
- }
-
- QDBusPendingCall call = connmanVpn_.Create(propertiesToDBus(properties));
-
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
- QDBusPendingReply<QDBusObjectPath> reply = *watcher;
- watcher->deleteLater();
-
- if (reply.isError()) {
- qCWarning(lcVpnLog) << "Unable to create Connman VPN connection:" << reply.error().message();
- } else {
- const QDBusObjectPath &objectPath(reply.value());
- qCWarning(lcVpnLog) << "Created VPN connection:" << objectPath.path();
- }
- });
- } else {
- qCWarning(lcVpnLog) << "Unable to create VPN connection without domain, host and name properties";
- }
- } else {
- qCWarning(lcVpnLog) << "Unable to create VPN connection with pre-existing path:" << path;
- }
-}
-
-void VpnModel::modifyConnection(const QString &path, const QVariantMap &properties)
-{
- auto it = connections_.find(path);
- if (it != connections_.end()) {
- // ConnmanVpnConnectionProxy provides the SetProperty interface to modify a connection,
- // but as far as I can tell, the only way to cause Connman to store the configuration to
- // disk is to create a new connection... Work around this by removing the existing
- // connection and recreating it with the updated properties.
- qCWarning(lcVpnLog) << "Updating VPN connection for modification:" << path;
-
- // Remove properties that connman doesn't know about
- QVariantMap updatedProperties(properties);
- updatedProperties.remove(QString("path"));
- updatedProperties.remove(QString("state"));
- updatedProperties.remove(QString("index"));
- updatedProperties.remove(QString("immutable"));
- updatedProperties.remove(QString("storeCredentials"));
-
- const QString domain(updatedProperties.value(QString("domain")).toString());
- if (domain.isEmpty()) {
- updatedProperties.insert(QString("domain"), QVariant::fromValue(createDefaultDomain()));
- }
-
- const QString location(CredentialsRepository::locationForObjectPath(path));
- const bool couldStoreCredentials(credentials_.credentialsExist(location));
- const bool canStoreCredentials(properties.value(QString("storeCredentials")).toBool());
-
- ConnmanVpnConnectionProxy *proxy(*it);
- QVariantMap dbusProps = propertiesToDBus(updatedProperties);
- for (QMap<QString, QVariant>::const_iterator i = dbusProps.constBegin(); i != dbusProps.constEnd(); ++i) {
- proxy->SetProperty(i.key(), QDBusVariant(i.value()));
- }
-
- if (canStoreCredentials != couldStoreCredentials) {
- if (canStoreCredentials) {
- credentials_.storeCredentials(location, QVariantMap());
- } else {
- credentials_.removeCredentials(location);
- }
- }
-
-
- } else {
- qCWarning(lcVpnLog) << "Unable to update unknown VPN connection:" << path;
- }
-}
-
-void VpnModel::deleteConnection(const QString &path)
-{
- if (VpnConnection *conn = connection(path)) {
- if (conn->state() == VpnModel::Ready || conn->state() == VpnModel::Configuration) {
- ConnmanServiceProxy* proxy = vpnServices_.value(path);
- if (proxy) {
- proxy->SetProperty(autoConnectKey, QDBusVariant(false));
- QDBusPendingCall call = proxy->Disconnect();
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
- watcher->deleteLater();
- // Regardless of reply status let's remove it.
- deleteConnection(path);
- });
- }
- } else {
-
- // Remove cached credentials
- const QString location(CredentialsRepository::locationForObjectPath(path));
- if (credentials_.credentialsExist(location)) {
- credentials_.removeCredentials(location);
- }
-
- // Remove provisioned files
- if (conn->type() == QStringLiteral("openvpn")) {
- QVariantMap providerProperties = conn->providerProperties();
- QStringList fileProperties;
- fileProperties << QStringLiteral("OpenVPN.Cert") << QStringLiteral("OpenVPN.Key") << QStringLiteral("OpenVPN.CACert") << QStringLiteral("OpenVPN.ConfigFile");
- for (const QString property : fileProperties) {
- const QString filename = providerProperties.value(property).toString();
-
- // Check if the file has been provisioned
- if (filename.contains(provisioningOutputPath_)) {
- int timesUsed = 0;
-
- // Check the same file is not used by other connections
- for (int i = 0, n = count(); i < n; ++i) {
- VpnConnection *c = qobject_cast<VpnConnection *>(get(i));
- if (filename == c->providerProperties().value(property).toString()) {
- timesUsed++;
- if (timesUsed > 1) {
- break;
- }
- }
- }
-
- if (timesUsed > 1) {
- continue;
- }
-
- if (!QFile::remove(filename)) {
- qCWarning(lcVpnLog) << "Failed to remove provisioning file" << filename;
- }
- }
- }
- }
-
- QDBusPendingCall call = connmanVpn_.Remove(QDBusObjectPath(path));
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
- QDBusPendingReply<void> reply = *watcher;
- watcher->deleteLater();
- if (reply.isError()) {
- qCWarning(lcVpnLog) << "Unable to delete Connman VPN connection:" << path << ":" << reply.error().message();
- } else {
- qCWarning(lcVpnLog) << "Deleted connection:" << path;
- }
- });
- }
- } else {
- qCWarning(lcVpnLog) << "Unable to delete unknown connection:" << path;
- }
-}
-
-void VpnModel::activateConnection(const QString &path)
-{
- qCInfo(lcVpnLog) << "Connect" << path;
- for (int i = 0, n = count(); i < n; ++i) {
- VpnConnection *connection = qobject_cast<VpnConnection *>(get(i));
- QString otherPath = connection->path();
- if (otherPath != path && (connection->state() == VpnModel::Ready ||
- connection->state() == VpnModel::Configuration)) {
- deactivateConnection(otherPath);
- qCDebug(lcVpnLog) << "Adding pending vpn disconnect" << otherPath << connection->state() << "when connecting to vpn";
- }
- }
-
- qCDebug(lcVpnLog) << "About to connect path:" << path;
-
- ConnmanServiceProxy* proxy = vpnServices_.value(path);
- if (proxy) {
- QDBusPendingCall call = proxy->Connect();
- qCDebug(lcVpnLog) << "Connect to vpn" << path;
-
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
- QDBusPendingReply<void> reply = *watcher;
- watcher->deleteLater();
-
- if (reply.isError()) {
- qCWarning(lcVpnLog) << "Unable to activate Connman VPN connection:" << path << ":" << reply.error().message();
- }
- });
- } else {
- qCWarning(lcVpnLog) << "Unable to activate VPN connection without proxy:" << path;
- }
-}
-
-void VpnModel::deactivateConnection(const QString &path)
-{
- qCInfo(lcVpnLog) << "Disconnect" << path;
- ConnmanServiceProxy* proxy = vpnServices_.value(path);
- if (proxy) {
- QDBusPendingCall call = proxy->Disconnect();
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, path](QDBusPendingCallWatcher *watcher) {
- QDBusPendingReply<void> reply = *watcher;
- watcher->deleteLater();
- if (reply.isError()) {
- qCWarning(lcVpnLog) << "Unable to deactivate Connman VPN connection:" << path << ":" << reply.error().message();
- }
- });
- } else {
- qCWarning(lcVpnLog) << "Unable to deactivate VPN connection without proxy:" << path;
- }
-}
-
-QVariantMap VpnModel::connectionCredentials(const QString &path)
-{
- QVariantMap rv;
-
- if (VpnConnection *conn = connection(path)) {
- const QString location(CredentialsRepository::locationForObjectPath(path));
- const bool enabled(credentials_.credentialsExist(location));
-
- if (enabled) {
- rv = credentials_.credentials(location);
- } else {
- qCWarning(lcVpnLog) << "VPN does not permit credentials storage:" << path;
- }
-
- if (conn->storeCredentials() != enabled) {
- conn->setStoreCredentials(enabled);
- itemChanged(conn);
- }
- } else {
- qCWarning(lcVpnLog) << "Unable to return credentials for unknown VPN connection:" << path;
- }
-
- return rv;
-}
-
-void VpnModel::setConnectionCredentials(const QString &path, const QVariantMap &credentials)
-{
- if (VpnConnection *conn = connection(path)) {
- credentials_.storeCredentials(CredentialsRepository::locationForObjectPath(path), credentials);
-
- if (!conn->storeCredentials()) {
- conn->setStoreCredentials(true);
- }
- itemChanged(conn);
- } else {
- qCWarning(lcVpnLog) << "Unable to set credentials for unknown VPN connection:" << path;
- }
-}
-
-bool VpnModel::connectionCredentialsEnabled(const QString &path)
-{
- if (VpnConnection *conn = connection(path)) {
- const QString location(CredentialsRepository::locationForObjectPath(path));
- const bool enabled(credentials_.credentialsExist(location));
-
- if (conn->storeCredentials() != enabled) {
- conn->setStoreCredentials(enabled);
- itemChanged(conn);
- }
- return enabled;
- } else {
- qCWarning(lcVpnLog) << "Unable to test credentials storage for unknown VPN connection:" << path;
- }
-
- return false;
-}
-
-void VpnModel::disableConnectionCredentials(const QString &path)
-{
- if (VpnConnection *conn = connection(path)) {
- const QString location(CredentialsRepository::locationForObjectPath(path));
- if (credentials_.credentialsExist(location)) {
- credentials_.removeCredentials(location);
- }
-
- if (conn->storeCredentials()) {
- conn->setStoreCredentials(false);
- }
- itemChanged(conn);
- } else {
- qCWarning(lcVpnLog) << "Unable to set automatic connection for unknown VPN connection:" << path;
- }
-}
-
-QVariantMap VpnModel::connectionSettings(const QString &path)
-{
- QVariantMap rv;
- if (VpnConnection *conn = connection(path)) {
- // Check if the credentials storage has been changed
- const QString location(CredentialsRepository::locationForObjectPath(path));
- const bool enabled(credentials_.credentialsExist(location));
- if (conn->storeCredentials() != enabled) {
- conn->setStoreCredentials(enabled);
- itemChanged(conn);
- }
-
- rv = itemRoles(conn);
- }
- return rv;
-}
-
-QVariantMap VpnModel::processProvisioningFile(const QString &path, const QString &type)
-{
- QVariantMap rv;
-
- QFile provisioningFile(path);
- if (provisioningFile.open(QIODevice::ReadOnly)) {
- if (type == QString("openvpn")) {
- rv = processOpenVpnProvisioningFile(provisioningFile);
- } else {
- qCWarning(lcVpnLog) << "Provisioning not currently supported for VPN type:" << type;
- }
- } else {
- qCWarning(lcVpnLog) << "Unable to open provisioning file:" << path;
- }
-
- return rv;
-}
-
-void VpnModel::fetchVpnList()
-{
- QDBusPendingCall call = connmanVpn_.GetConnections();
-
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
- QDBusPendingReply<PathPropertiesArray> reply = *watcher;
- watcher->deleteLater();
-
- if (reply.isError()) {
- qCWarning(lcVpnLog) << "Unable to fetch Connman VPN connections:" << reply.error().message();
- } else {
- const PathPropertiesArray &connections(reply.value());
-
- for (const PathProperties &connection : connections) {
- const QString &path(connection.first.path());
- const QVariantMap &properties(connection.second);
-
- QVariantMap qmlProperties(propertiesToQml(properties));
- qmlProperties.insert(QStringLiteral("storeCredentials"), credentials_.credentialsExist(CredentialsRepository::locationForObjectPath(path)));
-
- VpnConnection *conn = newConnection(path);
- updateConnection(conn, qmlProperties);
- }
- }
-
- setPopulated(true);
- });
-}
-
-VpnConnection *VpnModel::connection(const QString &path) const
-{
- for (int i = 0, n = count(); i < n; ++i) {
- VpnConnection *connection = qobject_cast<VpnConnection *>(get(i));
- if (connection->path() == path) {
- return connection;
- }
- }
-
- return nullptr;
-}
-
-VpnConnection *VpnModel::newConnection(const QString &path)
-{
- VpnConnection *conn = new VpnConnection(path);
- appendItem(conn);
-
- // Create a vpn and a connman service proxies for this connection
- ConnmanVpnConnectionProxy *proxy = new ConnmanVpnConnectionProxy(connmanVpnService, path, QDBusConnection::systemBus(), nullptr);
- ConnmanServiceProxy *serviceProxy = new ConnmanServiceProxy(connmanService, vpnServicePath(path), QDBusConnection::systemBus(), nullptr);
-
- connections_.insert(path, proxy);
- vpnServices_.insert(path, serviceProxy);
-
- QDBusPendingCall servicePropertiesCall = serviceProxy->GetProperties();
- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(servicePropertiesCall, this);
- connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, conn, path](QDBusPendingCallWatcher *watcher) {
- QDBusPendingReply<> reply = *watcher;
- if (reply.isFinished() && reply.isValid()) {
- QDBusMessage message = reply.reply();
- QVariantMap properties = NemoDBus::demarshallArgument<QVariantMap>(message.arguments().value(0));
- bool autoConnect = properties.value(autoConnectKey).toBool();
- properties.clear();
- properties.insert(autoConnectKey, autoConnect);
- qCInfo(lcVpnLog) << "Initial VPN service properties:" << properties << path << conn->name();
- updateConnection(conn, propertiesToQml(properties));
- } else {
- qCDebug(lcVpnLog) << "Error :" << path << ":" << reply.error().message();
- }
-
- watcher->deleteLater();
- });
-
- connect(proxy, &ConnmanVpnConnectionProxy::PropertyChanged, this, [this, conn](const QString &name, const QDBusVariant &value) {
- ConnmanVpnConnectionProxy *proxy = qobject_cast<ConnmanVpnConnectionProxy *>(sender());
- QVariantMap properties;
- qCInfo(lcVpnLog) << "VPN connection property changed:" << name << value.variant() << proxy->path() << conn->name();
- properties.insert(name, value.variant());
- updateConnection(conn, propertiesToQml(properties));
- });
-
- connect(serviceProxy, &ConnmanServiceProxy::PropertyChanged, this, [this, conn](const QString &name, const QDBusVariant &value) {
- ConnmanServiceProxy *proxy = qobject_cast<ConnmanServiceProxy *>(sender());
- qCInfo(lcVpnLog) << "VPN service property changed:" << name << value.variant() << proxy->path() << conn->name();
- if (name == autoConnectKey) {
- QVariantMap properties;
- properties.insert(name, value.variant());
- updateConnection(conn, propertiesToQml(properties));
- }
- });
-
- connect(conn, &VpnConnection::autoConnectChanged, conn, [this, conn]() {
- qCInfo(lcVpnLog) << "VPN autoconnect changed:" << conn->name() << conn->autoConnect();
- ConnmanServiceProxy* proxy = vpnServices_.value(conn->path());
- if (proxy) {
- proxy->SetProperty(autoConnectKey, QDBusVariant(conn->autoConnect()));
- }
- });
-
- return conn;
-}
-
-void VpnModel::updateConnection(VpnConnection *conn, const QVariantMap &updateProperties)
-{
- QVariantMap properties(updateProperties);
-
- // If providerProperties have been modified, merge them with existing values
- auto ppit = properties.find(QStringLiteral("providerProperties"));
- if (ppit != properties.end()) {
- QVariantMap existingProperties = conn->providerProperties();
-
- QVariantMap updated = (*ppit).value<QVariantMap>();
- for (QVariantMap::const_iterator pit = updated.cbegin(), pend = updated.cend(); pit != pend; ++pit) {
- existingProperties.insert(pit.key(), pit.value());
- }
-
- *ppit = QVariant::fromValue(existingProperties);
- }
-
- ppit = properties.find(QStringLiteral("domain"));
- if (ppit != properties.end()) {
- QString domain = (*ppit).value<QString>();
- if (isDefaultDomain(domain)) {
- // Default domains are dropped from the model data but
- // let's track what default domains we have seen.
- defaultDomains_.insert(domain);
- properties.erase(ppit);
- }
- }
-
- int oldState(conn->state());
- bool connectionChanged = false;
-
- if (updateItem(conn, properties)) {
- itemChanged(conn);
-
- const int itemCount(count());
-
- if (conn->state() != oldState) {
- emit connectionStateChanged(conn->path(), static_cast<int>(conn->state()));
- if ((conn->state() == VpnModel::Ready) != (oldState == VpnModel::Ready)) {
- emit conn->connectedChanged();
- connectionChanged = true;
- }
-
- // Check to see if the best state has changed
- ConnectionState maxState = Idle;
- for (int i = 0; i < itemCount; ++i) {
- ConnectionState state(static_cast<ConnectionState>(get<VpnConnection>(i)->state()));
- if (numericValue(state) > numericValue(maxState)) {
- maxState = state;
- }
- }
- if (bestState_ != maxState) {
- bestState_ = maxState;
- emit bestStateChanged();
- }
- }
-
- // Keep the items sorted by name and possibly connected status. So sort
- // only when the connection status has changed, or the updateProperties
- // map contains a name i.e. not when "autoConnect" changes. In practice
- // this means that if orderByConnected_ is false then sorting is only
- // allowed when a VPN is created. When modifying name of a VPN, the VPN
- // will be first removed and then recreated.
- if (updateProperties.contains(QStringLiteral("name")) || (orderByConnected_ && connectionChanged)) {
- reorderConnection(conn);
- }
- }
-
- bool autoConnect = false;
- for (int i = 0; i < count(); ++i) {
- autoConnect = autoConnect || get<VpnConnection>(i)->autoConnect();
- }
-
- if (autoConnect_ != autoConnect) {
- autoConnect_ = autoConnect;
- autoConnectChanged();
- }
-}
-
-void VpnModel::reorderConnection(VpnConnection * conn)
-{
- const int itemCount(count());
-
- if (itemCount > 1) {
- int index = 0;
- for ( ; index < itemCount; ++index) {
- const VpnConnection *existing = get<VpnConnection>(index);
- // Scenario 1 orderByConnected == true: order first by connected, second by name
- // Scenario 2 orderByConnected == false: order only by name
- if ((orderByConnected_ && (existing->connected() < conn->connected()))
- || ((!orderByConnected_ || (existing->connected() == conn->connected()))
- && (existing->name() > conn->name()))) {
- break;
- }
- }
- const int currentIndex = indexOf(conn);
- if (index != currentIndex && (index - 1) != currentIndex) {
- moveItem(currentIndex, (currentIndex < index ? (index - 1) : index));
- }
- }
-}
-
-QVariantMap VpnModel::processOpenVpnProvisioningFile(QFile &provisioningFile)
-{
- QVariantMap rv;
-
- QString embeddedMarker;
- QString embeddedContent;
- QStringList extraOptions;
-
- const QRegularExpression commentLeader(QStringLiteral("^\\s*(?:\\#|\\;)"));
- const QRegularExpression embeddedLeader(QStringLiteral("^\\s*<([^\\/>]+)>"));
- const QRegularExpression embeddedTrailer(QStringLiteral("^\\s*<\\/([^\\/>]+)>"));
- const QRegularExpression whitespace(QStringLiteral("\\s"));
-
- auto normaliseProtocol = [](const QString &proto) {
- if (proto == QStringLiteral("tcp")) {
- // 'tcp' is an undocumented option, which is interpreted by openvpn as 'tcp-client'
- return QStringLiteral("tcp-client");
- }
- return proto;
- };
-
- QTextStream is(&provisioningFile);
- while (!is.atEnd()) {
- QString line(is.readLine());
-
- QRegularExpressionMatch match;
- if (line.contains(commentLeader)) {
- // Skip
- } else if (line.contains(embeddedLeader, &match)) {
- embeddedMarker = match.captured(1);
- if (embeddedMarker.isEmpty()) {
- qCWarning(lcVpnLog) << "Invalid embedded content";
- }
- } else if (line.contains(embeddedTrailer, &match)) {
- const QString marker = match.captured(1);
- if (marker != embeddedMarker) {
- qCWarning(lcVpnLog) << "Invalid embedded content:" << marker << "!=" << embeddedMarker;
- } else {
- if (embeddedContent.isEmpty()) {
- qCWarning(lcVpnLog) << "Ignoring empty embedded content:" << embeddedMarker;
- } else {
- if (embeddedMarker == QStringLiteral("connection")) {
- // Special case: not embedded content, but a <connection> structure - pass through as an extra option
- extraOptions.append(QStringLiteral("<connection>\n") + embeddedContent + QStringLiteral("</connection>"));
- } else {
- // Embedded content
- QDir outputDir(provisioningOutputPath_);
- if (!outputDir.exists() && !outputDir.mkpath(provisioningOutputPath_)) {
- qCWarning(lcVpnLog) << "Unable to create base directory for VPN provisioning content:" << provisioningOutputPath_;
- } else {
- // Name the file according to content
- QCryptographicHash hash(QCryptographicHash::Sha1);
- hash.addData(embeddedContent.toUtf8());
-
- const QString outputFileName(QString(hash.result().toHex()) + QChar('.') + embeddedMarker);
- QFile outputFile(outputDir.absoluteFilePath(outputFileName));
- if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- qCWarning(lcVpnLog) << "Unable to write VPN provisioning content file:" << outputFile.fileName();
- } else {
- QTextStream os(&outputFile);
- os << embeddedContent;
-
- // Add the file to the configuration
- if (embeddedMarker == QStringLiteral("ca")) {
- rv.insert(QStringLiteral("OpenVPN.CACert"), outputFile.fileName());
- } else if (embeddedMarker == QStringLiteral("cert")) {
- rv.insert(QStringLiteral("OpenVPN.Cert"), outputFile.fileName());
- } else if (embeddedMarker == QStringLiteral("key")) {
- rv.insert(QStringLiteral("OpenVPN.Key"), outputFile.fileName());
- } else {
- // Assume that the marker corresponds to the openvpn option, (such as 'tls-auth')
- extraOptions.append(embeddedMarker + QChar(' ') + outputFile.fileName());
- }
- }
- }
- }
- }
- }
- embeddedMarker.clear();
- embeddedContent.clear();
- } else if (!embeddedMarker.isEmpty()) {
- embeddedContent.append(line + QStringLiteral("\n"));
- } else {
- QStringList tokens(line.split(whitespace, QString::SkipEmptyParts));
- if (!tokens.isEmpty()) {
- // Find directives that become part of the connman configuration
- const QString& directive(tokens.front());
- const QStringList arguments(tokens.count() > 1 ? tokens.mid(1) : QStringList());
-
- if (directive == QStringLiteral("remote")) {
- // Connman supports a single remote host - if we get further instances, pass them through the config file
- if (!rv.contains(QStringLiteral("Host"))) {
- if (arguments.count() > 0) {
- rv.insert(QStringLiteral("Host"), arguments.at(0));
- }
- if (arguments.count() > 1) {
- rv.insert(QStringLiteral("OpenVPN.Port"), arguments.at(1));
- }
- if (arguments.count() > 2) {
- rv.insert(QStringLiteral("OpenVPN.Proto"), normaliseProtocol(arguments.at(2)));
- }
- } else {
- extraOptions.append(line);
- }
- } else if (directive == QStringLiteral("ca") ||
- directive == QStringLiteral("cert") ||
- directive == QStringLiteral("key") ||
- directive == QStringLiteral("auth-user-pass")) {
- if (!arguments.isEmpty()) {
- // If these file paths are not absolute, assume they are in the same directory as the provisioning file
- QString file(arguments.at(0));
- if (!file.startsWith(QChar('/'))) {
- const QFileInfo info(provisioningFile.fileName());
- file = info.dir().absoluteFilePath(file);
- }
- if (directive == QStringLiteral("ca")) {
- rv.insert(QStringLiteral("OpenVPN.CACert"), file);
- } else if (directive == QStringLiteral("cert")) {
- rv.insert(QStringLiteral("OpenVPN.Cert"), file);
- } else if (directive == QStringLiteral("key")) {
- rv.insert(QStringLiteral("OpenVPN.Key"), file);
- } else if (directive == QStringLiteral("auth-user-pass")) {
- rv.insert(QStringLiteral("OpenVPN.AuthUserPass"), file);
- }
- } else if (directive == QStringLiteral("auth-user-pass")) {
- // Preserve this option to mean ask for credentials
- rv.insert(QStringLiteral("OpenVPN.AuthUserPass"), QStringLiteral("-"));
- }
- } else if (directive == QStringLiteral("mtu") ||
- directive == QStringLiteral("tun-mtu")) {
- // Connman appears to use a long obsolete form of this option...
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.MTU"), arguments.join(QChar(' ')));
- }
- } else if (directive == QStringLiteral("ns-cert-type")) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.NSCertType"), arguments.join(QChar(' ')));
- }
- } else if (directive == QStringLiteral("proto")) {
- if (!arguments.isEmpty()) {
- // All values from a 'remote' directive to take precedence
- if (!rv.contains(QStringLiteral("OpenVPN.Proto"))) {
- rv.insert(QStringLiteral("OpenVPN.Proto"), normaliseProtocol(arguments.join(QChar(' '))));
- }
- }
- } else if (directive == QStringLiteral("port")) {
- // All values from a 'remote' directive to take precedence
- if (!rv.contains(QStringLiteral("OpenVPN.Port"))) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.Port"), arguments.join(QChar(' ')));
- }
- }
- } else if (directive == QStringLiteral("askpass")) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.AskPass"), arguments.join(QChar(' ')));
- } else {
- rv.insert(QStringLiteral("OpenVPN.AskPass"), QString());
- }
- } else if (directive == QStringLiteral("auth-nocache")) {
- rv.insert(QStringLiteral("OpenVPN.AuthNoCache"), QStringLiteral("true"));
- } else if (directive == QStringLiteral("tls-remote")) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.TLSRemote"), arguments.join(QChar(' ')));
- }
- } else if (directive == QStringLiteral("cipher")) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.Cipher"), arguments.join(QChar(' ')));
- }
- } else if (directive == QStringLiteral("auth")) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.Auth"), arguments.join(QChar(' ')));
- }
- } else if (directive == QStringLiteral("comp-lzo")) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.CompLZO"), arguments.join(QChar(' ')));
- } else {
- rv.insert(QStringLiteral("OpenVPN.CompLZO"), QStringLiteral("adaptive"));
- }
- } else if (directive == QStringLiteral("remote-cert-tls")) {
- if (!arguments.isEmpty()) {
- rv.insert(QStringLiteral("OpenVPN.RemoteCertTls"), arguments.join(QChar(' ')));
- }
- } else {
- // A directive that connman does not care about - pass through to the config file
- extraOptions.append(line);
- }
- }
- }
- }
-
- if (!extraOptions.isEmpty()) {
- // Write a config file to contain the extra options
- QDir outputDir(provisioningOutputPath_);
- if (!outputDir.exists() && !outputDir.mkpath(provisioningOutputPath_)) {
- qCWarning(lcVpnLog) << "Unable to create base directory for VPN provisioning content:" << provisioningOutputPath_;
- } else {
- // Name the file according to content
- QCryptographicHash hash(QCryptographicHash::Sha1);
- foreach (const QString &line, extraOptions) {
- hash.addData(line.toUtf8());
- }
-
- const QString outputFileName(QString(hash.result().toHex()) + QStringLiteral(".conf"));
- QFile outputFile(outputDir.absoluteFilePath(outputFileName));
- if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- qCWarning(lcVpnLog) << "Unable to write VPN provisioning configuration file:" << outputFile.fileName();
- } else {
- QTextStream os(&outputFile);
- foreach (const QString &line, extraOptions) {
- os << line << endl;
- }
-
- rv.insert(QStringLiteral("OpenVPN.ConfigFile"), outputFile.fileName());
- }
- }
- }
-
- return rv;
-}
-
-bool VpnModel::domainInUse(const QString &domain) const
-{
- if (defaultDomains_.contains(domain)) {
- return true;
- }
-
- const int itemCount(count());
- for (int index = 0; index < itemCount; ++index) {
- const VpnConnection *connection = get<VpnConnection>(index);
- if (connection->domain() == domain) {
- return true;
- }
- }
- return false;
-}
-
-QString VpnModel::createDefaultDomain() const
-{
- QString newDomain = defaultDomain;
- int index = 1;
- while (domainInUse(newDomain)) {
- newDomain = defaultDomain + QString(".%1").arg(index);
- ++index;
- }
- return newDomain;
-}
-
-bool VpnModel::isDefaultDomain(const QString &domain) const
-{
- if (domain == legacyDefaultDomain)
- return true;
-
- static const QRegularExpression domainPattern(QStringLiteral("^%1(\\.\\d+)?$").arg(defaultDomain));
- return domainPattern.match(domain).hasMatch();
-}
-
-
-VpnConnection::VpnConnection(const QString &path)
- : QObject(0)
- , path_(path)
- , state_(static_cast<int>(VpnModel::Disconnect))
- , type_("openvpn")
- , autoConnect_(false)
- , storeCredentials_(false)
- , immutable_(false)
- , index_(-1)
-{
-}
-
|
[-]
[+]
|
Deleted |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.24.op5.tar.bz2/src/vpnmodel.h
^
|
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2016 Jolla Ltd.
- * Contact: Matt Vogt <matthew.vogt@jollamobile.com>
- *
- * You may use this file under the terms of the BSD license as follows:
- *
- * "Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Nemo Mobile nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
- */
-
-#ifndef VPNMODEL_H
-#define VPNMODEL_H
-
-#include "connmanvpnproxy.h"
-
-#include <systemsettingsglobal.h>
-#include <objectlistmodel.h>
-
-#include <QDir>
-#include <QVariantMap>
-
-class ConnmanServiceProxy;
-class ConnmanVpnConnectionProxy;
-
-class SYSTEMSETTINGS_EXPORT VpnConnection;
-
-class SYSTEMSETTINGS_EXPORT VpnModel : public ObjectListModel
-{
- Q_OBJECT
-
- Q_PROPERTY(int bestState READ bestState NOTIFY bestStateChanged)
- Q_PROPERTY(bool autoConnect READ autoConnect NOTIFY autoConnectChanged)
- Q_PROPERTY(bool orderByConnected READ orderByConnected WRITE setOrderByConnected NOTIFY orderByConnectedChanged)
-
-public:
- enum ConnectionState {
- Idle,
- Failure,
- Configuration,
- Ready,
- Disconnect,
- };
- Q_ENUM(ConnectionState)
-
- explicit VpnModel(QObject *parent = 0);
- virtual ~VpnModel();
-
- int bestState() const;
- bool autoConnect() const;
-
- bool orderByConnected() const;
- void setOrderByConnected(bool orderByConnected);
-
- Q_INVOKABLE void createConnection(const QVariantMap &properties);
- Q_INVOKABLE void modifyConnection(const QString &path, const QVariantMap &properties);
- Q_INVOKABLE void deleteConnection(const QString &path);
-
- Q_INVOKABLE void activateConnection(const QString &path);
- Q_INVOKABLE void deactivateConnection(const QString &path);
-
- Q_INVOKABLE QVariantMap connectionCredentials(const QString &path);
- Q_INVOKABLE void setConnectionCredentials(const QString &path, const QVariantMap &credentials);
-
- Q_INVOKABLE bool connectionCredentialsEnabled(const QString &path);
- Q_INVOKABLE void disableConnectionCredentials(const QString &path);
-
- Q_INVOKABLE QVariantMap connectionSettings(const QString &path);
-
- Q_INVOKABLE QVariantMap processProvisioningFile(const QString &path, const QString &type);
-
- VpnConnection *connection(const QString &path) const;
-
-signals:
- void bestStateChanged();
- void autoConnectChanged();
- void connectionStateChanged(const QString &path, int state);
- void orderByConnectedChanged();
-
-private:
- void fetchVpnList();
-
- VpnConnection *newConnection(const QString &path);
- void updateConnection(VpnConnection *conn, const QVariantMap &properties);
-
- QVariantMap processOpenVpnProvisioningFile(QFile &provisioningFile);
-
- bool domainInUse(const QString &domain) const;
- QString createDefaultDomain() const;
- bool isDefaultDomain(const QString &domain) const;
- void reorderConnection(VpnConnection * conn);
-
- class CredentialsRepository
- {
- public:
- CredentialsRepository(const QString &path);
-
- static QString locationForObjectPath(const QString &path);
-
- bool credentialsExist(const QString &location) const;
-
- bool storeCredentials(const QString &location, const QVariantMap &credentials);
- bool removeCredentials(const QString &location);
-
- QVariantMap credentials(const QString &location) const;
-
- static QByteArray encodeCredentials(const QVariantMap &credentials);
- static QVariantMap decodeCredentials(const QByteArray &encoded);
-
- private:
- QDir baseDir_;
- };
-
- ConnmanVpnProxy connmanVpn_;
- QHash<QString, ConnmanVpnConnectionProxy *> connections_;
- QHash<QString, ConnmanServiceProxy *> vpnServices_;
- QSet<QString> defaultDomains_;
- CredentialsRepository credentials_;
- QString provisioningOutputPath_;
- ConnectionState bestState_;
- // True if there's one VPN that has autoConnect true
- bool autoConnect_;
- bool orderByConnected_;
-};
-
-class SYSTEMSETTINGS_EXPORT VpnConnection : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QString path READ path CONSTANT)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(QString host READ host WRITE setHost NOTIFY hostChanged)
- Q_PROPERTY(QString domain READ domain WRITE setDomain NOTIFY domainChanged)
- Q_PROPERTY(QString networks READ networks WRITE setNetworks NOTIFY networksChanged)
- Q_PROPERTY(bool autoConnect READ autoConnect WRITE setAutoConnect NOTIFY autoConnectChanged)
- Q_PROPERTY(bool storeCredentials READ storeCredentials WRITE setStoreCredentials NOTIFY storeCredentialsChanged)
- Q_PROPERTY(int state READ state WRITE setState NOTIFY stateChanged)
- Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
- Q_PROPERTY(bool immutable READ immutable WRITE setImmutable NOTIFY immutableChanged)
- Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged)
- Q_PROPERTY(QVariantMap iPv4 READ iPv4 WRITE setIPv4 NOTIFY iPv4Changed)
- Q_PROPERTY(QVariantMap iPv6 READ iPv6 WRITE setIPv6 NOTIFY iPv6Changed)
- Q_PROPERTY(QStringList nameservers READ nameservers WRITE setNameservers NOTIFY nameserversChanged)
- Q_PROPERTY(QVariantList userRoutes READ userRoutes WRITE setUserRoutes NOTIFY userRoutesChanged)
- Q_PROPERTY(QVariantList serverRoutes READ serverRoutes WRITE setServerRoutes NOTIFY serverRoutesChanged)
- Q_PROPERTY(QVariantMap providerProperties READ providerProperties WRITE setProviderProperties NOTIFY providerPropertiesChanged)
- Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
-
-public:
- VpnConnection(const QString &path);
-
- QString path() const { return path_; }
-
- QString name() const { return name_; }
- void setName(const QString &name) { updateMember(&VpnConnection::name_, name, &VpnConnection::nameChanged); }
-
- QString host() const { return host_; }
- void setHost(const QString &host) { updateMember(&VpnConnection::host_, host, &VpnConnection::hostChanged); }
-
- QString domain() const { return domain_; }
- void setDomain(const QString &domain) { updateMember(&VpnConnection::domain_, domain, &VpnConnection::domainChanged); }
-
- QString networks() const { return networks_; }
- void setNetworks(const QString &networks) { updateMember(&VpnConnection::networks_, networks, &VpnConnection::networksChanged); }
-
- bool autoConnect() const { return autoConnect_; }
- void setAutoConnect(bool autoConnect) { updateMember(&VpnConnection::autoConnect_, autoConnect, &VpnConnection::autoConnectChanged); }
-
- bool storeCredentials() const { return storeCredentials_; }
- void setStoreCredentials(bool storeCredentials) { updateMember(&VpnConnection::storeCredentials_, storeCredentials, &VpnConnection::storeCredentialsChanged); }
-
- int state() const { return state_; }
- void setState(int state) { updateMember(&VpnConnection::state_, state, &VpnConnection::stateChanged); }
-
- QString type() const { return type_; }
- void setType(const QString &type) { updateMember(&VpnConnection::type_, type, &VpnConnection::typeChanged); }
-
- bool immutable() const { return immutable_; }
- void setImmutable(bool immutable) { updateMember(&VpnConnection::immutable_, immutable, &VpnConnection::immutableChanged); }
-
- int index() const { return index_; }
- void setIndex(int index) { updateMember(&VpnConnection::index_, index, &VpnConnection::indexChanged); }
-
- QVariantMap iPv4() const { return ipv4_; }
- void setIPv4(const QVariantMap &ipv4) { updateMember(&VpnConnection::ipv4_, ipv4, &VpnConnection::iPv4Changed); }
-
- QVariantMap iPv6() const { return ipv6_; }
- void setIPv6(const QVariantMap &ipv6) { updateMember(&VpnConnection::ipv6_, ipv6, &VpnConnection::iPv6Changed); }
-
- QStringList nameservers() const { return nameservers_; }
- void setNameservers(const QStringList &nameservers) { updateMember(&VpnConnection::nameservers_, nameservers, &VpnConnection::nameserversChanged); }
-
- QVariantList userRoutes() const { return userRoutes_; }
- void setUserRoutes(const QVariantList &userRoutes) { updateMember(&VpnConnection::userRoutes_, userRoutes, &VpnConnection::userRoutesChanged); }
-
- QVariantList serverRoutes() const { return serverRoutes_; }
- void setServerRoutes(const QVariantList &serverRoutes) { updateMember(&VpnConnection::serverRoutes_, serverRoutes, &VpnConnection::serverRoutesChanged); }
-
- QVariantMap providerProperties() const { return providerProperties_; }
- void setProviderProperties(const QVariantMap providerProperties) { updateMember(&VpnConnection::providerProperties_, providerProperties, &VpnConnection::providerPropertiesChanged); }
-
- int connected() const { return state_ == VpnModel::Ready; }
-
-signals:
- void nameChanged();
- void stateChanged();
- void typeChanged();
- void hostChanged();
- void domainChanged();
- void networksChanged();
- void autoConnectChanged();
- void storeCredentialsChanged();
- void immutableChanged();
- void indexChanged();
- void iPv4Changed();
- void iPv6Changed();
- void nameserversChanged();
- void userRoutesChanged();
- void serverRoutesChanged();
- void providerPropertiesChanged();
- void connectedChanged();
-
-private:
- template<typename T, typename V>
- bool updateMember(T VpnConnection::*member, const V &value, void (VpnConnection::*func)()) {
- if (this->*member != value) {
- this->*member = value;
- emit (this->*func)();
- return true;
- }
- return false;
- }
-
- QString path_;
- QString name_;
- int state_;
- QString type_;
- QString host_;
- QString domain_;
- QString networks_;
- bool autoConnect_;
- bool storeCredentials_;
- bool immutable_;
- int index_;
- QVariantMap ipv4_;
- QVariantMap ipv6_;
- QStringList nameservers_;
- QVariantList userRoutes_;
- QVariantList serverRoutes_;
- QVariantMap providerProperties_;
-};
-
-Q_DECLARE_METATYPE(VpnModel::ConnectionState)
-
-#endif
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/aboutsettings.cpp
^
|
@@ -30,10 +30,13 @@
*/
#include "aboutsettings.h"
+#include "aboutsettings_p.h"
#include <QDebug>
#include <QStringList>
+
#include <QNetworkInfo>
+
#include <QDeviceInfo>
#include <QFile>
#include <QByteArray>
@@ -151,19 +154,33 @@
}
+
+AboutSettingsPrivate::AboutSettingsPrivate(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+AboutSettingsPrivate::~AboutSettingsPrivate()
+{
+
+}
+
+
AboutSettings::AboutSettings(QObject *parent)
-: QObject(parent), m_netinfo(new QNetworkInfo(this)),
- m_devinfo(new QDeviceInfo(this))
+ : QObject(parent)
+ , d_ptr(new AboutSettingsPrivate(this))
{
+ Q_D(AboutSettings);
QSettings settings(QStringLiteral("/mnt/vendor_data/vendor-data.ini"), QSettings::IniFormat);
- m_vendorName = settings.value(QStringLiteral("Name")).toString();
- m_vendorVersion = settings.value(QStringLiteral("Version")).toString();
+ d->vendorName = settings.value(QStringLiteral("Name")).toString();
+ d->vendorVersion = settings.value(QStringLiteral("Version")).toString();
refreshStorageModels();
- connect(&m_partitionManager, &PartitionManager::partitionAdded,
+ connect(&d->partitionManager, &PartitionManager::partitionAdded,
this, &AboutSettings::partitionCountChanged);
- connect(&m_partitionManager, &PartitionManager::partitionRemoved,
+ connect(&d->partitionManager, &PartitionManager::partitionRemoved,
this, &AboutSettings::partitionCountChanged);
}
@@ -173,27 +190,32 @@
qlonglong AboutSettings::totalDiskSpace() const
{
- return m_partitionManager.root().bytesTotal();
+ Q_D(const AboutSettings);
+ return d->partitionManager.root().bytesTotal();
}
qlonglong AboutSettings::availableDiskSpace() const
{
- return m_partitionManager.root().bytesAvailable();
+ Q_D(const AboutSettings);
+ return d->partitionManager.root().bytesAvailable();
}
QVariant AboutSettings::diskUsageModel() const
{
- return m_internalStorage;
+ Q_D(const AboutSettings);
+ return d->internalStorage;
}
QString AboutSettings::wlanMacAddress() const
{
- return m_netinfo->macAddress(QNetworkInfo::WlanMode, 0);
+ Q_D(const AboutSettings);
+ return d->networkInfo.macAddress(QNetworkInfo::WlanMode, 0);
}
QString AboutSettings::imei() const
{
- return m_devinfo->imei(0);
+ Q_D(const AboutSettings);
+ return d->deviceInfo.imei(0);
}
QString AboutSettings::serial() const
@@ -224,9 +246,10 @@
QString AboutSettings::localizedOperatingSystemName() const
{
- parseLocalizationFile(QStringLiteral("/etc/os-release-l10n"), &m_osReleaseLocalization);
+ Q_D(const AboutSettings);
+ parseLocalizationFile(QStringLiteral("/etc/os-release-l10n"), &d->osReleaseLocalization);
- return m_osReleaseLocalization.value("NAME", operatingSystemName());
+ return d->osReleaseLocalization.value("NAME", operatingSystemName());
}
QString AboutSettings::baseOperatingSystemName() const
@@ -240,45 +263,60 @@
QString AboutSettings::operatingSystemName() const
{
- parseReleaseFile(QStringLiteral("/etc/os-release"), &m_osRelease);
+ Q_D(const AboutSettings);
+ parseReleaseFile(QStringLiteral("/etc/os-release"), &d->osRelease);
+
+ return d->osRelease["NAME"];
+}
+
+QString AboutSettings::localizedSoftwareVersion() const
+{
+ Q_D(const AboutSettings);
+ parseLocalizationFile(QStringLiteral("/etc/os-release-l10n"), &d->osReleaseLocalization);
- return m_osRelease["NAME"];
+ return d->osReleaseLocalization.value("VERSION", softwareVersion());
}
QString AboutSettings::softwareVersion() const
{
- parseReleaseFile(QStringLiteral("/etc/os-release"), &m_osRelease);
+ Q_D(const AboutSettings);
+ parseReleaseFile(QStringLiteral("/etc/os-release"), &d->osRelease);
- return m_osRelease["VERSION"];
+ return d->osRelease["VERSION"];
}
QString AboutSettings::softwareVersionId() const
{
- parseReleaseFile(QStringLiteral("/etc/os-release"), &m_osRelease);
+ Q_D(const AboutSettings);
+ parseReleaseFile(QStringLiteral("/etc/os-release"), &d->osRelease);
- return m_osRelease["VERSION_ID"];
+ return d->osRelease["VERSION_ID"];
}
QString AboutSettings::adaptationVersion() const
{
- parseReleaseFile(QStringLiteral("/etc/hw-release"), &m_hardwareRelease);
+ Q_D(const AboutSettings);
+ parseReleaseFile(QStringLiteral("/etc/hw-release"), &d->hardwareRelease);
- return m_hardwareRelease["VERSION_ID"];
+ return d->hardwareRelease["VERSION_ID"];
}
QString AboutSettings::vendorName() const
{
- return m_vendorName;
+ Q_D(const AboutSettings);
+ return d->vendorName;
}
QString AboutSettings::vendorVersion() const
{
- return m_vendorVersion;
+ Q_D(const AboutSettings);
+ return d->vendorVersion;
}
void AboutSettings::refreshStorageModels()
{
- m_partitionManager.refresh();
+ Q_D(AboutSettings);
+ d->partitionManager.refresh();
partitionCountChanged();
}
@@ -292,9 +330,10 @@
void AboutSettings::reloadStorageLists()
{
- m_internalStorage.clear();
+ Q_D(AboutSettings);
+ d->internalStorage.clear();
- for (auto partition : m_partitionManager.partitions()) {
+ for (auto partition : d->partitionManager.partitions()) {
QVariantMap row;
row[QStringLiteral("mounted")] = partition.status() == Partition::Mounted;
row[QStringLiteral("path")] = partition.mountPath();
@@ -318,7 +357,7 @@
}();
if (partition.storageType() != Partition::External) {
- m_internalStorage << QVariant(row);
+ d->internalStorage << QVariant(row);
}
}
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/aboutsettings.h
^
|
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2013 Jolla Ltd. <pekka.vuorela@jollamobile.com>
+ * Copyright (C) 2013 - 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
@@ -36,10 +37,9 @@
#include <QVariant>
#include <systemsettingsglobal.h>
-#include <partitionmanager.h>
-class QNetworkInfo;
-class QDeviceInfo;
+class AboutSettingsPrivate;
+
class SYSTEMSETTINGS_EXPORT AboutSettings: public QObject
{
Q_OBJECT
@@ -50,6 +50,7 @@
Q_PROPERTY(QString localizedOperatingSystemName READ localizedOperatingSystemName CONSTANT)
Q_PROPERTY(QString baseOperatingSystemName READ baseOperatingSystemName CONSTANT)
Q_PROPERTY(QString operatingSystemName READ operatingSystemName CONSTANT)
+ Q_PROPERTY(QString localizedSoftwareVersion READ localizedSoftwareVersion CONSTANT)
Q_PROPERTY(QString softwareVersion READ softwareVersion CONSTANT)
Q_PROPERTY(QString softwareVersionId READ softwareVersionId CONSTANT)
Q_PROPERTY(QString adaptationVersion READ adaptationVersion CONSTANT)
@@ -81,6 +82,7 @@
QString localizedOperatingSystemName() const;
QString baseOperatingSystemName() const;
QString operatingSystemName() const;
+ QString localizedSoftwareVersion() const;
QString softwareVersion() const;
QString softwareVersionId() const;
QString adaptationVersion() const;
@@ -95,18 +97,10 @@
void partitionCountChanged();
void reloadStorageLists();
- QNetworkInfo *m_netinfo;
- QDeviceInfo *m_devinfo;
-
- QVariantList m_internalStorage;
- PartitionManager m_partitionManager;
-
- mutable QMap<QString, QString> m_osRelease;
- mutable QMap<QString, QString> m_osReleaseLocalization;
- mutable QMap<QString, QString> m_hardwareRelease;
+ Q_DECLARE_PRIVATE(AboutSettings)
+ Q_DISABLE_COPY(AboutSettings)
- QString m_vendorName;
- QString m_vendorVersion;
+ AboutSettingsPrivate *d_ptr;
};
#endif
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/aboutsettings_p.h
^
|
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef ABOUTSETTINGS_P_H
+#define ABOUTSETTINGS_P_H
+
+#include <QObject>
+#include <QNetworkInfo>
+#include <QDeviceInfo>
+#include <QVariantList>
+
+#include "partitionmanager.h"
+
+class AboutSettingsPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ AboutSettingsPrivate(QObject *parent = nullptr);
+ virtual ~AboutSettingsPrivate();
+
+ QNetworkInfo networkInfo;
+ QDeviceInfo deviceInfo;
+
+ QVariantList internalStorage;
+
+ PartitionManager partitionManager;
+
+ mutable QMap<QString, QString> osRelease;
+ mutable QMap<QString, QString> osReleaseLocalization;
+ mutable QMap<QString, QString> hardwareRelease;
+
+ QString vendorName;
+ QString vendorVersion;
+};
+
+#endif
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/certificatemodel.cpp
^
|
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2016 Jolla Ltd.
- * COntact: Matt Vogt <matthew.vogt@jollamobile.com>
+ * Copyright (c) 2016 - 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
@@ -426,21 +426,7 @@
if (BIO_read_filename(input, const_cast<char *>(filename.constData())) <= 0) {
qWarning() << "Unable to open PKCS7 file:" << path;
} else {
- STACK_OF(X509_INFO) *certificateStack = PEM_X509_INFO_read_bio(input, NULL, NULL, NULL);
- if (!certificateStack) {
- qWarning() << "Unable to read PKCS7 file:" << path;
- } else {
- while (sk_X509_INFO_num(certificateStack)) {
- X509_INFO *certificateInfo = sk_X509_INFO_shift(certificateStack);
- if (certificateInfo->x509 != NULL) {
- certs.append(certificateInfo->x509);
- certificateInfo->x509 = NULL;
- }
- X509_INFO_free(certificateInfo);
- }
-
- sk_X509_INFO_free(certificateStack);
- }
+ read_pem_from_bio(input);
}
BIO_free(input);
@@ -448,6 +434,39 @@
}
}
+ explicit PKCS7File(const QByteArray &pem)
+ {
+ if (!isValid()) {
+ qWarning() << "Unable to prepare X509 certificates structure";
+ } else {
+ BIO *input = BIO_new_mem_buf(pem.constData(), pem.length());
+ if (!input) {
+ qWarning() << "Unable to allocate new BIO while importing in-memory PEM";
+ } else {
+ read_pem_from_bio(input);
+ BIO_free(input);
+ }
+ }
+ }
+
+ void read_pem_from_bio(BIO *input) {
+ STACK_OF(X509_INFO) *certificateStack = PEM_X509_INFO_read_bio(input, NULL, NULL, NULL);
+ if (!certificateStack) {
+ qWarning() << "Unable to read PKCS7 data";
+ } else {
+ while (sk_X509_INFO_num(certificateStack)) {
+ X509_INFO *certificateInfo = sk_X509_INFO_shift(certificateStack);
+ if (certificateInfo->x509 != NULL) {
+ certs.append(certificateInfo->x509);
+ certificateInfo->x509 = NULL;
+ }
+ X509_INFO_free(certificateInfo);
+ }
+
+ sk_X509_INFO_free(certificateStack);
+ }
+ }
+
~PKCS7File()
{
}
@@ -498,11 +517,17 @@
static Initializer init;
public:
- static QList<Certificate> getCertificates(const QString &bundlePath)
+ template<class T>
+ static QList<Certificate> getCertificates(const T &bundleData)
{
- QList<Certificate> certificates;
+ PKCS7File bundle(bundleData);
- PKCS7File bundle(bundlePath);
+ return bundleToCertificates(bundle);
+ }
+private:
+ static QList<Certificate> bundleToCertificates(PKCS7File &bundle)
+ {
+ QList<Certificate> certificates;
if (bundle.isValid() && bundle.count() > 0) {
certificates.reserve(bundle.count());
bundle.getCertificates().for_each([&certificates](const X509Certificate &cert) {
@@ -514,6 +539,7 @@
}
};
+
LibCrypto::Initializer LibCrypto::init;
const QList<QPair<QString, CertificateModel::BundleType> > &bundlePaths()
@@ -579,9 +605,24 @@
}
}
+ // Matches QSslCertificate::issuerDisplayName() introducd in Qt 5.12
+ // Returns a name that describes the issuer. It returns the CommonName if
+ // available, otherwise falls back to the Organization or the first
+ // OrganizationalUnitName.
+ m_issuerDisplayName = cert.issuerElement(NID_commonName);
+ if (m_issuerDisplayName.isEmpty()) {
+ m_issuerDisplayName = cert.issuerElement(NID_countryName);
+ }
+ if (m_issuerDisplayName.isEmpty()) {
+ m_issuerDisplayName = cert.issuerElement(NID_organizationName);
+ }
+
// Populate the details map
m_details.insert(QStringLiteral("Version"), QVariant(cert.version()));
m_details.insert(QStringLiteral("SerialNumber"), QVariant(cert.serialNumber()));
+ m_details.insert(QStringLiteral("SubjectDisplayName"), QVariant(m_primaryName));
+ m_details.insert(QStringLiteral("OrganizationName"), QVariant(m_organizationName));
+ m_details.insert(QStringLiteral("IssuerDisplayName"), QVariant(m_issuerDisplayName));
QVariantMap validity;
validity.insert(QStringLiteral("NotBefore"), QVariant(cert.notBefore()));
@@ -753,3 +794,7 @@
return LibCrypto::getCertificates(bundlePath);
}
+QList<Certificate> CertificateModel::getCertificates(const QByteArray &pem)
+{
+ return LibCrypto::getCertificates(pem);
+}
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/certificatemodel.h
^
|
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2016 Jolla Ltd.
- * Contact: Matt Vogt <matthew.vogt@jollamobile.com>
+ * Copyright (c) 2016 - 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
@@ -38,7 +38,7 @@
#include <QList>
#include <QVariantMap>
-#include <systemsettingsglobal.h>
+#include "systemsettingsglobal.h"
struct X509Certificate;
@@ -60,6 +60,8 @@
QVariantMap details() const { return m_details; }
+ QString issuerDisplayName() const { return m_issuerDisplayName; }
+
private:
QString m_commonName;
QString m_countryName;
@@ -71,6 +73,8 @@
QDateTime m_notValidBefore;
QDateTime m_notValidAfter;
+ QString m_issuerDisplayName;
+
QVariantMap m_details;
};
@@ -115,8 +119,9 @@
virtual QVariant data(const QModelIndex &index, int role) const;
static QList<Certificate> getCertificates(const QString &bundlePath);
+ static QList<Certificate> getCertificates(const QByteArray &pem);
-signals:
+Q_SIGNALS:
void bundleTypeChanged();
void bundlePathChanged();
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/developermodesettings.cpp
^
|
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2013-2018 Jolla Ltd.
+ * Copyright (c) 2013 – 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
* Contact: Thomas Perl <thomas.perl@jollamobile.com>
* Contact: Raine Makelainen <raine.makelainen@jolla.com>
*
@@ -55,6 +56,7 @@
/* A file that is provided by the developer mode package */
#define DEVELOPER_MODE_PROVIDED_FILE "/usr/bin/devel-su"
#define DEVELOPER_MODE_PACKAGE "jolla-developer-mode"
+#define DEVELOPER_MODE_PACKAGE_PRELOAD_DIR "/var/lib/jolla-developer-mode/preloaded/"
/* D-Bus service */
#define USB_MODED_SERVICE "com.meego.usb_moded"
@@ -84,6 +86,17 @@
return result;
}
+static QString get_cached_package(const QString &version)
+{
+ QDir dir(DEVELOPER_MODE_PACKAGE_PRELOAD_DIR);
+ QStringList filters;
+ filters << QStringLiteral("%1-%2.*.rpm").arg(DEVELOPER_MODE_PACKAGE).arg(version);
+ auto preloaded = dir.entryList(filters, QDir::Files, QDir::Name);
+ if (preloaded.empty())
+ return QString();
+ return dir.absoluteFilePath(preloaded.last());
+}
+
DeveloperModeSettings::DeveloperModeSettings(QObject *parent)
: QObject(parent)
, m_usbModeDaemon(USB_MODED_SERVICE, USB_MODED_PATH, USB_MODED_INTERFACE, QDBusConnection::systemBus())
@@ -97,6 +110,8 @@
, m_transactionRole(PackageKit::Transaction::RoleUnknown)
, m_transactionStatus(PackageKit::Transaction::StatusUnknown)
, m_refreshedForInstall(false)
+ , m_localInstallFailed(false)
+ , m_localDeveloperModePackagePath(get_cached_package(QStringLiteral("*"))) // Initialized to possibly incompatible package
{
int uid = getdef_num("UID_MIN", -1);
struct passwd *pwd;
@@ -106,6 +121,23 @@
qCWarning(lcDeveloperModeLog) << "Failed to return username using getpwuid()";
}
+ // Resolve and update local package path
+ if (!m_localDeveloperModePackagePath.isEmpty()) {
+ PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE"-preload", PackageKit::Transaction::FilterInstalled);
+ connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode);
+ connect(resolvePackage, &PackageKit::Transaction::package,
+ this, [this](PackageKit::Transaction::Info info, const QString &packageID, const QString &summary) {
+ Q_UNUSED(summary)
+ Q_ASSERT(info == PackageKit::Transaction::InfoInstalled);
+ const QString version = PackageKit::Transaction::packageVersion(packageID);
+ m_localDeveloperModePackagePath = get_cached_package(version);
+ if (m_localDeveloperModePackagePath.isEmpty()) {
+ emit repositoryAccessRequiredChanged();
+ }
+ qCDebug(lcDeveloperModeLog) << "Preload package version: " << version << ", local package path: " << m_localDeveloperModePackagePath;
+ });
+ }
+
refresh();
// TODO: Watch WLAN / USB IP addresses for changes
@@ -146,6 +178,12 @@
return m_workProgress;
}
+bool DeveloperModeSettings::repositoryAccessRequired() const
+{
+ // Aka local-install-of-developer-mode-package-is-not-possible
+ return m_localInstallFailed || m_localDeveloperModePackagePath.isEmpty();
+}
+
void DeveloperModeSettings::setDeveloperMode(bool enabled)
{
if (m_developerModeEnabled != enabled) {
@@ -233,72 +271,114 @@
void DeveloperModeSettings::resolveAndExecute(Command command)
{
setWorkStatus(Preparing);
+ m_workProgress = 0;
m_developerModePackageId.clear(); // might differ between installed/available
- PackageKit::Transaction::Filters filters;
- if (command == RemoveCommand) {
- filters = PackageKit::Transaction::FilterInstalled;
+ if (command == InstallCommand && !m_localInstallFailed && !m_localDeveloperModePackagePath.isEmpty()) {
+ // Resolve which version of developer mode package is expected
+ PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE"-preload", PackageKit::Transaction::FilterInstalled);
+ connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode);
+ connect(resolvePackage, &PackageKit::Transaction::package,
+ this, [this](PackageKit::Transaction::Info info, const QString &packageID, const QString &summary) {
+ Q_UNUSED(summary)
+ Q_ASSERT(info == PackageKit::Transaction::InfoInstalled);
+ const QString version = PackageKit::Transaction::packageVersion(packageID);
+ m_localDeveloperModePackagePath = get_cached_package(version);
+ emit repositoryAccessRequiredChanged();
+ qCDebug(lcDeveloperModeLog) << "Preload package version: " << version << ", local package path: " << m_localDeveloperModePackagePath;
+ });
+
+ connect(resolvePackage, &PackageKit::Transaction::finished,
+ this, [this](PackageKit::Transaction::Exit status, uint runtime) {
+ Q_UNUSED(runtime)
+ if (status != PackageKit::Transaction::ExitSuccess || m_localDeveloperModePackagePath.isEmpty()) {
+ qCDebug(lcDeveloperModeLog) << "Preloaded package not found, must use remote package";
+ // No cached package => install from repos
+ resolveAndExecute(InstallCommand);
+ } else {
+ PackageKit::Transaction *tx = PackageKit::Daemon::installFiles(QStringList() << m_localDeveloperModePackagePath);
+ connectCommandSignals(tx);
+ connect(tx, &PackageKit::Transaction::finished,
+ this, [this](PackageKit::Transaction::Exit status, uint runtime) {
+ if (status == PackageKit::Transaction::ExitSuccess) {
+ qCDebug(lcDeveloperModeLog) << "Developer mode installation from local package transaction done:" << status << runtime;
+ resetState();
+ } else if (status == PackageKit::Transaction::ExitFailed) {
+ qCWarning(lcDeveloperModeLog) << "Developer mode installation from local package failed, trying from repos";
+ m_localInstallFailed = true;
+ emit repositoryAccessRequiredChanged();
+ resolveAndExecute(InstallCommand); // TODO: If repo access is not available this can not bail out
+ } // else ExitUnknown (ignored)
+ });
+ }
+ });
+
} else {
- filters = PackageKit::Transaction::FilterNewest;
- }
- PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE, filters);
+ PackageKit::Transaction::Filters filters;
+ if (command == RemoveCommand) {
+ filters = PackageKit::Transaction::FilterInstalled;
+ } else {
+ filters = PackageKit::Transaction::FilterNewest;
+ }
+ PackageKit::Transaction *resolvePackage = PackageKit::Daemon::resolve(DEVELOPER_MODE_PACKAGE, filters);
- connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode);
- connect(resolvePackage, &PackageKit::Transaction::package,
- this, [this](PackageKit::Transaction::Info info, const QString &packageId, const QString &summary) {
- qCDebug(lcDeveloperModeLog) << "Package transaction:" << info << packageId << "summary:" << summary;
- m_developerModePackageId = packageId;
- });
+ connect(resolvePackage, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode);
+ connect(resolvePackage, &PackageKit::Transaction::package,
+ this, [this](PackageKit::Transaction::Info info, const QString &packageId, const QString &summary) {
+ qCDebug(lcDeveloperModeLog) << "Package transaction:" << info << packageId << "summary:" << summary;
+ m_developerModePackageId = packageId;
+ });
+
+ connect(resolvePackage, &PackageKit::Transaction::finished,
+ this, [this, command](PackageKit::Transaction::Exit status, uint runtime) {
+ Q_UNUSED(runtime)
+
+ if (status != PackageKit::Transaction::ExitSuccess || m_developerModePackageId.isEmpty()) {
+ if (command == InstallCommand) {
+ if (m_refreshedForInstall) {
+ qCWarning(lcDeveloperModeLog) << "Failed to install developer mode, package didn't resolve.";
+ resetState();
+ } else {
+ refreshPackageCacheAndInstall(); // try once if it helps
+ }
+ } else if (command == RemoveCommand) {
+ qCWarning(lcDeveloperModeLog) << "Removing developer mode but package didn't resolve into anything. Shouldn't happen.";
+ resetState();
+ }
- connect(resolvePackage, &PackageKit::Transaction::finished,
- this, [this, command](PackageKit::Transaction::Exit status, uint runtime) {
- Q_UNUSED(runtime)
+ } else if (command == InstallCommand) {
+ PackageKit::Transaction *tx = PackageKit::Daemon::installPackage(m_developerModePackageId);
+ connectCommandSignals(tx);
- if (status != PackageKit::Transaction::ExitSuccess || m_developerModePackageId.isEmpty()) {
- if (command == InstallCommand) {
if (m_refreshedForInstall) {
- qCWarning(lcDeveloperModeLog) << "Failed to install developer mode, package didn't resolve.";
- resetState();
+ connect(tx, &PackageKit::Transaction::finished,
+ this, [this](PackageKit::Transaction::Exit status, uint runtime) {
+ qCDebug(lcDeveloperModeLog) << "Developer mode installation transaction done (with refresh):" << status << runtime;
+ resetState();
+ });
} else {
- refreshPackageCacheAndInstall(); // try once if it helps
+ connect(tx, &PackageKit::Transaction::finished,
+ this, [this](PackageKit::Transaction::Exit status, uint runtime) {
+ if (status == PackageKit::Transaction::ExitSuccess) {
+ qCDebug(lcDeveloperModeLog) << "Developer mode installation transaction done:" << status << runtime;
+ resetState();
+ } else {
+ qCDebug(lcDeveloperModeLog) << "Developer mode installation failed, trying again after refresh";
+ refreshPackageCacheAndInstall();
+ }
+ });
}
- } else if (command == RemoveCommand) {
- qCWarning(lcDeveloperModeLog) << "Removing developer mode but package didn't resolve into anything. Shouldn't happen.";
- resetState();
- }
-
- } else if (command == InstallCommand) {
- PackageKit::Transaction *tx = PackageKit::Daemon::installPackage(m_developerModePackageId);
- connectCommandSignals(tx);
-
- if (m_refreshedForInstall) {
- connect(tx, &PackageKit::Transaction::finished,
- this, [this](PackageKit::Transaction::Exit status, uint runtime) {
- qCDebug(lcDeveloperModeLog) << "Developer mode installation transaction done (with refresh):" << status << runtime;
- resetState();
- });
} else {
+ PackageKit::Transaction *tx = PackageKit::Daemon::removePackage(m_developerModePackageId, true, true);
+ connectCommandSignals(tx);
connect(tx, &PackageKit::Transaction::finished,
this, [this](PackageKit::Transaction::Exit status, uint runtime) {
- if (status == PackageKit::Transaction::ExitSuccess) {
- qCDebug(lcDeveloperModeLog) << "Developer mode installation transaction done:" << status << runtime;
- resetState();
- } else {
- qCDebug(lcDeveloperModeLog) << "Developer mode installation failed, trying again after refresh";
- refreshPackageCacheAndInstall();
- }
+ qCDebug(lcDeveloperModeLog) << "Developer mode removal transaction done:" << status << runtime;
+ resetState();
});
}
- } else {
- PackageKit::Transaction *tx = PackageKit::Daemon::removePackage(m_developerModePackageId, true, true);
- connectCommandSignals(tx);
- connect(tx, &PackageKit::Transaction::finished,
- this, [this](PackageKit::Transaction::Exit status, uint runtime) {
- qCDebug(lcDeveloperModeLog) << "Developer mode removal transaction done:" << status << runtime;
- resetState();
- });
- }
- });
+ });
+ }
}
void DeveloperModeSettings::connectCommandSignals(PackageKit::Transaction *transaction)
@@ -319,19 +399,16 @@
void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction::Status status, PackageKit::Transaction::Role role)
{
- // Do not update progress when finished.
- if (status == PackageKit::Transaction::StatusFinished) {
- return;
- }
-
// Expected changes from PackageKit when installing packages:
- // 1. Change to 'install packages' role
+ // 1. Change to 'install packages' role or 'install files' if installing from local package file
// 2. Status changes:
// setup -> refresh cache -> query -> resolve deps -> install (refer to as 'Preparing' status)
// -> download ('DownloadingPackages' status)
// -> install ('InstallingPackages' status)
// -> finished
//
+ // If installing from local package fails, it starts over!
+ //
// Expected changes from PackageKit when removing packages:
// 1. Change to 'remove packages' role
// 2. Status changes:
@@ -347,10 +424,17 @@
m_transactionRole = role;
m_transactionStatus = status;
+ // Do not update progress when finished or role is unknown.
+ if (m_transactionStatus == PackageKit::Transaction::StatusFinished
+ || m_transactionRole == PackageKit::Transaction::RoleUnknown) {
+ return;
+ }
+
if (percentage >= 0 && percentage <= 100) {
int rangeStart = 0;
int rangeEnd = 0;
- if (m_transactionRole == PackageKit::Transaction::RoleInstallPackages) {
+ if (m_transactionRole == PackageKit::Transaction::RoleInstallPackages
+ || m_transactionRole == PackageKit::Transaction::RoleInstallFiles) {
switch (m_transactionStatus) {
case PackageKit::Transaction::StatusRefreshCache: // 0-10 %
rangeStart = 0;
@@ -362,7 +446,10 @@
rangeEnd = 20;
break;
case PackageKit::Transaction::StatusDownload: // 20-60 %
- workStatus = DownloadingPackages;
+ // Skip downloading when installing from local file
+ if (m_transactionRole != PackageKit::Transaction::RoleInstallFiles) {
+ workStatus = DownloadingPackages;
+ }
rangeStart = 20;
rangeEnd = 60;
break;
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/developermodesettings.h
^
|
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2013 Jolla Ltd.
+ * Copyright (c) 2013 – 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
* Contact: Thomas Perl <thomas.perl@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
@@ -55,6 +56,7 @@
Q_PROPERTY(bool developerModeEnabled READ developerModeEnabled NOTIFY developerModeEnabledChanged)
Q_PROPERTY(enum DeveloperModeSettings::Status workStatus READ workStatus NOTIFY workStatusChanged)
Q_PROPERTY(int workProgress READ workProgress NOTIFY workProgressChanged)
+ Q_PROPERTY(bool repositoryAccessRequired READ repositoryAccessRequired NOTIFY repositoryAccessRequiredChanged)
public:
explicit DeveloperModeSettings(QObject *parent = NULL);
@@ -74,6 +76,7 @@
bool developerModeEnabled() const;
enum DeveloperModeSettings::Status workStatus() const;
int workProgress() const;
+ bool repositoryAccessRequired() const;
Q_INVOKABLE void setDeveloperMode(bool enabled);
Q_INVOKABLE void setUsbIpAddress(const QString &usbIpAddress);
@@ -85,6 +88,7 @@
void developerModeEnabledChanged();
void workStatusChanged();
void workProgressChanged();
+ void repositoryAccessRequiredChanged();
private slots:
void reportTransactionErrorCode(PackageKit::Transaction::Error code, const QString &details);
@@ -117,6 +121,8 @@
PackageKit::Transaction::Role m_transactionRole;
PackageKit::Transaction::Status m_transactionStatus;
bool m_refreshedForInstall;
+ bool m_localInstallFailed;
+ QString m_localDeveloperModePackagePath;
};
Q_DECLARE_METATYPE(DeveloperModeSettings::Status)
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/diskusage.cpp
^
|
@@ -98,8 +98,8 @@
// Sort keys in reverse order (so child directories come before their
// parents, and the calculation is done correctly, no child directory
// subtracted once too often), for example:
- // 1. a0 = size(/home/nemo/foo/)
- // 2. b0 = size(/home/nemo/)
+ // 1. a0 = size(/home/<user>/foo/)
+ // 2. b0 = size(/home/<user>/)
// 3. c0 = size(/)
//
// This will calculate the following changes in the nested for loop below:
@@ -113,9 +113,9 @@
// 3. c' = c2 = c1 - b1 = (c0 - a0) - (b0 - a0) = c0 - a0 - b0 + a0 = c0 - b0
//
// Or with paths:
- // 1. output(/home/nemo/foo/) = size(/home/nemo/foo/)
- // 2. output(/home/nemo/) = size(/home/nemo/) - size(/home/nemo/foo/)
- // 3. output(/) = size(/) - size(/home/nemo/)
+ // 1. output(/home/<user>/foo/) = size(/home/<user>/foo/)
+ // 2. output(/home/<user>/) = size(/home/<user>/) - size(/home/<user>/foo/)
+ // 3. output(/) = size(/) - size(/home/<user>/)
QStringList keys;
foreach (const QString &key, usage.uniqueKeys()) {
keys << expandedPaths.value(key, key);
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/locationsettings.cpp
^
|
@@ -66,6 +66,9 @@
const QString LocationSettingsHereEnabledKey = QStringLiteral("here\\enabled");
const QString LocationSettingsHereAgreementAcceptedKey = QStringLiteral("here\\agreement_accepted");
const QString LocationSettingsHereOnlineEnabledKey = QStringLiteral("here\\online_enabled");
+ const QString LocationSettingsYandexLocatorEnabledKey = QStringLiteral("yandex\\enabled");
+ const QString LocationSettingsYandexLocatorAgreementAcceptedKey = QStringLiteral("yandex\\agreement_accepted");
+ const QString LocationSettingsYandexLocatorOnlineEnabledKey = QStringLiteral("yandex\\online_enabled");
const QMap<LocationSettings::DataSource, QString> AllowedDataSourcesKeys {
{ LocationSettings::OnlineDataSources, QStringLiteral("allowed_data_sources\\online") },
{ LocationSettings::DeviceSensorsData, QStringLiteral("allowed_data_sources\\device_sensors") },
@@ -180,7 +183,9 @@
, m_locationEnabled(false)
, m_gpsEnabled(false)
, m_mlsEnabled(true)
+ , m_yandexLocatorEnabled(true)
, m_mlsOnlineState(LocationSettings::OnlineAGpsAgreementNotAccepted)
+ , m_yandexLocatorOnlineState(LocationSettings::OnlineAGpsAgreementNotAccepted)
, m_hereState(LocationSettings::OnlineAGpsAgreementNotAccepted)
, m_locationMode(LocationSettings::CustomMode)
, m_settingLocationMode(true)
@@ -201,6 +206,10 @@
this, &LocationSettingsPrivate::recalculateLocationMode);
connect(q, &LocationSettings::mlsOnlineStateChanged,
this, &LocationSettingsPrivate::recalculateLocationMode);
+ connect(q, &LocationSettings::yandexLocatorEnabledChanged,
+ this, &LocationSettingsPrivate::recalculateLocationMode);
+ connect(q, &LocationSettings::yandexLocatorOnlineStateChanged,
+ this, &LocationSettingsPrivate::recalculateLocationMode);
connect(q, &LocationSettings::hereStateChanged,
this, &LocationSettingsPrivate::recalculateLocationMode);
@@ -271,25 +280,28 @@
LocationSettings::LocationMode
LocationSettingsPrivate::calculateLocationMode() const
{
+ bool nls = m_mlsEnabled || m_yandexLocatorEnabled;
+ bool nls_available = mlsAvailable() || yandexLocatorAvailable();
+
if (m_gpsEnabled
- && (!mlsAvailable() ||
- (m_mlsEnabled && m_mlsOnlineState == LocationSettings::OnlineAGpsEnabled))
+ && (!nls_available ||
+ (nls && (m_mlsOnlineState == LocationSettings::OnlineAGpsEnabled || m_yandexLocatorOnlineState == LocationSettings::OnlineAGpsEnabled)))
&& (!hereAvailable() || m_hereState == LocationSettings::OnlineAGpsEnabled)) {
return LocationSettings::HighAccuracyMode;
} else if (!m_gpsEnabled
- && (!mlsAvailable() ||
- (m_mlsEnabled &&
- (m_mlsOnlineState == LocationSettings::OnlineAGpsEnabled
- || m_mlsOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted)))
+ && (!nls_available ||
+ (nls &&
+ ((m_mlsOnlineState == LocationSettings::OnlineAGpsEnabled || m_yandexLocatorOnlineState == LocationSettings::OnlineAGpsEnabled )
+ || (m_mlsOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted || m_yandexLocatorOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted))))
&& (!hereAvailable() ||
(m_hereState == LocationSettings::OnlineAGpsEnabled
|| m_hereState == LocationSettings::OnlineAGpsAgreementNotAccepted))) {
return LocationSettings::BatterySavingMode;
} else if (m_gpsEnabled
- && (!mlsAvailable() ||
- (m_mlsEnabled &&
- (m_mlsOnlineState == LocationSettings::OnlineAGpsDisabled
- || m_mlsOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted)))
+ && (!nls_available ||
+ (nls &&
+ ((m_mlsOnlineState == LocationSettings::OnlineAGpsDisabled || m_yandexLocatorOnlineState == LocationSettings::OnlineAGpsDisabled)
+ ||(m_mlsOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted || m_yandexLocatorOnlineState == LocationSettings::OnlineAGpsAgreementNotAccepted))))
&& (!hereAvailable() ||
(m_hereState == LocationSettings::OnlineAGpsDisabled
|| m_hereState == LocationSettings::OnlineAGpsAgreementNotAccepted))) {
@@ -315,6 +327,11 @@
return QFile::exists(QStringLiteral("/usr/libexec/geoclue-mlsdb"));
}
+bool LocationSettingsPrivate::yandexLocatorAvailable() const
+{
+ return QFile::exists(QStringLiteral("/usr/libexec/geoclue-yandex"));
+}
+
bool LocationSettingsPrivate::hereAvailable() const
{
return QFile::exists(QStringLiteral("/usr/libexec/geoclue-here"));
@@ -409,6 +426,8 @@
return QFile::exists(QStringLiteral("/usr/libexec/geoclue-hybris"));
}
+/*Mozilla Location services*/
+
bool LocationSettings::mlsEnabled() const
{
Q_D(const LocationSettings);
@@ -448,6 +467,48 @@
return d->mlsAvailable();
}
+/*Yandex locator services*/
+
+bool LocationSettings::yandexLocatorEnabled() const
+{
+ Q_D(const LocationSettings);
+ return d->m_yandexLocatorEnabled;
+}
+
+void LocationSettings::setYandexLocatorEnabled(bool enabled)
+{
+ Q_D(LocationSettings);
+ if (enabled != d->m_yandexLocatorEnabled) {
+ d->m_yandexLocatorEnabled = enabled;
+ d->writeSettings();
+ emit yandexLocatorEnabledChanged();
+ }
+}
+
+LocationSettings::OnlineAGpsState LocationSettings::yandexLocatorOnlineState() const
+{
+ Q_D(const LocationSettings);
+ return d->m_yandexLocatorOnlineState;
+}
+
+void LocationSettings::setYandexLocatorOnlineState(LocationSettings::OnlineAGpsState state)
+{
+ Q_D(LocationSettings);
+ if (state == d->m_yandexLocatorOnlineState)
+ return;
+
+ d->m_yandexLocatorOnlineState = state;
+ d->writeSettings();
+ emit yandexLocatorOnlineStateChanged();
+}
+
+bool LocationSettings::yandexLocatorAvailable() const
+{
+ Q_D(const LocationSettings);
+ return d->yandexLocatorAvailable();
+}
+
+/*HERE*/
LocationSettings::OnlineAGpsState LocationSettings::hereState() const
{
Q_D(const LocationSettings);
@@ -498,6 +559,12 @@
setMlsOnlineState(LocationSettings::OnlineAGpsEnabled);
}
}
+ if (yandexLocatorAvailable()) {
+ setYandexLocatorEnabled(true);
+ if (yandexLocatorOnlineState() != LocationSettings::OnlineAGpsAgreementNotAccepted) {
+ setYandexLocatorOnlineState(LocationSettings::OnlineAGpsEnabled);
+ }
+ }
if (hereAvailable()) {
if (hereState() != LocationSettings::OnlineAGpsAgreementNotAccepted) {
setHereState(LocationSettings::OnlineAGpsEnabled);
@@ -511,6 +578,12 @@
setMlsOnlineState(LocationSettings::OnlineAGpsEnabled);
}
}
+ if (yandexLocatorAvailable()) {
+ setYandexLocatorEnabled(true);
+ if (yandexLocatorOnlineState() != LocationSettings::OnlineAGpsAgreementNotAccepted) {
+ setYandexLocatorOnlineState(LocationSettings::OnlineAGpsEnabled);
+ }
+ }
if (hereAvailable()) {
if (hereState() != LocationSettings::OnlineAGpsAgreementNotAccepted) {
setHereState(LocationSettings::OnlineAGpsEnabled);
@@ -524,6 +597,12 @@
setMlsOnlineState(LocationSettings::OnlineAGpsDisabled);
}
}
+ if (yandexLocatorAvailable()) {
+ setYandexLocatorEnabled(true);
+ if (yandexLocatorOnlineState() != LocationSettings::OnlineAGpsAgreementNotAccepted) {
+ setYandexLocatorOnlineState(LocationSettings::OnlineAGpsDisabled);
+ }
+ }
if (hereAvailable()) {
if (hereState() != LocationSettings::OnlineAGpsAgreementNotAccepted) {
setHereState(LocationSettings::OnlineAGpsDisabled);
@@ -561,6 +640,7 @@
bool oldMlsEnabled = false;
bool oldHereEnabled = false;
bool oldHereAgreementAccepted = false;
+ bool oldYandexLocatorEnabled = false;
// current key values
bool locationEnabled = false;
@@ -569,6 +649,10 @@
bool mlsEnabled = false;
bool mlsAgreementAccepted = false;
bool mlsOnlineEnabled = false;
+ bool yandexLocatorEnabled = false;
+ bool yandexLocatorAgreementAccepted = false;
+ bool yandexLocatorOnlineEnabled = false;
+
bool hereEnabled = false;
bool hereAgreementAccepted = false;
@@ -595,6 +679,9 @@
ini.readBool(LocationSettingsSection, LocationSettingsMlsEnabledKey, &mlsEnabled, oldMlsEnabled);
ini.readBool(LocationSettingsSection, LocationSettingsMlsAgreementAcceptedKey, &mlsAgreementAccepted);
ini.readBool(LocationSettingsSection, LocationSettingsMlsOnlineEnabledKey, &mlsOnlineEnabled);
+ ini.readBool(LocationSettingsSection, LocationSettingsYandexLocatorEnabledKey, &yandexLocatorEnabled, oldYandexLocatorEnabled);
+ ini.readBool(LocationSettingsSection, LocationSettingsYandexLocatorAgreementAcceptedKey, &yandexLocatorAgreementAccepted);
+ ini.readBool(LocationSettingsSection, LocationSettingsYandexLocatorOnlineEnabledKey, &yandexLocatorOnlineEnabled);
ini.readBool(LocationSettingsSection, LocationSettingsHereEnabledKey, &hereEnabled, oldHereEnabled);
ini.readBool(LocationSettingsSection, LocationSettingsHereAgreementAcceptedKey, &hereAgreementAccepted, oldHereAgreementAccepted);
@@ -639,6 +726,11 @@
emit q->mlsEnabledChanged();
}
+ if (m_yandexLocatorEnabled != yandexLocatorEnabled) {
+ m_yandexLocatorEnabled = yandexLocatorEnabled;
+ emit q->yandexLocatorEnabledChanged();
+ }
+
LocationSettings::OnlineAGpsState mlsOnlineState = mlsAgreementAccepted
? ((mlsOnlineEnabled && m_mlsEnabled) ? LocationSettings::OnlineAGpsEnabled : LocationSettings::OnlineAGpsDisabled)
: LocationSettings::OnlineAGpsAgreementNotAccepted;
@@ -647,6 +739,14 @@
emit q->mlsOnlineStateChanged();
}
+ LocationSettings::OnlineAGpsState yandexLocatorOnlineState = yandexLocatorAgreementAccepted
+ ? ((yandexLocatorOnlineEnabled && m_yandexLocatorEnabled) ? LocationSettings::OnlineAGpsEnabled : LocationSettings::OnlineAGpsDisabled)
+ : LocationSettings::OnlineAGpsAgreementNotAccepted;
+ if (m_yandexLocatorOnlineState != yandexLocatorOnlineState) {
+ m_yandexLocatorOnlineState = yandexLocatorOnlineState;
+ emit q->yandexLocatorOnlineStateChanged();
+ }
+
if ((m_locationMode == LocationSettings::CustomMode) != customMode) {
if (customMode) {
m_locationMode = LocationSettings::CustomMode;
@@ -671,13 +771,16 @@
}
// set the available location providers value based upon the enabled providers
- QString agps_providers;
- if (m_mlsEnabled && m_hereState == LocationSettings::OnlineAGpsEnabled) {
- agps_providers = QStringLiteral("\"mls,here\"");
- } else if (m_mlsEnabled) {
- agps_providers = QStringLiteral("\"mls\"");
- } else if (m_hereState == LocationSettings::OnlineAGpsEnabled) {
- agps_providers = QStringLiteral("\"here\"");
+ QStringList agps_providers;
+
+ if (m_mlsEnabled) {
+ agps_providers.append("mls");
+ }
+ if (m_hereState == LocationSettings::OnlineAGpsEnabled) {
+ agps_providers.append("here");
+ }
+ if (m_yandexLocatorEnabled) {
+ agps_providers.append("yandex");
}
// write the values to the conf file
@@ -696,12 +799,15 @@
ini.writeBool(LocationSettingsSection, LocationSettingsMlsEnabledKey, m_mlsEnabled);
ini.writeBool(LocationSettingsSection, LocationSettingsMlsAgreementAcceptedKey, m_mlsOnlineState != LocationSettings::OnlineAGpsAgreementNotAccepted);
ini.writeBool(LocationSettingsSection, LocationSettingsMlsOnlineEnabledKey, m_mlsOnlineState == LocationSettings::OnlineAGpsEnabled);
+ ini.writeBool(LocationSettingsSection, LocationSettingsYandexLocatorEnabledKey, m_yandexLocatorEnabled);
+ ini.writeBool(LocationSettingsSection, LocationSettingsYandexLocatorAgreementAcceptedKey, m_yandexLocatorOnlineState != LocationSettings::OnlineAGpsAgreementNotAccepted);
+ ini.writeBool(LocationSettingsSection, LocationSettingsYandexLocatorOnlineEnabledKey, m_yandexLocatorOnlineState == LocationSettings::OnlineAGpsEnabled);
ini.writeBool(LocationSettingsSection, LocationSettingsHereEnabledKey, m_hereState == LocationSettings::OnlineAGpsEnabled);
ini.writeBool(LocationSettingsSection, LocationSettingsHereAgreementAcceptedKey, m_hereState != LocationSettings::OnlineAGpsAgreementNotAccepted);
ini.writeBool(LocationSettingsSection, LocationSettingsHereOnlineEnabledKey, m_hereState == LocationSettings::OnlineAGpsEnabled);
// write the available location providers based on the enabled plugins
- ini.writeString(LocationSettingsSection, LocationSettingsAgpsProvidersKey, agps_providers);
+ ini.writeString(LocationSettingsSection, LocationSettingsAgpsProvidersKey, "\""+agps_providers.join(",")+"\"");
// write the MDM allowed allowed data source keys
for (QMap<LocationSettings::DataSource, QString>::const_iterator
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/locationsettings.h
^
|
@@ -58,6 +58,10 @@
Q_PROPERTY(OnlineAGpsState mlsOnlineState READ mlsOnlineState WRITE setMlsOnlineState NOTIFY mlsOnlineStateChanged)
Q_PROPERTY(bool mlsAvailable READ mlsAvailable CONSTANT)
+ Q_PROPERTY(bool yandexLocatorEnabled READ yandexLocatorEnabled WRITE setYandexLocatorEnabled NOTIFY yandexLocatorEnabledChanged)
+ Q_PROPERTY(OnlineAGpsState yandexLocatorOnlineState READ yandexLocatorOnlineState WRITE setYandexLocatorOnlineState NOTIFY yandexLocatorOnlineStateChanged)
+ Q_PROPERTY(bool yandexLocatorAvailable READ yandexLocatorAvailable CONSTANT)
+
Q_PROPERTY(LocationMode locationMode READ locationMode WRITE setLocationMode NOTIFY locationModeChanged)
Q_PROPERTY(DataSources allowedDataSources READ allowedDataSources WRITE setAllowedDataSources NOTIFY allowedDataSourcesChanged)
@@ -100,6 +104,12 @@
void setMlsOnlineState(OnlineAGpsState state);
bool mlsAvailable() const;
+ bool yandexLocatorEnabled() const;
+ void setYandexLocatorEnabled(bool enabled);
+ OnlineAGpsState yandexLocatorOnlineState() const;
+ void setYandexLocatorOnlineState(OnlineAGpsState state);
+ bool yandexLocatorAvailable() const;
+
enum LocationMode {
HighAccuracyMode,
BatterySavingMode,
@@ -144,6 +154,8 @@
void gpsFlightModeChanged();
void mlsEnabledChanged();
void mlsOnlineStateChanged();
+ void yandexLocatorEnabledChanged();
+ void yandexLocatorOnlineStateChanged();
void locationModeChanged();
void allowedDataSourcesChanged();
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/locationsettings_p.h
^
|
@@ -62,13 +62,16 @@
void writeSettings();
bool mlsAvailable() const;
+ bool yandexLocatorAvailable() const;
bool hereAvailable() const;
QFileSystemWatcher m_watcher;
bool m_locationEnabled;
bool m_gpsEnabled;
bool m_mlsEnabled;
+ bool m_yandexLocatorEnabled;
LocationSettings::OnlineAGpsState m_mlsOnlineState;
+ LocationSettings::OnlineAGpsState m_yandexLocatorOnlineState;
LocationSettings::OnlineAGpsState m_hereState;
LocationSettings::LocationMode m_locationMode;
bool m_settingLocationMode;
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/plugin/plugin.cpp
^
|
@@ -47,13 +47,14 @@
#include "diskusage.h"
#include "partitionmodel.h"
#include "certificatemodel.h"
-#include "vpnmodel.h"
+#include "settingsvpnmodel.h"
#include "locationsettings.h"
#include "deviceinfo.h"
-static QObject *vpnmodel_api_factory(QQmlEngine *, QJSEngine *)
+template<class T>
+static QObject *api_factory(QQmlEngine *, QJSEngine *)
{
- return new VpnModel;
+ return new T;
}
class SystemSettingsPlugin : public QQmlExtensionPlugin
@@ -82,7 +83,7 @@
qRegisterMetaType<Partition>("Partition");
qmlRegisterType<DeveloperModeSettings>(uri, 1, 0, "DeveloperModeSettings");
qmlRegisterType<CertificateModel>(uri, 1, 0, "CertificateModel");
- qmlRegisterSingletonType<VpnModel>(uri, 1, 0, "VpnModel", vpnmodel_api_factory);
+ qmlRegisterSingletonType<SettingsVpnModel>(uri, 1, 0, "SettingsVpnModel", api_factory<SettingsVpnModel>);
qRegisterMetaType<DeveloperModeSettings::Status>("DeveloperModeSettings::Status");
qmlRegisterType<BatteryStatus>(uri, 1, 0, "BatteryStatus");
qmlRegisterType<DiskUsage>(uri, 1, 0, "DiskUsage");
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/plugin/plugins.qmltypes
^
|
@@ -19,6 +19,7 @@
Property { name: "localizedOperatingSystemName"; type: "string"; isReadonly: true }
Property { name: "baseOperatingSystemName"; type: "string"; isReadonly: true }
Property { name: "operatingSystemName"; type: "string"; isReadonly: true }
+ Property { name: "localizedSoftwareVersion"; type: "string"; isReadonly: true }
Property { name: "softwareVersion"; type: "string"; isReadonly: true }
Property { name: "softwareVersionId"; type: "string"; isReadonly: true }
Property { name: "adaptationVersion"; type: "string"; isReadonly: true }
@@ -371,53 +372,13 @@
Property { name: "mlsEnabled"; type: "bool" }
Property { name: "mlsOnlineState"; type: "OnlineAGpsState" }
Property { name: "mlsAvailable"; type: "bool"; isReadonly: true }
+ Property { name: "yandexLocatorEnabled"; type: "bool" }
+ Property { name: "yandexLocatorOnlineState"; type: "OnlineAGpsState" }
+ Property { name: "yandexLocatorAvailable"; type: "bool"; isReadonly: true }
Property { name: "locationMode"; type: "LocationMode" }
Property { name: "allowedDataSources"; type: "DataSources" }
}
Component {
- name: "ObjectListModel"
- prototype: "QAbstractListModel"
- Property { name: "automaticRoles"; type: "bool" }
- Property { name: "populated"; type: "bool" }
- Property { name: "count"; type: "int"; isReadonly: true }
- Signal {
- name: "itemAdded"
- Parameter { name: "item"; type: "QObject"; isPointer: true }
- }
- Signal {
- name: "itemRemoved"
- Parameter { name: "item"; type: "QObject"; isPointer: true }
- }
- Method {
- name: "insertItem"
- Parameter { name: "index"; type: "int" }
- Parameter { name: "item"; type: "QObject"; isPointer: true }
- }
- Method {
- name: "appendItem"
- Parameter { name: "item"; type: "QObject"; isPointer: true }
- }
- Method {
- name: "removeItem"
- Parameter { name: "item"; type: "QObject"; isPointer: true }
- }
- Method {
- name: "removeItemAt"
- Parameter { name: "index"; type: "int" }
- }
- Method { name: "clear" }
- Method {
- name: "get"
- type: "QObject*"
- Parameter { name: "index"; type: "int" }
- }
- Method {
- name: "indexOf"
- type: "int"
- Parameter { name: "item"; type: "QObject"; isPointer: true }
- }
- }
- Component {
name: "PartitionModel"
prototype: "QAbstractListModel"
exports: ["org.nemomobile.systemsettings/PartitionModel 1.0"]
@@ -495,6 +456,7 @@
Property { name: "count"; type: "int"; isReadonly: true }
Property { name: "storageTypes"; type: "StorageTypes" }
Property { name: "supportedFormatTypes"; type: "QStringList"; isReadonly: true }
+ Property { name: "externalStoragesPopulated"; type: "bool"; isReadonly: true }
Signal {
name: "errorMessage"
Parameter { name: "objectPath"; type: "string" }
@@ -690,29 +652,24 @@
}
}
Component {
- name: "VpnModel"
- prototype: "ObjectListModel"
- exports: ["org.nemomobile.systemsettings/VpnModel 1.0"]
+ name: "SettingsVpnModel"
+ prototype: "VpnModel"
+ exports: ["org.nemomobile.systemsettings/SettingsVpnModel 1.0"]
isCreatable: false
isSingleton: true
exportMetaObjectRevisions: [0]
- Enum {
- name: "ConnectionState"
- values: {
- "Idle": 0,
- "Failure": 1,
- "Configuration": 2,
- "Ready": 3,
- "Disconnect": 4
- }
- }
- Property { name: "bestState"; type: "int"; isReadonly: true }
+ Property { name: "bestState"; type: "VpnConnection::ConnectionState"; isReadonly: true }
Property { name: "autoConnect"; type: "bool"; isReadonly: true }
Property { name: "orderByConnected"; type: "bool" }
Signal {
name: "connectionStateChanged"
Parameter { name: "path"; type: "string" }
- Parameter { name: "state"; type: "int" }
+ Parameter { name: "state"; type: "VpnConnection::ConnectionState" }
+ }
+ Method {
+ name: "isDefaultDomain"
+ type: "bool"
+ Parameter { name: "domain"; type: "string" }
}
Method {
name: "createConnection"
@@ -765,5 +722,27 @@
Parameter { name: "path"; type: "string" }
Parameter { name: "type"; type: "string" }
}
+ Method {
+ name: "get"
+ type: "VpnConnection*"
+ Parameter { name: "index"; type: "int" }
+ }
+ }
+ Component {
+ name: "VpnModel"
+ prototype: "QAbstractListModel"
+ Property { name: "connected"; type: "bool"; isReadonly: true }
+ Property { name: "count"; type: "int"; isReadonly: true }
+ Property { name: "vpnManager"; type: "VpnManager"; isReadonly: true; isPointer: true }
+ Property { name: "populated"; type: "bool"; isReadonly: true }
+ Signal {
+ name: "connectedChanged"
+ Parameter { name: "connected"; type: "bool" }
+ }
+ Method {
+ name: "connectionSettings"
+ type: "QVariantMap"
+ Parameter { name: "path"; type: "string" }
+ }
}
}
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/settingsvpnmodel.cpp
^
|
@@ -0,0 +1,846 @@
+/*
+ * Copyright (c) 2016 - 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#include <QRegularExpression>
+#include <QStandardPaths>
+#include <QDataStream>
+#include <QCryptographicHash>
+#include <QQmlEngine>
+#include <QDir>
+#include "logging_p.h"
+#include "vpnmanager.h"
+
+#include "settingsvpnmodel.h"
+
+namespace {
+
+const auto defaultDomain = QStringLiteral("sailfishos.org");
+const auto legacyDefaultDomain(QStringLiteral("merproject.org"));
+
+int numericValue(VpnConnection::ConnectionState state)
+{
+ return (state == VpnConnection::Ready ? 3 :
+ (state == VpnConnection::Configuration ? 2 : 0));
+}
+
+VpnConnection::ConnectionState getMaxState(VpnConnection::ConnectionState newState, VpnConnection::ConnectionState oldState)
+{
+ if (numericValue(newState) > numericValue(oldState)) {
+ return newState;
+ }
+
+ return oldState;
+}
+
+} // end anonymous namespace
+
+SettingsVpnModel::SettingsVpnModel(QObject* parent)
+ : VpnModel(parent)
+ , credentials_(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/system/privileged/vpn-data"))
+ , bestState_(VpnConnection::Idle)
+ , autoConnect_(false)
+ , orderByConnected_(true)
+ , provisioningOutputPath_(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/system/privileged/vpn-provisioning"))
+ , roles(VpnModel::roleNames())
+{
+ VpnManager *manager = vpnManager();
+
+ roles.insert(ConnectedRole, "connected");
+
+ connect(manager, &VpnManager::connectionAdded, this, &SettingsVpnModel::connectionAdded, Qt::UniqueConnection);
+ connect(manager, &VpnManager::connectionRemoved, this, &SettingsVpnModel::connectionRemoved, Qt::UniqueConnection);
+ connect(manager, &VpnManager::connectionsRefreshed, this, &SettingsVpnModel::connectionsRefreshed, Qt::UniqueConnection);
+}
+
+SettingsVpnModel::~SettingsVpnModel()
+{
+ VpnManager *manager = vpnManager();
+
+ disconnect(manager, 0, this, 0);
+}
+
+void SettingsVpnModel::createConnection(const QVariantMap &createProperties)
+{
+ QVariantMap properties(createProperties);
+ const QString domain(properties.value(QString("domain")).toString());
+ if (domain.isEmpty()) {
+ properties.insert(QString("domain"), QVariant::fromValue(createDefaultDomain()));
+ }
+
+ vpnManager()->createConnection(properties);
+}
+
+QHash<int, QByteArray> SettingsVpnModel::roleNames() const
+{
+ return roles;
+}
+
+QVariant SettingsVpnModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid() && index.row() >= 0 && index.row() < connections().count()) {
+ switch (role) {
+ case ConnectedRole:
+ return QVariant::fromValue((bool)connections().at(index.row())->connected());
+ default:
+ return VpnModel::data(index, role);
+ }
+ }
+
+ return QVariant();
+}
+
+VpnConnection::ConnectionState SettingsVpnModel::bestState() const
+{
+ return bestState_;
+}
+
+bool SettingsVpnModel::autoConnect() const
+{
+ return autoConnect_;
+}
+
+bool SettingsVpnModel::orderByConnected() const
+{
+ return orderByConnected_;
+}
+
+void SettingsVpnModel::setOrderByConnected(bool orderByConnected)
+{
+ if (orderByConnected != orderByConnected_) {
+ orderByConnected_ = orderByConnected;
+ VpnModel::connectionsChanged();
+ emit orderByConnectedChanged();
+ }
+}
+
+void SettingsVpnModel::modifyConnection(const QString &path, const QVariantMap &properties)
+{
+ VpnConnection *conn = vpnManager()->connection(path);
+ if (conn) {
+ QVariantMap updatedProperties(properties);
+ const QString domain(updatedProperties.value(QString("domain")).toString());
+
+ if (domain.isEmpty()) {
+ if (isDefaultDomain(conn->domain())) {
+ // The connection already has a default domain, no need to change it
+ updatedProperties.remove("domain");
+ }
+ else {
+ updatedProperties.insert(QString("domain"), QVariant::fromValue(createDefaultDomain()));
+ }
+ }
+
+ const QString location(CredentialsRepository::locationForObjectPath(path));
+ const bool couldStoreCredentials(credentials_.credentialsExist(location));
+ const bool canStoreCredentials(properties.value(QString("storeCredentials")).toBool());
+
+ vpnManager()->modifyConnection(path, updatedProperties);
+
+ if (canStoreCredentials != couldStoreCredentials) {
+ if (canStoreCredentials) {
+ credentials_.storeCredentials(location, QVariantMap());
+ } else {
+ credentials_.removeCredentials(location);
+ }
+ }
+ }
+ else {
+ qCWarning(lcVpnLog) << "VPN connection modification failed: connection doesn't exist";
+ }
+}
+
+void SettingsVpnModel::deleteConnection(const QString &path)
+{
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ // Remove cached credentials
+ const QString location(CredentialsRepository::locationForObjectPath(path));
+ if (credentials_.credentialsExist(location)) {
+ credentials_.removeCredentials(location);
+ }
+
+ // Remove provisioned files
+ if (conn->type() == QStringLiteral("openvpn")) {
+ QVariantMap providerProperties = conn->providerProperties();
+ QStringList fileProperties;
+ fileProperties << QStringLiteral("OpenVPN.Cert") << QStringLiteral("OpenVPN.Key") << QStringLiteral("OpenVPN.CACert") << QStringLiteral("OpenVPN.ConfigFile");
+ for (const QString property : fileProperties) {
+ const QString filename = providerProperties.value(property).toString();
+
+ // Check if the file has been provisioned
+ if (filename.contains(provisioningOutputPath_)) {
+ int timesUsed = 0;
+
+ // Check the same file is not used by other connections
+ for (VpnConnection *c : connections()) {
+ if (filename == c->providerProperties().value(property).toString()) {
+ timesUsed++;
+ if (timesUsed > 1) {
+ break;
+ }
+ }
+ }
+
+ if (timesUsed > 1) {
+ qCInfo(lcVpnLog) << "VPN provisioning file kept, used by" << timesUsed << "connections.";
+ continue;
+ }
+
+ qCInfo(lcVpnLog) << "VPN provisioning file removed: " << filename;
+ if (!QFile::remove(filename)) {
+ qCWarning(lcVpnLog) << "VPN provisioning file could not be removed: " << filename;
+ }
+ }
+ }
+ }
+
+ vpnManager()->deleteConnection(path);
+ }
+
+}
+
+void SettingsVpnModel::activateConnection(const QString &path)
+{
+ vpnManager()->activateConnection(path);
+}
+
+void SettingsVpnModel::deactivateConnection(const QString &path)
+{
+ vpnManager()->deactivateConnection(path);
+}
+
+VpnConnection *SettingsVpnModel::get(int index) const
+{
+ if (index >= 0 && index < connections().size()) {
+ VpnConnection *item(connections().at(index));
+ QQmlEngine::setObjectOwnership(item, QQmlEngine::CppOwnership);
+ return item;
+ }
+
+ return 0;
+
+}
+
+// ==========================================================================
+// QAbstractListModel Ordering
+// ==========================================================================
+
+bool SettingsVpnModel::compareConnections(const VpnConnection *i, const VpnConnection *j)
+{
+ return ((orderByConnected_ && (i->connected() > j->connected()))
+ || ((!orderByConnected_ || (i->connected() == j->connected()))
+ && (i->name().localeAwareCompare(j->name()) <= 0)));
+}
+
+void SettingsVpnModel::orderConnections(QVector<VpnConnection*> &connections)
+{
+ std::sort(connections.begin(), connections.end(), [this](const VpnConnection *i, const VpnConnection *j) -> bool {
+ // Return true if i should appear before j in the list
+ return compareConnections(i, j);
+ });
+}
+
+void SettingsVpnModel::reorderConnection(VpnConnection * conn)
+{
+ const int itemCount(connections().size());
+
+ if (itemCount > 1) {
+ int index = 0;
+ for ( ; index < itemCount; ++index) {
+ const VpnConnection *existing = connections().at(index);
+ // Scenario 1 orderByConnected == true: order first by connected, second by name
+ // Scenario 2 orderByConnected == false: order only by name
+ if (!compareConnections(existing, conn)) {
+ break;
+ }
+ }
+ const int currentIndex = connections().indexOf(conn);
+ if (index != currentIndex && (index - 1) != currentIndex) {
+ moveItem(currentIndex, (currentIndex < index ? (index - 1) : index));
+ }
+ }
+}
+
+void SettingsVpnModel::updatedConnectionPosition()
+{
+ VpnConnection *conn = qobject_cast<VpnConnection *>(sender());
+ reorderConnection(conn);
+}
+
+void SettingsVpnModel::connectedChanged()
+{
+ VpnConnection *conn = qobject_cast<VpnConnection *>(sender());
+
+ int row = connections().indexOf(conn);
+ if (row >= 0) {
+ QModelIndex index = createIndex(row, 0);;
+ emit dataChanged(index, index);
+ }
+ reorderConnection(conn);
+}
+
+void SettingsVpnModel::connectionAdded(const QString &path)
+{
+ qCDebug(lcVpnLog) << "VPN connection added";
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ bool credentialsExist = credentials_.credentialsExist(CredentialsRepository::locationForObjectPath(path));
+ conn->setStoreCredentials(credentialsExist);
+
+ connect(conn, &VpnConnection::nameChanged, this, &SettingsVpnModel::updatedConnectionPosition, Qt::UniqueConnection);
+ connect(conn, &VpnConnection::connectedChanged, this, &SettingsVpnModel::connectedChanged, Qt::UniqueConnection);
+ connect(conn, &VpnConnection::stateChanged, this, &SettingsVpnModel::stateChanged, Qt::UniqueConnection);
+ }
+}
+
+void SettingsVpnModel::connectionRemoved(const QString &path)
+{
+ qCDebug(lcVpnLog) << "VPN connection removed";
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ disconnect(conn, 0, this, 0);
+ }
+}
+
+void SettingsVpnModel::connectionsRefreshed()
+{
+ qCDebug(lcVpnLog) << "VPN connections refreshed";
+ QVector<VpnConnection*> connections = vpnManager()->connections();
+
+ // Check to see if the best state has changed
+ VpnConnection::ConnectionState maxState = VpnConnection::Idle;
+ for (VpnConnection *conn : connections) {
+ connect(conn, &VpnConnection::nameChanged, this, &SettingsVpnModel::updatedConnectionPosition, Qt::UniqueConnection);
+ connect(conn, &VpnConnection::connectedChanged, this, &SettingsVpnModel::connectedChanged, Qt::UniqueConnection);
+ connect(conn, &VpnConnection::stateChanged, this, &SettingsVpnModel::stateChanged, Qt::UniqueConnection);
+
+ maxState = getMaxState(conn->state(), maxState);
+ }
+
+ updateBestState(maxState);
+}
+
+void SettingsVpnModel::stateChanged()
+{
+ // Emit the state changed signal needed for the VPN EnableSwitch
+ VpnConnection *conn = qobject_cast<VpnConnection *>(sender());
+ emit connectionStateChanged(conn->path(), conn->state());
+
+ // Check to see if the best state has changed
+ VpnConnection::ConnectionState maxState = getMaxState(conn->state(), VpnConnection::Idle);
+ updateBestState(maxState);
+}
+
+// ==========================================================================
+// Automatic domain allocation
+// ==========================================================================
+
+bool SettingsVpnModel::domainInUse(const QString &domain) const
+{
+ const int itemCount(count());
+ for (int index = 0; index < itemCount; ++index) {
+ const VpnConnection *connection = connections().at(index);
+ if (connection->domain() == domain) {
+ return true;
+ }
+ }
+ return false;
+}
+
+QString SettingsVpnModel::createDefaultDomain() const
+{
+ QString newDomain = defaultDomain;
+ int index = 1;
+ while (domainInUse(newDomain)) {
+ newDomain = defaultDomain + QString(".%1").arg(index);
+ ++index;
+ }
+ return newDomain;
+}
+
+bool SettingsVpnModel::isDefaultDomain(const QString &domain)
+{
+ if (domain == legacyDefaultDomain)
+ return true;
+
+ static const QRegularExpression domainPattern(QStringLiteral("^%1(\\.\\d+)?$").arg(defaultDomain));
+ return domainPattern.match(domain).hasMatch();
+}
+
+// ==========================================================================
+// Credential storage
+// ==========================================================================
+
+QVariantMap SettingsVpnModel::connectionCredentials(const QString &path)
+{
+ QVariantMap rv;
+
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ const QString location(CredentialsRepository::locationForObjectPath(path));
+ const bool enabled(credentials_.credentialsExist(location));
+
+ if (enabled) {
+ rv = credentials_.credentials(location);
+ } else {
+ qWarning() << "VPN does not permit credentials storage:" << path;
+ }
+
+ conn->setStoreCredentials(enabled);
+ } else {
+ qWarning() << "Unable to return credentials for unknown VPN connection:" << path;
+ }
+
+ return rv;
+}
+
+void SettingsVpnModel::setConnectionCredentials(const QString &path, const QVariantMap &credentials)
+{
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ credentials_.storeCredentials(CredentialsRepository::locationForObjectPath(path), credentials);
+
+ conn->setStoreCredentials(true);
+ } else {
+ qWarning() << "Unable to set credentials for unknown VPN connection:" << path;
+ }
+}
+
+bool SettingsVpnModel::connectionCredentialsEnabled(const QString &path)
+{
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ const QString location(CredentialsRepository::locationForObjectPath(path));
+ const bool enabled(credentials_.credentialsExist(location));
+
+ conn->setStoreCredentials(enabled);
+ return enabled;
+ } else {
+ qWarning() << "Unable to test credentials storage for unknown VPN connection:" << path;
+ }
+
+ return false;
+}
+
+void SettingsVpnModel::disableConnectionCredentials(const QString &path)
+{
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ const QString location(CredentialsRepository::locationForObjectPath(path));
+ if (credentials_.credentialsExist(location)) {
+ credentials_.removeCredentials(location);
+ }
+
+ conn->setStoreCredentials(false);
+ } else {
+ qWarning() << "Unable to set automatic connection for unknown VPN connection:" << path;
+ }
+}
+
+QVariantMap SettingsVpnModel::connectionSettings(const QString &path)
+{
+ QVariantMap properties;
+ if (VpnConnection *conn = vpnManager()->connection(path)) {
+ // Check if the credentials storage has been changed
+ const QString location(CredentialsRepository::locationForObjectPath(path));
+ conn->setStoreCredentials(credentials_.credentialsExist(location));
+
+ properties = VpnModel::connectionSettings(path);
+ }
+ return properties;
+}
+
+// ==========================================================================
+// CredentialsRepository
+// ==========================================================================
+
+SettingsVpnModel::CredentialsRepository::CredentialsRepository(const QString &path)
+ : baseDir_(path)
+{
+ if (!baseDir_.exists() && !baseDir_.mkpath(path)) {
+ qWarning() << "Unable to create base directory for VPN credentials:" << path;
+ }
+}
+
+QString SettingsVpnModel::CredentialsRepository::locationForObjectPath(const QString &path)
+{
+ int index = path.lastIndexOf(QChar('/'));
+ if (index != -1) {
+ return path.mid(index + 1);
+ }
+
+ return QString();
+}
+
+bool SettingsVpnModel::CredentialsRepository::credentialsExist(const QString &location) const
+{
+ // Test the FS, as another process may store/remove the credentials
+ return baseDir_.exists(location);
+}
+
+bool SettingsVpnModel::CredentialsRepository::storeCredentials(const QString &location, const QVariantMap &credentials)
+{
+ QFile credentialsFile(baseDir_.absoluteFilePath(location));
+ if (!credentialsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ qWarning() << "Unable to write credentials file:" << credentialsFile.fileName();
+ return false;
+ } else {
+ credentialsFile.write(encodeCredentials(credentials));
+ credentialsFile.setPermissions(QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ReadOther | QFileDevice::WriteOther);
+ credentialsFile.close();
+ }
+
+ return true;
+}
+
+bool SettingsVpnModel::CredentialsRepository::removeCredentials(const QString &location)
+{
+ if (baseDir_.exists(location)) {
+ if (!baseDir_.remove(location)) {
+ qWarning() << "Unable to delete credentials file:" << location;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QVariantMap SettingsVpnModel::CredentialsRepository::credentials(const QString &location) const
+{
+ QVariantMap rv;
+
+ QFile credentialsFile(baseDir_.absoluteFilePath(location));
+ if (!credentialsFile.open(QIODevice::ReadOnly)) {
+ qWarning() << "Unable to read credentials file:" << credentialsFile.fileName();
+ } else {
+ const QByteArray encoded = credentialsFile.readAll();
+ credentialsFile.close();
+
+ rv = decodeCredentials(encoded);
+ }
+
+ return rv;
+}
+
+QByteArray SettingsVpnModel::CredentialsRepository::encodeCredentials(const QVariantMap &credentials)
+{
+ // We can't store these values securely, but we may as well encode them to protect from grep, at least...
+ QByteArray encoded;
+
+ QDataStream os(&encoded, QIODevice::WriteOnly);
+ os.setVersion(QDataStream::Qt_5_6);
+
+ const quint32 version = 1u;
+ os << version;
+
+ const quint32 items = credentials.size();
+ os << items;
+
+ for (auto it = credentials.cbegin(), end = credentials.cend(); it != end; ++it) {
+ os << it.key();
+ os << it.value().toString();
+ }
+
+ return encoded.toBase64();
+}
+
+QVariantMap SettingsVpnModel::CredentialsRepository::decodeCredentials(const QByteArray &encoded)
+{
+ QVariantMap rv;
+
+ QByteArray decoded(QByteArray::fromBase64(encoded));
+
+ QDataStream is(decoded);
+ is.setVersion(QDataStream::Qt_5_6);
+
+ quint32 version;
+ is >> version;
+
+ if (version != 1u) {
+ qWarning() << "Invalid version for stored credentials:" << version;
+ } else {
+ quint32 items;
+ is >> items;
+
+ for (quint32 i = 0; i < items; ++i) {
+ QString key, value;
+ is >> key;
+ is >> value;
+ rv.insert(key, QVariant::fromValue(value));
+ }
+ }
+
+ return rv;
+}
+
+// ==========================================================================
+// Provisioning files
+// ==========================================================================
+
+QVariantMap SettingsVpnModel::processProvisioningFile(const QString &path, const QString &type)
+{
+ QVariantMap rv;
+
+ QFile provisioningFile(path);
+ if (provisioningFile.open(QIODevice::ReadOnly)) {
+ if (type == QString("openvpn")) {
+ rv = processOpenVpnProvisioningFile(provisioningFile);
+ } else {
+ qWarning() << "Provisioning not currently supported for VPN type:" << type;
+ }
+ } else {
+ qWarning() << "Unable to open provisioning file:" << path;
+ }
+
+ return rv;
+}
+
+QVariantMap SettingsVpnModel::processOpenVpnProvisioningFile(QFile &provisioningFile)
+{
+ QVariantMap rv;
+
+ QString embeddedMarker;
+ QString embeddedContent;
+ QStringList extraOptions;
+
+ const QRegularExpression commentLeader(QStringLiteral("^\\s*(?:\\#|\\;)"));
+ const QRegularExpression embeddedLeader(QStringLiteral("^\\s*<([^\\/>]+)>"));
+ const QRegularExpression embeddedTrailer(QStringLiteral("^\\s*<\\/([^\\/>]+)>"));
+ const QRegularExpression whitespace(QStringLiteral("\\s"));
+
+ auto normaliseProtocol = [](const QString &proto) {
+ if (proto == QStringLiteral("tcp")) {
+ // 'tcp' is an undocumented option, which is interpreted by openvpn as 'tcp-client'
+ return QStringLiteral("tcp-client");
+ }
+ return proto;
+ };
+
+ QTextStream is(&provisioningFile);
+ while (!is.atEnd()) {
+ QString line(is.readLine());
+
+ QRegularExpressionMatch match;
+ if (line.contains(commentLeader)) {
+ // Skip
+ } else if (line.contains(embeddedLeader, &match)) {
+ embeddedMarker = match.captured(1);
+ if (embeddedMarker.isEmpty()) {
+ qWarning() << "Invalid embedded content";
+ }
+ } else if (line.contains(embeddedTrailer, &match)) {
+ const QString marker = match.captured(1);
+ if (marker != embeddedMarker) {
+ qWarning() << "Invalid embedded content:" << marker << "!=" << embeddedMarker;
+ } else {
+ if (embeddedContent.isEmpty()) {
+ qWarning() << "Ignoring empty embedded content:" << embeddedMarker;
+ } else {
+ if (embeddedMarker == QStringLiteral("connection")) {
+ // Special case: not embedded content, but a <connection> structure - pass through as an extra option
+ extraOptions.append(QStringLiteral("<connection>\n") + embeddedContent + QStringLiteral("</connection>"));
+ } else {
+ // Embedded content
+ QDir outputDir(provisioningOutputPath_);
+ if (!outputDir.exists() && !outputDir.mkpath(provisioningOutputPath_)) {
+ qWarning() << "Unable to create base directory for VPN provisioning content:" << provisioningOutputPath_;
+ } else {
+ // Name the file according to content
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ hash.addData(embeddedContent.toUtf8());
+
+ const QString outputFileName(QString(hash.result().toHex()) + QChar('.') + embeddedMarker);
+ QFile outputFile(outputDir.absoluteFilePath(outputFileName));
+ if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ qWarning() << "Unable to write VPN provisioning content file:" << outputFile.fileName();
+ } else {
+ QTextStream os(&outputFile);
+ os << embeddedContent;
+
+ // Add the file to the configuration
+ if (embeddedMarker == QStringLiteral("ca")) {
+ rv.insert(QStringLiteral("OpenVPN.CACert"), outputFile.fileName());
+ } else if (embeddedMarker == QStringLiteral("cert")) {
+ rv.insert(QStringLiteral("OpenVPN.Cert"), outputFile.fileName());
+ } else if (embeddedMarker == QStringLiteral("key")) {
+ rv.insert(QStringLiteral("OpenVPN.Key"), outputFile.fileName());
+ } else {
+ // Assume that the marker corresponds to the openvpn option, (such as 'tls-auth')
+ extraOptions.append(embeddedMarker + QChar(' ') + outputFile.fileName());
+ }
+ }
+ }
+ }
+ }
+ }
+ embeddedMarker.clear();
+ embeddedContent.clear();
+ } else if (!embeddedMarker.isEmpty()) {
+ embeddedContent.append(line + QStringLiteral("\n"));
+ } else {
+ QStringList tokens(line.split(whitespace, QString::SkipEmptyParts));
+ if (!tokens.isEmpty()) {
+ // Find directives that become part of the connman configuration
+ const QString& directive(tokens.front());
+ const QStringList arguments(tokens.count() > 1 ? tokens.mid(1) : QStringList());
+
+ if (directive == QStringLiteral("remote")) {
+ // Connman supports a single remote host - if we get further instances, pass them through the config file
+ if (!rv.contains(QStringLiteral("Host"))) {
+ if (arguments.count() > 0) {
+ rv.insert(QStringLiteral("Host"), arguments.at(0));
+ }
+ if (arguments.count() > 1) {
+ rv.insert(QStringLiteral("OpenVPN.Port"), arguments.at(1));
+ }
+ if (arguments.count() > 2) {
+ rv.insert(QStringLiteral("OpenVPN.Proto"), normaliseProtocol(arguments.at(2)));
+ }
+ } else {
+ extraOptions.append(line);
+ }
+ } else if (directive == QStringLiteral("ca") ||
+ directive == QStringLiteral("cert") ||
+ directive == QStringLiteral("key") ||
+ directive == QStringLiteral("auth-user-pass")) {
+ if (!arguments.isEmpty()) {
+ // If these file paths are not absolute, assume they are in the same directory as the provisioning file
+ QString file(arguments.at(0));
+ if (!file.startsWith(QChar('/'))) {
+ const QFileInfo info(provisioningFile.fileName());
+ file = info.dir().absoluteFilePath(file);
+ }
+ if (directive == QStringLiteral("ca")) {
+ rv.insert(QStringLiteral("OpenVPN.CACert"), file);
+ } else if (directive == QStringLiteral("cert")) {
+ rv.insert(QStringLiteral("OpenVPN.Cert"), file);
+ } else if (directive == QStringLiteral("key")) {
+ rv.insert(QStringLiteral("OpenVPN.Key"), file);
+ } else if (directive == QStringLiteral("auth-user-pass")) {
+ rv.insert(QStringLiteral("OpenVPN.AuthUserPass"), file);
+ }
+ } else if (directive == QStringLiteral("auth-user-pass")) {
+ // Preserve this option to mean ask for credentials
+ rv.insert(QStringLiteral("OpenVPN.AuthUserPass"), QStringLiteral("-"));
+ }
+ } else if (directive == QStringLiteral("mtu") ||
+ directive == QStringLiteral("tun-mtu")) {
+ // Connman appears to use a long obsolete form of this option...
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.MTU"), arguments.join(QChar(' ')));
+ }
+ } else if (directive == QStringLiteral("ns-cert-type")) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.NSCertType"), arguments.join(QChar(' ')));
+ }
+ } else if (directive == QStringLiteral("proto")) {
+ if (!arguments.isEmpty()) {
+ // All values from a 'remote' directive to take precedence
+ if (!rv.contains(QStringLiteral("OpenVPN.Proto"))) {
+ rv.insert(QStringLiteral("OpenVPN.Proto"), normaliseProtocol(arguments.join(QChar(' '))));
+ }
+ }
+ } else if (directive == QStringLiteral("port")) {
+ // All values from a 'remote' directive to take precedence
+ if (!rv.contains(QStringLiteral("OpenVPN.Port"))) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.Port"), arguments.join(QChar(' ')));
+ }
+ }
+ } else if (directive == QStringLiteral("askpass")) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.AskPass"), arguments.join(QChar(' ')));
+ } else {
+ rv.insert(QStringLiteral("OpenVPN.AskPass"), QString());
+ }
+ } else if (directive == QStringLiteral("auth-nocache")) {
+ rv.insert(QStringLiteral("OpenVPN.AuthNoCache"), QStringLiteral("true"));
+ } else if (directive == QStringLiteral("tls-remote")) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.TLSRemote"), arguments.join(QChar(' ')));
+ }
+ } else if (directive == QStringLiteral("cipher")) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.Cipher"), arguments.join(QChar(' ')));
+ }
+ } else if (directive == QStringLiteral("auth")) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.Auth"), arguments.join(QChar(' ')));
+ }
+ } else if (directive == QStringLiteral("comp-lzo")) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.CompLZO"), arguments.join(QChar(' ')));
+ } else {
+ rv.insert(QStringLiteral("OpenVPN.CompLZO"), QStringLiteral("adaptive"));
+ }
+ } else if (directive == QStringLiteral("remote-cert-tls")) {
+ if (!arguments.isEmpty()) {
+ rv.insert(QStringLiteral("OpenVPN.RemoteCertTls"), arguments.join(QChar(' ')));
+ }
+ } else {
+ // A directive that connman does not care about - pass through to the config file
+ extraOptions.append(line);
+ }
+ }
+ }
+ }
+
+ if (!extraOptions.isEmpty()) {
+ // Write a config file to contain the extra options
+ QDir outputDir(provisioningOutputPath_);
+ if (!outputDir.exists() && !outputDir.mkpath(provisioningOutputPath_)) {
+ qWarning() << "Unable to create base directory for VPN provisioning content:" << provisioningOutputPath_;
+ } else {
+ // Name the file according to content
+ QCryptographicHash hash(QCryptographicHash::Sha1);
+ foreach (const QString &line, extraOptions) {
+ hash.addData(line.toUtf8());
+ }
+
+ const QString outputFileName(QString(hash.result().toHex()) + QStringLiteral(".conf"));
+ QFile outputFile(outputDir.absoluteFilePath(outputFileName));
+ if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ qWarning() << "Unable to write VPN provisioning configuration file:" << outputFile.fileName();
+ } else {
+ QTextStream os(&outputFile);
+ foreach (const QString &line, extraOptions) {
+ os << line << endl;
+ }
+
+ rv.insert(QStringLiteral("OpenVPN.ConfigFile"), outputFile.fileName());
+ }
+ }
+ }
+
+ return rv;
+}
+
+void SettingsVpnModel::updateBestState(VpnConnection::ConnectionState maxState)
+{
+ if (bestState_ != maxState) {
+ bestState_ = maxState;
+ emit bestStateChanged();
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/settingsvpnmodel.h
^
|
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2016 - 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
+ *
+ * You may use this file under the terms of the BSD license as follows:
+ *
+ * "Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Nemo Mobile nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ */
+
+#ifndef SETTINGSVPNMODEL_H
+#define SETTINGSVPNMODEL_H
+
+#include <QObject>
+#include <QSet>
+#include <QDir>
+
+#include <vpnconnection.h>
+#include <vpnmodel.h>
+#include <systemsettingsglobal.h>
+
+class SYSTEMSETTINGS_EXPORT SettingsVpnModel : public VpnModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(VpnConnection::ConnectionState bestState READ bestState NOTIFY bestStateChanged)
+ Q_PROPERTY(bool autoConnect READ autoConnect NOTIFY autoConnectChanged)
+ Q_PROPERTY(bool orderByConnected READ orderByConnected WRITE setOrderByConnected NOTIFY orderByConnectedChanged)
+
+public:
+ SettingsVpnModel(QObject* parent = nullptr);
+ ~SettingsVpnModel() override;
+
+ enum ItemRoles {
+ ConnectedRole = VpnModel::VpnRole + 1
+ };
+
+ QHash<int, QByteArray> roleNames() const override;
+ QVariant data(const QModelIndex &index, int role) const override;
+
+ VpnConnection::ConnectionState bestState() const;
+ bool autoConnect() const;
+ bool orderByConnected() const;
+ void setOrderByConnected(bool orderByConnected);
+
+ Q_INVOKABLE static bool isDefaultDomain(const QString &domain);
+ Q_INVOKABLE void createConnection(const QVariantMap &properties);
+ Q_INVOKABLE void modifyConnection(const QString &path, const QVariantMap &properties);
+ Q_INVOKABLE void deleteConnection(const QString &path);
+
+ Q_INVOKABLE void activateConnection(const QString &path);
+ Q_INVOKABLE void deactivateConnection(const QString &path);
+
+ Q_INVOKABLE QVariantMap connectionCredentials(const QString &path);
+ Q_INVOKABLE void setConnectionCredentials(const QString &path, const QVariantMap &credentials);
+
+ Q_INVOKABLE bool connectionCredentialsEnabled(const QString &path);
+ Q_INVOKABLE void disableConnectionCredentials(const QString &path);
+
+ Q_INVOKABLE QVariantMap connectionSettings(const QString &path);
+
+ Q_INVOKABLE QVariantMap processProvisioningFile(const QString &path, const QString &type);
+
+ Q_INVOKABLE VpnConnection *get(int index) const;
+
+signals:
+ void bestStateChanged();
+ void autoConnectChanged();
+ void connectionStateChanged(const QString &path, VpnConnection::ConnectionState state);
+ void orderByConnectedChanged();
+
+private:
+ bool domainInUse(const QString &domain) const;
+ QString createDefaultDomain() const;
+ void reorderConnection(VpnConnection * conn);
+ virtual void orderConnections(QVector<VpnConnection*> &connections) override;
+ bool compareConnections(const VpnConnection *i, const VpnConnection *j);
+ QVariantMap processOpenVpnProvisioningFile(QFile &provisioningFile);
+ void updateBestState(VpnConnection::ConnectionState maxState);
+
+private Q_SLOTS:
+ void connectionAdded(const QString &path);
+ void connectionRemoved(const QString &path);
+ void connectionsRefreshed();
+ void updatedConnectionPosition();
+ void connectedChanged();
+ void stateChanged();
+
+private:
+ class CredentialsRepository
+ {
+ public:
+ CredentialsRepository(const QString &path);
+
+ static QString locationForObjectPath(const QString &path);
+
+ bool credentialsExist(const QString &location) const;
+
+ bool storeCredentials(const QString &location, const QVariantMap &credentials);
+ bool removeCredentials(const QString &location);
+
+ QVariantMap credentials(const QString &location) const;
+
+ static QByteArray encodeCredentials(const QVariantMap &credentials);
+ static QVariantMap decodeCredentials(const QByteArray &encoded);
+
+ private:
+ QDir baseDir_;
+ };
+
+ CredentialsRepository credentials_;
+ VpnConnection::ConnectionState bestState_;
+ // True if there's one VPN that has autoConnect true
+ bool autoConnect_;
+ bool orderByConnected_;
+ QString provisioningOutputPath_;
+ QHash<int, QByteArray> roles;
+};
+
+#endif // SETTINGSVPNMODEL_H
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/src.pro
^
|
@@ -10,9 +10,6 @@
PKGCONFIG += ssu-sysinfo nemodbus packagekitqt5
system(qdbusxml2cpp -p mceiface.h:mceiface.cpp mce.xml)
-system(qdbusxml2cpp -c ConnmanVpnProxy -p connmanvpnproxy ../dbus/net.connman.vpn.xml -i qdbusxml2cpp_dbus_types.h)
-system(qdbusxml2cpp -c ConnmanVpnConnectionProxy -p connmanvpnconnectionproxy ../dbus/net.connman.vpn.Connection.xml -i qdbusxml2cpp_dbus_types.h)
-system(qdbusxml2cpp -c ConnmanServiceProxy -p connmanserviceproxy ../dbus/net.connman.service.xml -i qdbusxml2cpp_dbus_types.h)
SOURCES += \
languagemodel.cpp \
@@ -25,10 +22,6 @@
displaysettings.cpp \
aboutsettings.cpp \
certificatemodel.cpp \
- vpnmodel.cpp \
- connmanserviceproxy.cpp \
- connmanvpnproxy.cpp \
- connmanvpnconnectionproxy.cpp \
developermodesettings.cpp \
batterystatus.cpp \
diskusage.cpp \
@@ -38,6 +31,7 @@
partitionmodel.cpp \
deviceinfo.cpp \
locationsettings.cpp \
+ settingsvpnmodel.cpp \
timezoneinfo.cpp \
udisks2block.cpp \
udisks2blockdevices.cpp \
@@ -53,12 +47,10 @@
displaysettings.h \
aboutsettings.h \
certificatemodel.h \
- vpnmodel.h \
- connmanserviceproxy.h \
- connmanvpnproxy.h \
- connmanvpnconnectionproxy.h \
+ settingsvpnmodel.h \
developermodesettings.h \
batterystatus.h \
+ udisks2block_p.h \
udisks2defines.h \
diskusage.h \
partition.h \
@@ -71,7 +63,7 @@
HEADERS += \
$$PUBLIC_HEADERS \
- qdbusxml2cpp_dbus_types.h \
+ aboutsettings_p.h \
localeconfig.h \
batterystatus_p.h \
logging_p.h \
@@ -80,7 +72,6 @@
logging_p.h \
partition_p.h \
partitionmanager_p.h \
- udisks2block_p.h \
udisks2blockdevices_p.h \
udisks2job_p.h \
udisks2monitor_p.h
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/udisks2block.cpp
^
|
@@ -294,6 +294,32 @@
return value(QStringLiteral("IdUUID")).toString();
}
+QStringList UDisks2::Block::symlinks() const
+{
+ QStringList links;
+ QVariant variantListBytes = value(QStringLiteral("Symlinks"));
+
+ if (variantListBytes.canConvert<QVariantList>()) {
+ QSequentialIterable iterable = variantListBytes.value<QSequentialIterable>();
+
+ for (const QVariant &a : iterable) {
+ QByteArray symlinkBytes;
+
+ if (a.canConvert<QVariantList>()) {
+ QSequentialIterable i = a.value<QSequentialIterable>();
+ for (const QVariant &variantByte : i) {
+ symlinkBytes.append(variantByte.toChar());
+ }
+ }
+
+ if (!symlinkBytes.isEmpty())
+ links << QString::fromLocal8Bit(symlinkBytes);
+ }
+ }
+
+ return links;
+}
+
QString UDisks2::Block::mountPath() const
{
return m_mountPath;
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/src/udisks2block_p.h
^
|
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2018 Jolla Ltd. <raine.makelainen@jolla.com>
+ * Copyright (c) 2018 - 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
@@ -38,6 +39,8 @@
#include <QPointer>
#include <functional>
+#include <systemsettingsglobal.h>
+
#include "udisks2defines.h"
class QDBusPendingCallWatcher;
@@ -45,12 +48,13 @@
namespace UDisks2 {
-class Block : public QObject
+class SYSTEMSETTINGS_EXPORT Block : public QObject
{
Q_OBJECT
Q_PROPERTY(QString connectionBus READ connectionBus NOTIFY updated)
public:
+ Block(const QString &path, const UDisks2::InterfacePropertyMap &interfacePropertyMap, QObject *parent = nullptr);
virtual ~Block();
QString path() const;
@@ -96,6 +100,8 @@
QString idLabel() const;
QString idUUID() const;
+ QStringList symlinks() const;
+
QString mountPath() const;
QVariant value(const QString &key) const;
@@ -119,7 +125,6 @@
void complete();
private:
- Block(const QString &path, const UDisks2::InterfacePropertyMap &interfacePropertyMap, QObject *parent = nullptr);
Block& operator=(const Block& other);
bool setEncrypted(bool encrypted);
|
[-]
[+]
|
Changed |
_service:tar_git:nemo-qml-plugin-systemsettings-0.5.34.op5.tar.bz2/tests/ut_diskusage.cpp
^
|
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2015 Jolla Ltd.
- * Contact: Thomas Perl <thomas.perl@jolla.com>
+ * Copyright (c) 2015 - 2019 Jolla Ltd.
+ * Copyright (c) 2019 Open Mobile Platform LLC.
*
* You may use this file under the terms of the BSD license as follows:
*
@@ -37,7 +37,7 @@
#include "ut_diskusage.h"
#include <QtTest>
-
+#include <QDir>
static QVariantMap g_mocked_file_size;
static QVariantMap g_mocked_rpm_size;
@@ -131,37 +131,37 @@
{
g_mocked_file_size["/"] = MB(1000);
g_mocked_file_size["/home/"] = MB(300);
- g_mocked_file_size["/home/nemo/"] = MB(150);
- g_mocked_file_size["/home/nemo/Documents/"] = MB(70);
+ g_mocked_file_size[QDir::homePath()] = MB(150);
+ g_mocked_file_size[QDir::homePath() + "/Documents/"] = MB(70);
QVariantMap usage = DiskUsageWorker().calculate(QStringList() <<
- "/" << "/home/" << "/home/nemo/" << "/home/nemo/Documents/");
+ "/" << "/home/" << QDir::homePath() << QDir::homePath() + "/Documents/");
UT_DISKUSAGE_EXPECT_SIZE("/", MB(1000) - MB(300))
UT_DISKUSAGE_EXPECT_SIZE("/home/", MB(300) - MB(150))
- UT_DISKUSAGE_EXPECT_SIZE("/home/nemo/", MB(150) - MB(70))
- UT_DISKUSAGE_EXPECT_SIZE("/home/nemo/Documents/", MB(70))
+ UT_DISKUSAGE_EXPECT_SIZE(QDir::homePath(), MB(150) - MB(70))
+ UT_DISKUSAGE_EXPECT_SIZE(QDir::homePath() + "/Documents/", MB(70))
}
void Ut_DiskUsage::testSubtractNestedSubdirectoryMulti()
{
g_mocked_file_size["/"] = MB(1000);
g_mocked_file_size["/home/"] = MB(300);
- g_mocked_file_size["/home/nemo/"] = MB(150);
- g_mocked_file_size["/home/nemo/Documents/"] = MB(70);
+ g_mocked_file_size[QDir::homePath()] = MB(150);
+ g_mocked_file_size[QDir::homePath() + "/Documents/"] = MB(70);
g_mocked_file_size["/opt/"] = MB(100);
g_mocked_file_size["/opt/foo/"] = MB(30);
g_mocked_file_size["/opt/foo/bar/"] = MB(20);
g_mocked_file_size["/opt/baz/"] = MB(10);
QVariantMap usage = DiskUsageWorker().calculate(QStringList() << "/" <<
- "/home/" << "/home/nemo/" << "/home/nemo/Documents/" <<
+ "/home/" << QDir::homePath() << QDir::homePath() + "/Documents/" <<
"/opt/" << "/opt/foo/" << "/opt/foo/bar/" << "/opt/baz/");
UT_DISKUSAGE_EXPECT_SIZE("/", MB(1000) - MB(300) - MB(100))
UT_DISKUSAGE_EXPECT_SIZE("/home/", MB(300) - MB(150))
- UT_DISKUSAGE_EXPECT_SIZE("/home/nemo/", MB(150) - MB(70))
- UT_DISKUSAGE_EXPECT_SIZE("/home/nemo/Documents/", MB(70))
+ UT_DISKUSAGE_EXPECT_SIZE(QDir::homePath(), MB(150) - MB(70))
+ UT_DISKUSAGE_EXPECT_SIZE(QDir::homePath() + "/Documents/", MB(70))
UT_DISKUSAGE_EXPECT_SIZE("/opt/", MB(100) - MB(30) - MB(10))
UT_DISKUSAGE_EXPECT_SIZE("/opt/foo/", MB(30) - MB(20))
UT_DISKUSAGE_EXPECT_SIZE("/opt/foo/bar/", MB(20))
|