From bdfb1592045fb6d99a5e6d32478e460aaac35146 Mon Sep 17 00:00:00 2001 From: Bart Ribbers Date: Fri, 1 May 2020 17:11:44 +0200 Subject: testing/nemo-qml-plugin-systemsettings: new aport --- .../0001-Remove-developer-mode.patch | 736 +++++++++++++++ .../0002-Remove-broken-certificatemodel.patch | 996 +++++++++++++++++++++ testing/nemo-qml-plugin-systemsettings/APKBUILD | 29 + 3 files changed, 1761 insertions(+) create mode 100644 testing/nemo-qml-plugin-systemsettings/0001-Remove-developer-mode.patch create mode 100644 testing/nemo-qml-plugin-systemsettings/0002-Remove-broken-certificatemodel.patch create mode 100644 testing/nemo-qml-plugin-systemsettings/APKBUILD diff --git a/testing/nemo-qml-plugin-systemsettings/0001-Remove-developer-mode.patch b/testing/nemo-qml-plugin-systemsettings/0001-Remove-developer-mode.patch new file mode 100644 index 0000000000..15f6236048 --- /dev/null +++ b/testing/nemo-qml-plugin-systemsettings/0001-Remove-developer-mode.patch @@ -0,0 +1,736 @@ +Developer mode is really SailfishOS specific and doesn't make sense to have on other platforms. +Besides, it depends on PackageKit which is not available on Alpine. + +diff --git a/src/developermodesettings.cpp b/src/developermodesettings.cpp +deleted file mode 100644 +index 5767eb7..0000000 +--- a/src/developermodesettings.cpp ++++ /dev/null +@@ -1,524 +0,0 @@ +-/* +- * Copyright (c) 2013 – 2019 Jolla Ltd. +- * Copyright (c) 2019 Open Mobile Platform LLC. +- * Contact: Thomas Perl +- * Contact: Raine Makelainen +- * +- * 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 "developermodesettings.h" +-#include "logging_p.h" +- +-#include +-#include +-#include +-#include +-#include +- +-/* Symbolic constants */ +-#define PROGRESS_INDETERMINATE (-1) +- +-/* Interfaces for IP addresses */ +-#define USB_NETWORK_FALLBACK_INTERFACE "usb0" +-#define USB_NETWORK_FALLBACK_IP "192.168.2.15" +-#define WLAN_NETWORK_INTERFACE "wlan0" +-#define WLAN_NETWORK_FALLBACK_INTERFACE "tether" +- +-/* 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" +-#define USB_MODED_PATH "/com/meego/usb_moded" +-#define USB_MODED_INTERFACE "com.meego.usb_moded" +- +-/* D-Bus method names */ +-#define USB_MODED_GET_NET_CONFIG "get_net_config" +-#define USB_MODED_SET_NET_CONFIG "net_config" +- +-/* USB Mode Daemon network configuration properties */ +-#define USB_MODED_CONFIG_IP "ip" +-#define USB_MODED_CONFIG_INTERFACE "interface" +- +-static QMap enumerate_network_interfaces() +-{ +- QMap result; +- +- for (const QNetworkInterface &intf : QNetworkInterface::allInterfaces()) { +- for (const QNetworkAddressEntry &entry : intf.addressEntries()) { +- if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) { +- result[intf.name()] = entry.ip().toString(); +- } +- } +- } +- +- 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()) +- , m_wlanIpAddress("-") +- , m_usbInterface(USB_NETWORK_FALLBACK_INTERFACE) +- , m_usbIpAddress(USB_NETWORK_FALLBACK_IP) +- , m_username(qgetenv("USER")) +- , m_developerModeEnabled(QFile::exists(DEVELOPER_MODE_PROVIDED_FILE)) +- , m_workStatus(Idle) +- , m_workProgress(PROGRESS_INDETERMINATE) +- , 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 +-{ +- // 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 +- // TODO: Watch package manager for changes to developer mode +-} +- +-DeveloperModeSettings::~DeveloperModeSettings() +-{ +-} +- +-QString DeveloperModeSettings::wlanIpAddress() const +-{ +- return m_wlanIpAddress; +-} +- +-QString DeveloperModeSettings::usbIpAddress() const +-{ +- return m_usbIpAddress; +-} +- +-QString DeveloperModeSettings::username() const +-{ +- return m_username; +-} +- +-bool DeveloperModeSettings::developerModeEnabled() const +-{ +- return m_developerModeEnabled; +-} +- +-enum DeveloperModeSettings::Status DeveloperModeSettings::workStatus() const +-{ +- return m_workStatus; +-} +- +-int DeveloperModeSettings::workProgress() const +-{ +- 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) { +- if (m_workStatus != Idle) { +- qCWarning(lcDeveloperModeLog) << "DeveloperMode state change requested during activity, ignored."; +- return; +- } +- +- m_refreshedForInstall = false; +- if (enabled) { +- resolveAndExecute(InstallCommand); +- } else { +- resolveAndExecute(RemoveCommand); +- } +- } +-} +- +-void DeveloperModeSettings::setUsbIpAddress(const QString &usbIpAddress) +-{ +- if (m_usbIpAddress != usbIpAddress) { +- usbModedSetConfig(USB_MODED_CONFIG_IP, usbIpAddress); +- m_usbIpAddress = usbIpAddress; +- emit usbIpAddressChanged(); +- } +-} +- +-void DeveloperModeSettings::refresh() +-{ +- /* Retrieve network configuration from usb_moded */ +- m_usbInterface = usbModedGetConfig(USB_MODED_CONFIG_INTERFACE, USB_NETWORK_FALLBACK_INTERFACE); +- QString usbIp = usbModedGetConfig(USB_MODED_CONFIG_IP, USB_NETWORK_FALLBACK_IP); +- +- if (usbIp != m_usbIpAddress) { +- m_usbIpAddress = usbIp; +- emit usbIpAddressChanged(); +- } +- +- /* Retrieve network configuration from interfaces */ +- QMap entries = enumerate_network_interfaces(); +- +- if (entries.contains(m_usbInterface)) { +- QString ip = entries[m_usbInterface]; +- if (m_usbIpAddress != ip) { +- m_usbIpAddress = ip; +- emit usbIpAddressChanged(); +- } +- } +- +- if (entries.contains(WLAN_NETWORK_INTERFACE)) { +- QString ip = entries[WLAN_NETWORK_INTERFACE]; +- if (m_wlanIpAddress != ip) { +- m_wlanIpAddress = ip; +- emit wlanIpAddressChanged(); +- } +- } else if (entries.contains(WLAN_NETWORK_FALLBACK_INTERFACE)) { +- // If the WLAN network interface does not have an IP address, +- // but there is a "tether" interface that does have an IP, assume +- // it is the WLAN interface in tethering mode, and use its IP. +- QString ip = entries[WLAN_NETWORK_FALLBACK_INTERFACE]; +- if (m_wlanIpAddress != ip) { +- m_wlanIpAddress = ip; +- emit wlanIpAddressChanged(); +- } +- } +- +- for (const QString &device : entries.keys()) { +- qCDebug(lcDeveloperModeLog) << "Device:" << device << "IP:" << entries[device]; +- } +-} +- +-void DeveloperModeSettings::refreshPackageCacheAndInstall() +-{ +- m_refreshedForInstall = true; +- +- // Soft refresh, do not clear & reload valid cache. +- PackageKit::Transaction *refreshCache = PackageKit::Daemon::refreshCache(false); +- connect(refreshCache, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode); +- connect(refreshCache, &PackageKit::Transaction::finished, +- this, [this](PackageKit::Transaction::Exit status, uint runtime) { +- qCDebug(lcDeveloperModeLog) << "Package cache updated:" << status << runtime; +- resolveAndExecute(InstallCommand); // trying again regardless of success, some repositories might be updated +- }); +-} +- +-void DeveloperModeSettings::resolveAndExecute(Command command) +-{ +- setWorkStatus(Preparing); +- m_workProgress = 0; +- m_developerModePackageId.clear(); // might differ between installed/available +- +- 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 { +- 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::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(); +- } +- +- } 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 { +- 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 { +- 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) +-{ +- connect(transaction, &PackageKit::Transaction::errorCode, this, &DeveloperModeSettings::reportTransactionErrorCode); +- connect(transaction, &PackageKit::Transaction::percentageChanged, this, [this, transaction]() { +- updateState(transaction->percentage(), m_transactionStatus, m_transactionRole); +- }); +- +- connect(transaction, &PackageKit::Transaction::statusChanged, this, [this, transaction]() { +- updateState(m_workProgress, transaction->status(), m_transactionRole); +- }); +- +- connect(transaction, &PackageKit::Transaction::roleChanged, this, [this, transaction]() { +- updateState(m_workProgress, m_transactionStatus, transaction->role()); +- }); +-} +- +-void DeveloperModeSettings::updateState(int percentage, PackageKit::Transaction::Status status, PackageKit::Transaction::Role role) +-{ +- // Expected changes from PackageKit when installing packages: +- // 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: +- // setup -> remove -> resolve deps (refer to as 'Preparing' status) +- // -> remove ('RemovingPackages' status) +- // -> finished +- // +- // Notice the 'install' and 'remove' packagekit status changes occur twice. +- +- int progress = m_workProgress; +- DeveloperModeSettings::Status workStatus = m_workStatus; +- +- 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 +- || m_transactionRole == PackageKit::Transaction::RoleInstallFiles) { +- switch (m_transactionStatus) { +- case PackageKit::Transaction::StatusRefreshCache: // 0-10 % +- rangeStart = 0; +- rangeEnd = 10; +- break; +- case PackageKit::Transaction::StatusQuery: // fall through; packagekit progress changes 0-100 over query->resolve stages +- case PackageKit::Transaction::StatusDepResolve: // 10-20 % +- rangeStart = 10; +- rangeEnd = 20; +- break; +- case PackageKit::Transaction::StatusDownload: // 20-60 % +- // Skip downloading when installing from local file +- if (m_transactionRole != PackageKit::Transaction::RoleInstallFiles) { +- workStatus = DownloadingPackages; +- } +- rangeStart = 20; +- rangeEnd = 60; +- break; +- case PackageKit::Transaction::StatusInstall: // 60-100 % +- workStatus = InstallingPackages; +- rangeStart = 60; +- rangeEnd = 100; +- break; +- default: +- break; +- } +- } else if (m_transactionRole == PackageKit::Transaction::RoleRemovePackages) { +- if (m_transactionStatus == PackageKit::Transaction::StatusSetup) { +- // Let the setup to be bound between 0-20 % +- rangeStart = 0; +- rangeEnd = 20; +- } else { // 20-100 % +- workStatus = RemovingPackages; +- rangeStart = 20; +- rangeEnd = 100; +- } +- } +- if (rangeEnd > 0 && rangeEnd > rangeStart) { +- progress = rangeStart + ((rangeEnd - rangeStart) * (percentage / 100.0)); +- } +- } +- +- progress = qBound(0, qMax(progress, m_workProgress), 100); // Ensure the emitted progress value never decreases. +- +- setWorkStatus(workStatus); +- +- if (m_workProgress != progress) { +- m_workProgress = progress; +- emit workProgressChanged(); +- } +-} +- +-void DeveloperModeSettings::resetState() +-{ +- bool enabled = QFile::exists(DEVELOPER_MODE_PROVIDED_FILE); +- if (m_developerModeEnabled != enabled) { +- m_developerModeEnabled = enabled; +- emit developerModeEnabledChanged(); +- } +- +- setWorkStatus(Idle); +- +- if (m_workProgress != PROGRESS_INDETERMINATE) { +- m_workProgress = PROGRESS_INDETERMINATE; +- emit workProgressChanged(); +- } +-} +- +-void DeveloperModeSettings::setWorkStatus(DeveloperModeSettings::Status status) +-{ +- if (m_workStatus != status) { +- m_workStatus = status; +- emit workStatusChanged(); +- } +-} +- +-void DeveloperModeSettings::reportTransactionErrorCode(PackageKit::Transaction::Error code, const QString &details) +-{ +- qCWarning(lcDeveloperModeLog) << "Transaction error:" << code << details; +-} +- +-QString DeveloperModeSettings::usbModedGetConfig(const QString &key, const QString &fallback) +-{ +- QString value = fallback; +- +- QDBusMessage msg = m_usbModeDaemon.call(USB_MODED_GET_NET_CONFIG, key); +- QList result = msg.arguments(); +- if (result[0].toString() == key && result.size() == 2) { +- value = result[1].toString(); +- } +- +- return value; +-} +- +-void DeveloperModeSettings::usbModedSetConfig(const QString &key, const QString &value) +-{ +- m_usbModeDaemon.call(USB_MODED_SET_NET_CONFIG, key, value); +-} +diff --git a/src/developermodesettings.h b/src/developermodesettings.h +deleted file mode 100644 +index d5473f7..0000000 +--- a/src/developermodesettings.h ++++ /dev/null +@@ -1,130 +0,0 @@ +-/* +- * Copyright (c) 2013 – 2019 Jolla Ltd. +- * Copyright (c) 2019 Open Mobile Platform LLC. +- * Contact: Thomas Perl +- * +- * 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 DEVELOPERMODESETTINGS_H +-#define DEVELOPERMODESETTINGS_H +- +-#include +-#include +- +-#include +-#include +- +- +-QT_BEGIN_NAMESPACE +-class QDBusPendingCallWatcher; +-QT_END_NAMESPACE +- +-class SYSTEMSETTINGS_EXPORT DeveloperModeSettings : public QObject +-{ +- Q_OBJECT +- Q_ENUMS(Status) +- +- Q_PROPERTY(QString wlanIpAddress READ wlanIpAddress NOTIFY wlanIpAddressChanged) +- Q_PROPERTY(QString usbIpAddress READ usbIpAddress NOTIFY usbIpAddressChanged) +- Q_PROPERTY(QString username READ username CONSTANT) +- 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); +- virtual ~DeveloperModeSettings(); +- +- enum Status { +- Idle = 0, +- Preparing, +- DownloadingPackages, +- InstallingPackages, +- RemovingPackages +- }; +- +- QString wlanIpAddress() const; +- QString usbIpAddress() const; +- QString username() const; +- 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); +- Q_INVOKABLE void refresh(); +- +-signals: +- void wlanIpAddressChanged(); +- void usbIpAddressChanged(); +- void developerModeEnabledChanged(); +- void workStatusChanged(); +- void workProgressChanged(); +- void repositoryAccessRequiredChanged(); +- +-private slots: +- void reportTransactionErrorCode(PackageKit::Transaction::Error code, const QString &details); +- void updateState(int percentage, PackageKit::Transaction::Status status, PackageKit::Transaction::Role role); +- +-private: +- enum Command { +- InstallCommand, +- RemoveCommand +- }; +- +- void resetState(); +- void setWorkStatus(Status status); +- void refreshPackageCacheAndInstall(); +- void resolveAndExecute(Command command); +- void connectCommandSignals(PackageKit::Transaction *transaction); +- +- QString usbModedGetConfig(const QString &key, const QString &fallback); +- void usbModedSetConfig(const QString &key, const QString &value); +- +- QDBusInterface m_usbModeDaemon; +- QString m_wlanIpAddress; +- QString m_usbInterface; +- QString m_usbIpAddress; +- QString m_username; +- QString m_developerModePackageId; +- bool m_developerModeEnabled; +- DeveloperModeSettings::Status m_workStatus; +- int m_workProgress; +- PackageKit::Transaction::Role m_transactionRole; +- PackageKit::Transaction::Status m_transactionStatus; +- bool m_refreshedForInstall; +- bool m_localInstallFailed; +- QString m_localDeveloperModePackagePath; +-}; +- +-Q_DECLARE_METATYPE(DeveloperModeSettings::Status) +- +-#endif /* DEVELOPERMODESETTINGS_H */ +diff --git a/src/plugin/plugin.cpp b/src/plugin/plugin.cpp +index 8174c09..b7db9ae 100644 +--- a/src/plugin/plugin.cpp ++++ b/src/plugin/plugin.cpp +@@ -43,7 +43,6 @@ + #include "alarmtonemodel.h" + #include "displaysettings.h" + #include "aboutsettings.h" +-#include "developermodesettings.h" + #include "batterystatus.h" + #include "diskusage.h" + #include "partitionmodel.h" +@@ -104,10 +103,8 @@ public: + qmlRegisterType(uri, 1, 0, "AboutSettings"); + qmlRegisterType(uri, 1, 0, "PartitionModel"); + qRegisterMetaType("Partition"); +- qmlRegisterType(uri, 1, 0, "DeveloperModeSettings"); + qmlRegisterType(uri, 1, 0, "CertificateModel"); + qmlRegisterSingletonType(uri, 1, 0, "SettingsVpnModel", api_factory); +- qRegisterMetaType("DeveloperModeSettings::Status"); + qmlRegisterType(uri, 1, 0, "BatteryStatus"); + qmlRegisterType(uri, 1, 0, "DiskUsage"); + qmlRegisterType(uri, 1, 0, "LocationSettings"); +diff --git a/src/plugin/plugin.pro b/src/plugin/plugin.pro +index 9a05fa9..cfd58e7 100644 +--- a/src/plugin/plugin.pro ++++ b/src/plugin/plugin.pro +@@ -6,7 +6,7 @@ CONFIG += qt plugin c++11 hide_symbols link_pkgconfig + QT += qml dbus network + QT -= gui + +-PKGCONFIG += profile usb-moded-qt5 nemomodels-qt5 libsailfishkeyprovider connman-qt5 packagekitqt5 ++PKGCONFIG += profile usb-moded-qt5 nemomodels-qt5 libsailfishkeyprovider connman-qt5 + + target.path = $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH + INSTALLS += target +diff --git a/src/src.pro b/src/src.pro +index 791a3f7..57f59b4 100644 +--- a/src/src.pro ++++ b/src/src.pro +@@ -7,7 +7,7 @@ QT -= gui + + CONFIG += c++11 hide_symbols link_pkgconfig + PKGCONFIG += profile mlite5 mce timed-qt5 blkid libcrypto nemomodels-qt5 libsailfishkeyprovider connman-qt5 glib-2.0 +-PKGCONFIG += ssu-sysinfo nemodbus packagekitqt5 libsystemd sailfishusermanager sailfishaccesscontrol ++PKGCONFIG += ssu-sysinfo nemodbus libsystemd sailfishusermanager sailfishaccesscontrol + + system(qdbusxml2cpp -p mceiface.h:mceiface.cpp mce.xml) + +@@ -22,8 +22,7 @@ SOURCES += \ + mceiface.cpp \ + displaysettings.cpp \ + aboutsettings.cpp \ +- certificatemodel.cpp \ +- developermodesettings.cpp \ ++ certificatemodel.cpp \ + batterystatus.cpp \ + diskusage.cpp \ + diskusage_impl.cpp \ +@@ -51,7 +50,6 @@ PUBLIC_HEADERS = \ + aboutsettings.h \ + certificatemodel.h \ + settingsvpnmodel.h \ +- developermodesettings.h \ + batterystatus.h \ + udisks2block_p.h \ + udisks2defines.h \ diff --git a/testing/nemo-qml-plugin-systemsettings/0002-Remove-broken-certificatemodel.patch b/testing/nemo-qml-plugin-systemsettings/0002-Remove-broken-certificatemodel.patch new file mode 100644 index 0000000000..c12acc6599 --- /dev/null +++ b/testing/nemo-qml-plugin-systemsettings/0002-Remove-broken-certificatemodel.patch @@ -0,0 +1,996 @@ +Sadly this functionality is broken with no available patch to fix it. +To make sure we can still build and use this package, let's just remove it. + +diff --git a/src/certificatemodel.cpp b/src/certificatemodel.cpp +deleted file mode 100644 +index f568fec..0000000 +--- a/src/certificatemodel.cpp ++++ /dev/null +@@ -1,800 +0,0 @@ +-/* +- * 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 "certificatemodel.h" +- +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-namespace { +- +-struct X509List; +- +-} +- +-struct X509Certificate +-{ +- QList> subjectList(bool shortForm = false) const +- { +- return nameList(X509_get_subject_name(x509), shortForm); +- } +- QString subject(bool shortForm = true, const QString &separator = QString(", ")) const +- { +- return toString(subjectList(shortForm), separator); +- } +- QString subjectElement(int nid) const +- { +- return nameElement(X509_get_subject_name(x509), nid); +- } +- +- QList> issuerList(bool shortForm = false) const +- { +- return nameList(X509_get_issuer_name(x509), shortForm); +- } +- QString issuer(bool shortForm = true, const QString &separator = QString(", ")) const +- { +- return toString(issuerList(shortForm), separator); +- } +- QString issuerElement(int nid) const +- { +- return nameElement(X509_get_issuer_name(x509), nid); +- } +- +- QString version() const +- { +- return QString::number(X509_get_version(x509) + 1); +- } +- +- QString serialNumber() const +- { +- return integerToString(X509_get_serialNumber(x509)); +- } +- +- QDateTime notBefore() const +- { +- return toDateTime(X509_get_notBefore(x509)); +- } +- +- QDateTime notAfter() const +- { +- return toDateTime(X509_get_notAfter(x509)); +- } +- +- QList> publicKeyList(bool shortForm = false) const +- { +- QList> rv; +- +- if (EVP_PKEY *key = X509_get_pubkey(x509)) { +- rv.append(qMakePair(QStringLiteral("Algorithm"), idToString(EVP_PKEY_id(key), shortForm))); +- rv.append(qMakePair(QStringLiteral("Bits"), QString::number(EVP_PKEY_bits(key)))); +- +- BIO *b = BIO_new(BIO_s_mem()); +- EVP_PKEY_print_public(b, key, 0, 0); +- const QList> &details(parseData(bioToString(b))); +- for (auto it = details.cbegin(), end = details.cend(); it != end; ++it) { +- rv.append(qMakePair(it->first, it->second)); +- } +- BIO_free(b); +- +- EVP_PKEY_free(key); +- } +- +- return rv; +- } +- +- QList> extensionList(bool shortForm = false) const +- { +- QList> rv; +- +- for (int i = 0, n = sk_X509_EXTENSION_num(x509->cert_info->extensions); i < n; ++i) { +- X509_EXTENSION *extension = sk_X509_EXTENSION_value(x509->cert_info->extensions, i); +- +- ASN1_OBJECT *object = X509_EXTENSION_get_object(extension); +- int nid = OBJ_obj2nid(object); +- if (nid == NID_undef) +- continue; +- +- QString name(objectToString(object, shortForm)); +- if (X509_EXTENSION_get_critical(extension) > 0) { +- name.append(QStringLiteral(" (Critical)")); +- } +- +- BIO *b = BIO_new(BIO_s_mem()); +- X509V3_EXT_print(b, extension, 0, 0); +- rv.append(qMakePair(name, bioToString(b))); +- BIO_free(b); +- } +- +- return rv; +- } +- +- QList> signatureList(bool shortForm = false) const +- { +- QList> rv; +- +- rv.append(qMakePair(QStringLiteral("Algorithm"), objectToString(x509->sig_alg->algorithm, shortForm))); +- +- BIO *b = BIO_new(BIO_s_mem()); +- X509_signature_dump(b, x509->signature, 0); +- QString d(bioToString(b).replace(QChar('\n'), QString())); +- rv.append(qMakePair(QStringLiteral("Data"), d.trimmed())); +- BIO_free(b); +- +- return rv; +- } +- +-private: +- static QString stringToString(ASN1_STRING *data) +- { +- return QString::fromUtf8(reinterpret_cast(ASN1_STRING_data(data))); +- } +- +- static QString timeToString(ASN1_TIME *data) +- { +- return stringToString(data); +- } +- +- static QString idToString(int nid, bool shortForm) +- { +- return QString::fromUtf8(shortForm ? OBJ_nid2sn(nid) : OBJ_nid2ln(nid)); +- } +- +- static QString objectToString(ASN1_OBJECT *object, bool shortForm) +- { +- return idToString(OBJ_obj2nid(object), shortForm); +- } +- +- static QString integerToString(ASN1_INTEGER *integer) +- { +- if (integer->type != V_ASN1_INTEGER && integer->type != V_ASN1_NEG_INTEGER) +- return QString(); +- +- quint64 value = 0; +- for (size_t i = 0, n = qMin(integer->length, 8); i < n; ++i) +- value = value << 8 | integer->data[i]; +- +- QString rv = QString::number(value); +- if (integer->type == V_ASN1_NEG_INTEGER) +- rv.prepend(QStringLiteral("-")); +- return rv; +- } +- +- static QString bioToString(BIO *bio) +- { +- char *out = 0; +- int n = BIO_get_mem_data(bio, &out); +- return QString::fromUtf8(QByteArray::fromRawData(out, n)); +- } +- +- static QList> nameList(X509_NAME *name, bool shortForm = true) +- { +- QList> rv; +- +- for (int i = 0, n = X509_NAME_entry_count(name); i < n; ++i) { +- X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); +- ASN1_OBJECT *object = X509_NAME_ENTRY_get_object(entry); +- ASN1_STRING *data = X509_NAME_ENTRY_get_data(entry); +- rv.append(qMakePair(objectToString(object, shortForm), stringToString(data))); +- } +- +- return rv; +- } +- +- static QString nameElement(X509_NAME *name, int nid) +- { +- for (int i = 0, n = X509_NAME_entry_count(name); i < n; ++i) { +- X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i); +- ASN1_OBJECT *object = X509_NAME_ENTRY_get_object(entry); +- if (OBJ_obj2nid(object) == nid) { +- ASN1_STRING *data = X509_NAME_ENTRY_get_data(entry); +- return stringToString(data); +- } +- } +- +- return QString(); +- } +- +- static QString toString(const QList> &list, const QString &separator = QString(", ")) +- { +- QString rv; +- +- for (auto it = list.cbegin(), end = list.cend(); it != end; ++it) { +- if (!rv.isEmpty()) { +- rv.append(separator); +- } +- rv.append(it->first); +- rv.append(QChar(':')); +- rv.append(it->second); +- } +- +- return rv; +- } +- +- static QDateTime toDateTime(ASN1_TIME *time) +- { +- const QString ts(timeToString(time)); +- return (time->type == V_ASN1_GENERALIZEDTIME ? fromGENERALIZEDTIME(ts) : fromUTCTIME(ts)); +- } +- +- static QDateTime fromUTCTIME(const QString &ts) +- { +- QDate d; +- QTime t; +- int offset = 0; +- +- // "YYMMDDhhmm[ss](Z|(+|-)hhmm)" +- const QRegularExpression re("([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?(Z)?(([+-])([0-9]{2})([0-9]{2}))?"); +- QRegularExpressionMatch match = re.match(ts); +- if (match.hasMatch()) { +- int y = match.captured(1).toInt(); +- d = QDate((y < 70 ? 2000 : 1900) + y, match.captured(2).toInt(), match.captured(3).toInt()); +- +- t = QTime(match.captured(4).toInt(), match.captured(5).toInt(), match.captured(6).toInt()); +- +- if (match.lastCapturedIndex() > 7) { +- offset = match.captured(11).toInt() * 60 + match.captured(10).toInt() * 60*60; +- if (match.captured(9) == "-") { +- offset = -offset; +- } +- } +- } +- +- return QDateTime(d, t, Qt::OffsetFromUTC, offset); +- } +- +- static QDateTime fromGENERALIZEDTIME(const QString &ts) +- { +- QDate d; +- QTime t; +- int offset = 0; +- +- // "YYYYMMDDhh[mm[ss[.fff]]](Z|(+|-)hhmm)" <- nested optionals can be treated as appearing sequentially +- const QRegularExpression re("([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?([0-9]{2})?(\\.[0-9]{1,3})?(Z)?(([+-])([0-9]{2})([0-9]{2}))?"); +- QRegularExpressionMatch match = re.match(ts); +- if (match.hasMatch()) { +- d = QDate(match.captured(1).toInt(), match.captured(2).toInt(), match.captured(3).toInt()); +- +- double fraction = match.captured(7).toDouble(); +- int ms = (fraction * 1000); +- t = QTime(match.captured(4).toInt(), match.captured(5).toInt(), match.captured(6).toInt(), ms); +- +- if (match.lastCapturedIndex() > 8) { +- offset = match.captured(12).toInt() * 60 + match.captured(11).toInt() * 60*60; +- if (match.captured(10) == "-") { +- offset = -offset; +- } +- } +- } +- +- return QDateTime(d, t, Qt::OffsetFromUTC, offset); +- } +- +- static QList> parseData(QString data) +- { +- QList> rv; +- +- // Join any data with the preceding header +- data.replace(QRegularExpression(": *\n +"), QStringLiteral(":")); +- foreach (const QString &line, data.split(QString("\n"), QString::SkipEmptyParts)) { +- int index = line.indexOf(QChar(':')); +- if (index != -1) { +- QString name(line.left(index)); +- QString value(line.mid(index + 1).trimmed()); +- rv.append(qMakePair(name, value)); +- } +- } +- +- return rv; +- } +- +- friend struct ::X509List; +- +- X509Certificate(X509 *x) : x509(x) {} +- +- X509 *x509; +-}; +- +-namespace { +- +-struct X509List +-{ +- X509List() +- : crlStack(0), certificateStack(0), pkcs7(0), pkcs7Signed(0) +- { +- crlStack = sk_X509_CRL_new_null(); +- if (!crlStack) { +- qWarning() << "Unable to allocate CRL stack"; +- } else { +- certificateStack = sk_X509_new_null(); +- if (!certificateStack) { +- qWarning() << "Unable to allocate X509 stack"; +- } else { +- pkcs7 = PKCS7_new(); +- pkcs7Signed = PKCS7_SIGNED_new(); +- if (!pkcs7 || !pkcs7Signed) { +- qWarning() << "Unable to create PKCS7 structures"; +- } else { +- pkcs7Signed->crl = crlStack; +- pkcs7Signed->cert = certificateStack; +- +- pkcs7->type = OBJ_nid2obj(NID_pkcs7_signed); +- pkcs7->d.sign = pkcs7Signed; +- pkcs7Signed->contents->type = OBJ_nid2obj(NID_pkcs7_data); +- if (!ASN1_INTEGER_set(pkcs7Signed->version, 1)) { +- qWarning() << "Unable to set PKCS7 signed version"; +- } +- } +- } +- } +- } +- +- ~X509List() +- { +- /* Apparently, pkcs7Signed and pkcs7 cannot be safely freed... +- if (pkcs7Signed) +- PKCS7_SIGNED_free(pkcs7Signed); +- if (pkcs7) +- PKCS7_free(pkcs7); +- */ +- if (certificateStack) +- sk_X509_free(certificateStack); +- if (crlStack) +- sk_X509_CRL_free(crlStack); +- } +- +- bool isValid() const +- { +- return pkcs7 && pkcs7Signed; +- } +- +- int count() const +- { +- return sk_X509_num(certificateStack); +- } +- +- void append(X509 *x509) +- { +- sk_X509_push(certificateStack, x509); +- } +- +- void for_each(std::function fn) const +- { +- for (int i = 0, n(count()); i < n; ++i) { +- fn(X509Certificate(sk_X509_value(certificateStack, i))); +- } +- } +- +-private: +- STACK_OF(X509_CRL) *crlStack; +- STACK_OF(X509) *certificateStack; +- PKCS7 *pkcs7; +- PKCS7_SIGNED *pkcs7Signed; +-}; +- +-struct PKCS7File +-{ +- explicit PKCS7File(const QString &path) +- { +- if (!isValid()) { +- qWarning() << "Unable to prepare X509 certificates structure"; +- } else { +- BIO *input = BIO_new(BIO_s_file()); +- if (!input) { +- qWarning() << "Unable to allocate new BIO for:" << path; +- } else { +- const QByteArray filename(QFile::encodeName(path)); +- if (BIO_read_filename(input, const_cast(filename.constData())) <= 0) { +- qWarning() << "Unable to open PKCS7 file:" << path; +- } else { +- read_pem_from_bio(input); +- } +- +- BIO_free(input); +- } +- } +- } +- +- 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() +- { +- } +- +- bool isValid() const +- { +- return certs.isValid(); +- } +- +- int count() const +- { +- return certs.count(); +- } +- +- const X509List &getCertificates() +- { +- return certs; +- } +- +-private: +- X509List certs; +-}; +- +-class LibCrypto +-{ +- struct Initializer +- { +- Initializer() +- { +- // As per: https://wiki.openssl.org/index.php/Library_Initialization#libcrypto_Initialization +- OpenSSL_add_all_algorithms(); +- ERR_load_crypto_strings(); +- OPENSSL_config(NULL); +- } +- +- ~Initializer() +- { +- FIPS_mode_set(0); +- ENGINE_cleanup(); +- CONF_modules_unload(1); +- EVP_cleanup(); +- CRYPTO_cleanup_all_ex_data(); +- ERR_remove_thread_state(NULL); +- ERR_free_strings(); +- } +- }; +- +- static Initializer init; +- +-public: +- template +- static QList getCertificates(const T &bundleData) +- { +- PKCS7File bundle(bundleData); +- +- return bundleToCertificates(bundle); +- } +-private: +- static QList bundleToCertificates(PKCS7File &bundle) +- { +- QList certificates; +- if (bundle.isValid() && bundle.count() > 0) { +- certificates.reserve(bundle.count()); +- bundle.getCertificates().for_each([&certificates](const X509Certificate &cert) { +- certificates.append(Certificate(cert)); +- }); +- } +- +- return certificates; +- } +-}; +- +- +-LibCrypto::Initializer LibCrypto::init; +- +-const QList > &bundlePaths() +-{ +- static QList > paths; +- if (paths.isEmpty()) { +- paths.append(qMakePair(QString("/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"), CertificateModel::TLSBundle)); +- paths.append(qMakePair(QString("/etc/pki/ca-trust/extracted/pem/email-ca-bundle.pem"), CertificateModel::EmailBundle)); +- paths.append(qMakePair(QString("/etc/pki/ca-trust/extracted/pem/objsign-ca-bundle.pem"), CertificateModel::ObjectSigningBundle)); +- } +- return paths; +-} +- +-CertificateModel::BundleType bundleType(const QString &path) +-{ +- if (path.isEmpty()) +- return CertificateModel::NoBundle; +- +- const QList > &bundles(bundlePaths()); +- for (auto it = bundles.cbegin(), end = bundles.cend(); it != end; ++it) { +- if (it->first == path) +- return it->second; +- } +- +- return CertificateModel::UserSpecifiedBundle; +-} +- +-QString bundlePath(CertificateModel::BundleType type) +-{ +- if (type == CertificateModel::UserSpecifiedBundle) +- return QString(); +- +- const QList > &bundles(bundlePaths()); +- for (auto it = bundles.cbegin(), end = bundles.cend(); it != end; ++it) { +- if (it->second == type) +- return it->first; +- } +- +- return QStringLiteral(""); +-} +- +-} +- +-Certificate::Certificate(const X509Certificate &cert) +- : m_commonName(cert.subjectElement(NID_commonName)) +- , m_countryName(cert.subjectElement(NID_countryName)) +- , m_organizationName(cert.subjectElement(NID_organizationName)) +- , m_organizationalUnitName(cert.subjectElement(NID_organizationalUnitName)) +- , m_notValidBefore(cert.notBefore()) +- , m_notValidAfter(cert.notAfter()) +-{ +- // Yield consistent names for the certificates, despite inconsistent naming policy +- QString Certificate::*members[] = { &Certificate::m_commonName, &Certificate::m_organizationalUnitName, &Certificate::m_organizationName, &Certificate::m_countryName }; +- for (auto it = std::begin(members); it != std::end(members); ++it) { +- const QString &s(this->*(*it)); +- if (!s.isEmpty()) { +- if (m_primaryName.isEmpty()) { +- m_primaryName = s; +- } else if (m_secondaryName.isEmpty()) { +- m_secondaryName = s; +- break; +- } +- } +- } +- +- // 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())); +- validity.insert(QStringLiteral("NotAfter"), QVariant(cert.notAfter())); +- m_details.insert(QStringLiteral("Validity"), QVariant(validity)); +- +- QVariantMap issuer; +- const QList> &issuerDetails(cert.issuerList()); +- for (auto it = issuerDetails.cbegin(), end = issuerDetails.cend(); it != end; ++it) { +- issuer.insert(it->first, QVariant(it->second)); +- } +- m_details.insert(QStringLiteral("Issuer"), QVariant(issuer)); +- +- QVariantMap subject; +- const QList> &subjectDetails(cert.subjectList()); +- for (auto it = subjectDetails.cbegin(), end = subjectDetails.cend(); it != end; ++it) { +- subject.insert(it->first, QVariant(it->second)); +- } +- m_details.insert(QStringLiteral("Subject"), QVariant(subject)); +- +- QVariantMap publicKey; +- const QList> &keyDetails(cert.publicKeyList()); +- for (auto it = keyDetails.cbegin(), end = keyDetails.cend(); it != end; ++it) { +- publicKey.insert(it->first, QVariant(it->second)); +- } +- m_details.insert(QStringLiteral("SubjectPublicKeyInfo"), QVariant(publicKey)); +- +- QVariantMap extensions; +- const QList> &extensionDetails(cert.extensionList()); +- for (auto it = extensionDetails.cbegin(), end = extensionDetails.cend(); it != end; ++it) { +- extensions.insert(it->first, QVariant(it->second)); +- } +- m_details.insert(QStringLiteral("Extensions"), extensions); +- +- QVariantMap signature; +- const QList> &signatureDetails(cert.signatureList()); +- for (auto it = signatureDetails.cbegin(), end = signatureDetails.cend(); it != end; ++it) { +- signature.insert(it->first, QVariant(it->second)); +- } +- m_details.insert(QStringLiteral("Signature"), signature); +-} +- +-CertificateModel::CertificateModel(QObject *parent) +- : QAbstractListModel(parent) +- , m_type(NoBundle) +-{ +-} +- +-CertificateModel::~CertificateModel() +-{ +-} +- +-CertificateModel::BundleType CertificateModel::bundleType() const +-{ +- return m_type; +-} +- +-void CertificateModel::setBundleType(BundleType type) +-{ +- if (m_type != type) { +- m_type = type; +- +- const QString path(::bundlePath(m_type)); +- if (!path.isNull()) +- setBundlePath(path); +- +- emit bundleTypeChanged(); +- } +-} +- +-QString CertificateModel::bundlePath() const +-{ +- return m_path; +-} +- +-void CertificateModel::setBundlePath(const QString &path) +-{ +- if (m_path != path) { +- m_path = path; +- refresh(); +- +- const BundleType type(::bundleType(m_path)); +- setBundleType(type); +- +- emit bundlePathChanged(); +- } +-} +- +-int CertificateModel::rowCount(const QModelIndex & parent) const +-{ +- Q_UNUSED(parent) +- return m_certificates.count(); +-} +- +-QVariant CertificateModel::data(const QModelIndex &index, int role) const +-{ +- int row = index.row(); +- if (row < 0 || row >= m_certificates.count()) { +- return QVariant(); +- } +- +- const Certificate &cert = m_certificates.at(row); +- switch (role) { +- case CommonNameRole: +- return cert.commonName(); +- case CountryNameRole: +- return cert.countryName(); +- case OrganizationNameRole: +- return cert.organizationName(); +- case OrganizationalUnitNameRole: +- return cert.organizationalUnitName(); +- case PrimaryNameRole: +- return cert.primaryName(); +- case SecondaryNameRole: +- return cert.secondaryName(); +- case NotValidBeforeRole: +- return cert.notValidBefore(); +- case NotValidAfterRole: +- return cert.notValidAfter(); +- case DetailsRole: +- return cert.details(); +- default: +- break; +- } +- +- return QVariant(); +-} +- +-QHash CertificateModel::roleNames() const +-{ +- QHash roles; +- +- roles[CommonNameRole] = "commonName"; +- roles[CountryNameRole] = "countryName"; +- roles[OrganizationNameRole] = "organizationName"; +- roles[OrganizationalUnitNameRole] = "organizationalUnitName"; +- roles[PrimaryNameRole] = "primaryName"; +- roles[SecondaryNameRole] = "secondaryName"; +- roles[NotValidBeforeRole] = "notValidBefore"; +- roles[NotValidAfterRole] = "notValidAfter"; +- roles[DetailsRole] = "details"; +- +- return roles; +-} +-void CertificateModel::refresh() +-{ +- beginResetModel(); +- if (m_path.isEmpty()) { +- m_certificates.clear(); +- } else { +- m_certificates = getCertificates(m_path); +- std::stable_sort(m_certificates.begin(), m_certificates.end(), [](const Certificate &lhs, const Certificate &rhs) { +- int c = lhs.primaryName().compare(rhs.primaryName(), Qt::CaseInsensitive); +- if (c < 0) +- return true; +- if (c > 0) +- return false; +- c = lhs.secondaryName().compare(rhs.secondaryName(), Qt::CaseInsensitive); +- if (c < 0) +- return true; +- return false; +- }); +- } +- endResetModel(); +-} +- +-QList CertificateModel::getCertificates(const QString &bundlePath) +-{ +- return LibCrypto::getCertificates(bundlePath); +-} +- +-QList CertificateModel::getCertificates(const QByteArray &pem) +-{ +- return LibCrypto::getCertificates(pem); +-} +diff --git a/src/certificatemodel.h b/src/certificatemodel.h +deleted file mode 100644 +index 8573ac4..0000000 +--- a/src/certificatemodel.h ++++ /dev/null +@@ -1,139 +0,0 @@ +-/* +- * 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 CERTIFICATEMODEL_H +-#define CERTIFICATEMODEL_H +- +-#include +-#include +-#include +-#include +- +-#include "systemsettingsglobal.h" +- +- +-struct X509Certificate; +- +-class SYSTEMSETTINGS_EXPORT Certificate +-{ +-public: +- Certificate(const X509Certificate &cert); +- +- QString commonName() const { return m_commonName; } +- QString countryName() const { return m_countryName; } +- QString organizationName() const { return m_organizationName; } +- QString organizationalUnitName() const { return m_organizationalUnitName; } +- QString primaryName() const { return m_primaryName; } +- QString secondaryName() const { return m_secondaryName; } +- +- QDateTime notValidBefore() const { return m_notValidBefore; } +- QDateTime notValidAfter() const { return m_notValidAfter; } +- +- QVariantMap details() const { return m_details; } +- +- QString issuerDisplayName() const { return m_issuerDisplayName; } +- +-private: +- QString m_commonName; +- QString m_countryName; +- QString m_organizationName; +- QString m_organizationalUnitName; +- QString m_primaryName; +- QString m_secondaryName; +- +- QDateTime m_notValidBefore; +- QDateTime m_notValidAfter; +- +- QString m_issuerDisplayName; +- +- QVariantMap m_details; +-}; +- +-class SYSTEMSETTINGS_EXPORT CertificateModel: public QAbstractListModel +-{ +- Q_OBJECT +- Q_PROPERTY(BundleType bundleType READ bundleType WRITE setBundleType NOTIFY bundleTypeChanged) +- Q_PROPERTY(QString bundlePath READ bundlePath WRITE setBundlePath NOTIFY bundlePathChanged) +- Q_ENUMS(BundleType) +- +-public: +- enum BundleType { +- NoBundle, +- TLSBundle, +- EmailBundle, +- ObjectSigningBundle, +- UserSpecifiedBundle, +- }; +- +- enum CertificateRoles { +- CommonNameRole = Qt::UserRole + 1, +- CountryNameRole = Qt::UserRole + 2, +- OrganizationNameRole = Qt::UserRole + 3, +- OrganizationalUnitNameRole = Qt::UserRole + 4, +- PrimaryNameRole = Qt::UserRole + 5, +- SecondaryNameRole = Qt::UserRole + 6, +- NotValidBeforeRole = Qt::UserRole + 7, +- NotValidAfterRole = Qt::UserRole + 8, +- DetailsRole = Qt::UserRole + 9, +- }; +- +- explicit CertificateModel(QObject *parent = 0); +- virtual ~CertificateModel(); +- +- BundleType bundleType() const; +- void setBundleType(BundleType type); +- +- QString bundlePath() const; +- void setBundlePath(const QString &path); +- +- virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; +- virtual QVariant data(const QModelIndex &index, int role) const; +- +- static QList getCertificates(const QString &bundlePath); +- static QList getCertificates(const QByteArray &pem); +- +-Q_SIGNALS: +- void bundleTypeChanged(); +- void bundlePathChanged(); +- +-protected: +- void refresh(); +- +- QHash roleNames() const; +- +-private: +- BundleType m_type; +- QString m_path; +- QList m_certificates; +-}; +- +-#endif +diff --git a/src/plugin/plugin.cpp b/src/plugin/plugin.cpp +index b7db9ae..b06f37a 100644 +--- a/src/plugin/plugin.cpp ++++ b/src/plugin/plugin.cpp +@@ -46,7 +46,6 @@ + #include "batterystatus.h" + #include "diskusage.h" + #include "partitionmodel.h" +-#include "certificatemodel.h" + #include "settingsvpnmodel.h" + #include "locationsettings.h" + #include "deviceinfo.h" +@@ -103,7 +102,6 @@ public: + qmlRegisterType(uri, 1, 0, "AboutSettings"); + qmlRegisterType(uri, 1, 0, "PartitionModel"); + qRegisterMetaType("Partition"); +- qmlRegisterType(uri, 1, 0, "CertificateModel"); + qmlRegisterSingletonType(uri, 1, 0, "SettingsVpnModel", api_factory); + qmlRegisterType(uri, 1, 0, "BatteryStatus"); + qmlRegisterType(uri, 1, 0, "DiskUsage"); +diff --git a/src/src.pro b/src/src.pro +index 57f59b4..e5b7d37 100644 +--- a/src/src.pro ++++ b/src/src.pro +@@ -21,8 +21,7 @@ SOURCES += \ + alarmtonemodel.cpp \ + mceiface.cpp \ + displaysettings.cpp \ +- aboutsettings.cpp \ +- certificatemodel.cpp \ ++ aboutsettings.cpp \ + batterystatus.cpp \ + diskusage.cpp \ + diskusage_impl.cpp \ +@@ -48,7 +47,6 @@ PUBLIC_HEADERS = \ + mceiface.h \ + displaysettings.h \ + aboutsettings.h \ +- certificatemodel.h \ + settingsvpnmodel.h \ + batterystatus.h \ + udisks2block_p.h \ diff --git a/testing/nemo-qml-plugin-systemsettings/APKBUILD b/testing/nemo-qml-plugin-systemsettings/APKBUILD new file mode 100644 index 0000000000..0434c7ad1a --- /dev/null +++ b/testing/nemo-qml-plugin-systemsettings/APKBUILD @@ -0,0 +1,29 @@ +# Contributor: Bart Ribbers +# Maintainer: Bart Ribbers +pkgname=nemo-qml-plugin-systemsettings +pkgver=0.5.47 +pkgrel=0 +pkgdesc="Nemo QML systemsettings plugin" +url="https://git.sailfishos.org/mer-core/nemo-qml-plugin-systemsettings" +arch="all" +license="BSD-3-Clause" +depends_dev="qt5-qtdeclarative-dev qt5-qtsystems-dev sailfish-access-control profiled-dev mlite-dev mce-dev timed-dev ssu-sysinfo-dev nemo-qml-plugin-dbus-dev user-managerd-dev libusb-moded-qt-dev" +makedepends="$depends_dev qt5-qtbase-dev qt5-qttools-dev qtchooser libconnman-qt-dev libsailfishkeyprovider-dev nemo-qml-plugin-models-dev" +subpackages="$pkgname-dev" +source="https://git.sailfishos.org/mer-core/nemo-qml-plugin-systemsettings/-/archive/$pkgver/nemo-qml-plugin-systemsettings-$pkgver.tar.gz + 0001-Remove-developer-mode.patch + 0002-Remove-broken-certificatemodel.patch + " + +build() { + qmake-qt5 + make +} + +package() { + INSTALL_ROOT="$pkgdir" make install +} + +sha512sums="3214f8acd1ecda421c03355e7c53265a7e9f4544354ed84f4f4b5f60484b958aedc551b22fdbe0b8e532eb038406fe3328f4148d480eda8bdbc9d3b1e188e1c1 nemo-qml-plugin-systemsettings-0.5.47.tar.gz +f0b06a9634dcf81f31b8dcb17be70e9c0a7a8615aa7c4b8625c24db525c7e333ef372987db74e4356f36cabb9d8e9142e90390df5731f09e592a362cb26c1aa5 0001-Remove-developer-mode.patch +b49f239c9dc7c3e52e5f62e5cc13359ae4a92d289d22906b9ca02a33e6b032d8682692b25a0f5f6163b167d643f318537854b4c9e08b185a423d40f76643c5c5 0002-Remove-broken-certificatemodel.patch" -- cgit v1.2.3