diff --git a/libdiscover/backends/FwupdBackend/FwupdBackend.cpp b/libdiscover/backends/FwupdBackend/FwupdBackend.cpp index f9f68e8b..9ada1d74 100644 --- a/libdiscover/backends/FwupdBackend/FwupdBackend.cpp +++ b/libdiscover/backends/FwupdBackend/FwupdBackend.cpp @@ -1,630 +1,569 @@ /*************************************************************************** * Copyright © 2013 Aleix Pol Gonzalez * * Copyright © 2018 Abhijeet Sharma * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "FwupdBackend.h" #include "FwupdResource.h" #include "FwupdTransaction.h" #include "FwupdSourcesBackend.h" #include #include #include #include #include #include #include #include #include DISCOVER_BACKEND_PLUGIN(FwupdBackend) FwupdBackend::FwupdBackend(QObject* parent) : AbstractResourcesBackend(parent) , client(fwupd_client_new()) , m_updater(new StandardBackendUpdater(this)) { connect(m_updater, &StandardBackendUpdater::updatesCountChanged, this, &FwupdBackend::updatesCountChanged); SourcesModel::global()->addSourcesBackend(new FwupdSourcesBackend(this)); QTimer::singleShot(0, this, &FwupdBackend::checkForUpdates); } QMap FwupdBackend::gchecksumToQChryptographicHash() { static QMap map; if (map.isEmpty()) { map.insert(G_CHECKSUM_SHA1,QCryptographicHash::Sha1); map.insert(G_CHECKSUM_SHA256,QCryptographicHash::Sha256); map.insert(G_CHECKSUM_SHA512,QCryptographicHash::Sha512); map.insert(G_CHECKSUM_MD5,QCryptographicHash::Md5); } return map; } FwupdBackend::~FwupdBackend() { g_object_unref(client); } -QString FwupdBackend::buildDeviceID(FwupdDevice* device) -{ - QString DeviceID = QString::fromUtf8(fwupd_device_get_id(device)); - DeviceID.replace(QLatin1Char('/'),QLatin1Char('_')); - return QStringLiteral("org.fwupd.%1.device").arg(DeviceID); -} - void FwupdBackend::addResourceToList(FwupdResource* res) { res->setParent(this); auto &r = m_resources[res->packageName().toLower()]; if (r) { Q_EMIT resourceRemoved(r); delete r; } r = res; Q_ASSERT(m_resources.value(res->packageName().toLower()) == res); } FwupdResource * FwupdBackend::createDevice(FwupdDevice *device) { const QString name = QString::fromUtf8(fwupd_device_get_name(device)); FwupdResource* res = new FwupdResource(name, nullptr); - res->setId(buildDeviceID(device)); - setDeviceDetails(res, device); + const QString deviceID = QString::fromUtf8(fwupd_device_get_id(device)); + res->setId(QStringLiteral("org.fwupd.%1.device").arg(QString(deviceID).replace(QLatin1Char('/'),QLatin1Char('_')))); + res->setDeviceID(deviceID); + + res->setDeviceDetails(device); return res; } FwupdResource * FwupdBackend::createRelease(FwupdDevice *device) { - FwupdRelease *release = fwupd_device_get_release_default(device); - QString name = QString::fromUtf8(fwupd_release_get_name(release)); - if (name.isEmpty()) - name = QString::fromUtf8(fwupd_device_get_name(device)); + FwupdResource* res = createDevice(device); - FwupdResource* res = new FwupdResource(name, this); - - res->setDeviceID(QString::fromUtf8(fwupd_device_get_id(device))); - setReleaseDetails(res, release); - setDeviceDetails(res, device); + FwupdRelease *release = fwupd_device_get_release_default(device); res->setId(QString::fromUtf8(fwupd_release_get_appstream_id(release))); + res->setReleaseDetails(release); /* the same as we have already */ if (qstrcmp(fwupd_device_get_version(device), fwupd_release_get_version(release)) == 0) { qWarning() << "Fwupd Error: same firmware version as installed"; } return res; } -void FwupdBackend::setReleaseDetails(FwupdResource *res, FwupdRelease *release) -{ - res->setOrigin(QString::fromUtf8(fwupd_release_get_remote_id(release))); - res->setSummary(QString::fromUtf8(fwupd_release_get_summary(release))); - res->setVendor(QString::fromUtf8(fwupd_release_get_vendor(release))); - res->setSize(fwupd_release_get_size(release)); - res->setVersion(QString::fromUtf8(fwupd_release_get_version(release))); - res->setDescription(QString::fromUtf8((fwupd_release_get_description(release)))); - res->setHomePage(QUrl(QString::fromUtf8(fwupd_release_get_homepage(release)))); - res->setLicense(QString::fromUtf8(fwupd_release_get_license(release))); - res->m_updateURI = QString::fromUtf8(fwupd_release_get_uri(release)); -} - -void FwupdBackend::setDeviceDetails(FwupdResource *res, FwupdDevice *dev) -{ - res->isLiveUpdatable = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_UPDATABLE); - res->isOnlyOffline = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_ONLY_OFFLINE); - res->needsReboot = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_NEEDS_REBOOT); - res->isDeviceRemoval = !fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_INTERNAL); - res->needsBootLoader = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER); - - GPtrArray *guids = fwupd_device_get_guids(dev); - if (guids->len > 0) - { - QString guidStr = QString::fromUtf8((char *)g_ptr_array_index(guids, 0)); - for(uint i = 1; i < guids->len; i++) - { - guidStr += QLatin1Char(',') + QString::fromUtf8((char *)g_ptr_array_index(guids, i)); - } - res->guidString = guidStr; - } - if (fwupd_device_get_name(dev)) - { - QString vendorDesc = QString::fromUtf8(fwupd_device_get_name(dev)); - const QString vendorName = QString::fromUtf8(fwupd_device_get_vendor(dev)); - - if (!vendorDesc.startsWith(vendorName)) - vendorDesc = vendorName + QLatin1Char(' ') + vendorDesc; - res->setName(vendorDesc); - } - res->setSummary(QString::fromUtf8(fwupd_device_get_summary(dev))); - res->setVendor(QString::fromUtf8(fwupd_device_get_vendor(dev))); - res->setReleaseDate((QDateTime::fromSecsSinceEpoch(fwupd_device_get_created(dev))).date()); - res->setVersion(QString::fromUtf8(fwupd_device_get_version(dev))); - res->setDescription(QString::fromUtf8((fwupd_device_get_description(dev)))); - - if (fwupd_device_get_icons(dev)->len >= 1) - res->setIconName(QString::fromUtf8((const gchar *)g_ptr_array_index(fwupd_device_get_icons(dev), 0)));// Check wether given icon exists or not! - else - res->setIconName(QString::fromUtf8("device-notifier")); -} void FwupdBackend::addUpdates() { g_autoptr(GError) error = nullptr; g_autoptr(GPtrArray) devices = fwupd_client_get_devices(client, nullptr, &error); if (!devices) { if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO)) { qDebug() << "Fwupd Info: No Devices Found"; handleError(&error); } return; } for(uint i = 0; i < devices->len; i++) { FwupdDevice *device = (FwupdDevice *)g_ptr_array_index(devices, i); if (!fwupd_device_has_flag(device, FWUPD_DEVICE_FLAG_SUPPORTED)) continue; /*Device is Locked Needs Unlocking*/ if (fwupd_device_has_flag(device, FWUPD_DEVICE_FLAG_LOCKED)) { auto res = createDevice(device); res->setIsDeviceLocked(true); addResourceToList(res); connect(res, &FwupdResource::stateChanged, this, &FwupdBackend::updatesCountChanged); continue; } if (!fwupd_device_has_flag(device, FWUPD_DEVICE_FLAG_UPDATABLE)) continue; g_autoptr(GError) error2 = nullptr; g_autoptr(GPtrArray) rels = fwupd_client_get_upgrades(client, fwupd_device_get_id(device), nullptr, &error2); if (rels) { fwupd_device_add_release(device, (FwupdRelease *)g_ptr_array_index(rels, 0)); auto res = createApp(device); if (!res) { qWarning() << "Fwupd Error: Cannot Create App From Device" << fwupd_device_get_name(device); } else { QString longdescription; for(uint j = 0; j < rels->len; j++) { FwupdRelease *release = (FwupdRelease *)g_ptr_array_index(rels, j); if (!fwupd_release_get_description(release)) continue; longdescription += QStringLiteral("Version %1\n").arg(QString::fromUtf8(fwupd_release_get_version(release))); longdescription += QString::fromUtf8(fwupd_release_get_description(release)) + QLatin1Char('\n'); } res->setDescription(longdescription); addResourceToList(res); } } else { if (!g_error_matches(error2, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO)) { handleError(&error2); } } } } void FwupdBackend::addHistoricalUpdates() { g_autoptr(GError) error = nullptr; g_autoptr(FwupdDevice) device = fwupd_client_get_results(client, FWUPD_DEVICE_ID_ANY, nullptr, &error); if (!device) { handleError(&error); } else { FwupdResource* res = createRelease(device); if (!res) qWarning() << "Fwupd Error: Cannot Make App for" << fwupd_device_get_name(device); else { addResourceToList(res); } } } QByteArray FwupdBackend::getChecksum(const QString &filename, QCryptographicHash::Algorithm hashAlgorithm) { QFile f(filename); if (!f.open(QFile::ReadOnly)) return {}; QCryptographicHash hash(hashAlgorithm); if (!hash.addData(&f)) return {}; return hash.result().toHex(); } FwupdResource* FwupdBackend::createApp(FwupdDevice *device) { FwupdRelease *release = fwupd_device_get_release_default(device); FwupdResource* app = createRelease(device); if (!app->isLiveUpdatable) { qWarning() << "Fwupd Error: " << app->m_name << "[" << app->m_id << "]" << "cannot be updated "; return nullptr; } if (app->m_id.isNull()) { qWarning() << "Fwupd Error: No id for firmware"; return nullptr; } if (app->m_version.isNull()) { qWarning() << "Fwupd Error: No version! for " << app->m_id; return nullptr; } GPtrArray *checksums = fwupd_release_get_checksums(release); if (checksums->len == 0) { qWarning() << "Fwupd Error: " << app->m_name << "[" << app->m_id << "] has no checksums, ignoring as unsafe"; return nullptr; } const QUrl update_uri(QString::fromUtf8(fwupd_release_get_uri(release))); if (!update_uri.isValid()) { qWarning() << "Fwupd Error: No Update URI available for" << app->m_name << "[" << app->m_id << "]"; return nullptr; } /* Checking for firmware in the cache? */ const QString filename_cache = cacheFile(QStringLiteral("fwupd"), QFileInfo(update_uri.path()).fileName()); Q_ASSERT(!filename_cache.isEmpty()); /* Currently LVFS supports SHA1 only*/ const QByteArray checksum_tmp(fwupd_checksum_get_by_kind(checksums, G_CHECKSUM_SHA1)); const QByteArray checksum = getChecksum(filename_cache, QCryptographicHash::Sha1); if (checksum_tmp != checksum) { qWarning() << "Fwupd Error: " << filename_cache << " does not match checksum, expected" << checksum_tmp << "got" << checksum; QFile::remove(filename_cache); return nullptr; } /* link file to application and return its reference */ app->m_file = filename_cache; if (!app->needsReboot) app->setState(AbstractResource::Upgradeable); return app; } bool FwupdBackend::downloadFile(const QUrl &uri, const QString &filename) { Q_ASSERT(QThread::currentThread() != QCoreApplication::instance()->thread()); QScopedPointer manager(new QNetworkAccessManager); QEventLoop loop; QTimer getTimer; connect(&getTimer, &QTimer::timeout, &loop, &QEventLoop::quit); connect(manager.data(), &QNetworkAccessManager::finished, &loop, &QEventLoop::quit); QScopedPointer reply(manager->get(QNetworkRequest(uri))); getTimer.start(600000); // 60 Seconds TimeOout Period loop.exec(); if (!reply) { return false; } else if (QNetworkReply::NoError != reply->error() ) { qWarning() << "error fetching" << uri; return false; } else if (reply->error() == QNetworkReply::NoError) { QFile file(filename); if (file.open(QIODevice::WriteOnly)) { file.write(reply->readAll()); } else { qWarning() << "Fwupd Error: Cannot Open File to write Data" << filename; } } return true; } void FwupdBackend::refreshRemote(FwupdBackend* backend, FwupdRemote* remote, uint cacheAge) { if (!fwupd_remote_get_filename_cache_sig(remote)) { qWarning() << "Fwupd Error: " << "Remote " << fwupd_remote_get_id(remote) << "has no cache signature!"; return; } /* check cache age */ if (cacheAge > 0) { quint64 age = fwupd_remote_get_age(remote); uint tmp = age < std::numeric_limits::max() ? (uint) age : std::numeric_limits::max(); if (tmp < cacheAge) { // qDebug() << "Fwupd Info:" << fwupd_remote_get_id(remote) << "is only" << tmp << "seconds old, so ignoring refresh! "; return; } } const QString cacheId = QStringLiteral("fwupd/remotes.d/%1").arg(QString::fromUtf8(fwupd_remote_get_id(remote))); const auto basenameSig = QString::fromUtf8(g_path_get_basename(fwupd_remote_get_filename_cache_sig(remote))); const QString filenameSig = cacheFile(cacheId, basenameSig); if (filenameSig.isEmpty()) return; /* download the signature first*/ const QUrl urlSig(QString::fromUtf8(fwupd_remote_get_metadata_uri_sig(remote))); const QString filenameSigTmp(filenameSig + QStringLiteral(".tmp")); if (!downloadFile(urlSig, filenameSigTmp)) { qWarning() << "failed to download" << urlSig; return; } Q_ASSERT(QFile::exists(filenameSigTmp)); const auto checksum = fwupd_remote_get_checksum(remote); const QCryptographicHash::Algorithm hashAlgorithm = gchecksumToQChryptographicHash()[fwupd_checksum_guess_kind(checksum)]; const QByteArray hash = getChecksum(filenameSigTmp, hashAlgorithm); const QByteArray oldHash = getChecksum(filenameSig, hashAlgorithm); if (oldHash == hash) { qDebug() << "remote hasn't changed:" << fwupd_remote_get_id(remote); QFile::remove(filenameSigTmp); return; } QFile::remove(filenameSig); if (!QFile::rename(filenameSigTmp, filenameSig)) { QFile::remove(filenameSigTmp); qWarning() << "Fwupd Error: cannot save remote signature" << filenameSigTmp << "to" << filenameSig; return; } QFile::remove(filenameSigTmp); const auto basename = QString::fromUtf8(g_path_get_basename(fwupd_remote_get_filename_cache(remote))); const QString filename = cacheFile(cacheId, basename); if (filename.isEmpty()) return; qDebug() << "Fwupd Info: saving new firmware metadata to:" << filename; const QUrl url(QString::fromUtf8(fwupd_remote_get_metadata_uri(remote))); if (!downloadFile(url, filename)) { qWarning() << "Fwupd Error: cannot download file:" << filename; return; } g_autoptr(GError) error = nullptr; if (!fwupd_client_update_metadata(backend->client, fwupd_remote_get_id(remote), filename.toUtf8().constData(), filenameSig.toUtf8().constData(), nullptr, &error)) { backend->handleError(&error); } } void FwupdBackend::handleError(GError **perror) { //TODO: localise the error message if ((*perror)->code != FWUPD_ERROR_NOTHING_TO_DO) { const QString msg = QString::fromUtf8((*perror)->message); QTimer::singleShot(0, this, [this, msg](){ Q_EMIT passiveMessage(msg); }); } qWarning() << "Fwupd Error" << (*perror)->code << (*perror)->message; } QString FwupdBackend::cacheFile(const QString &kind, const QString &basename) { const QDir cacheDir(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); const QString cacheDirFile = cacheDir.filePath(kind); if (!QFileInfo::exists(cacheDirFile) && !cacheDir.mkpath(kind)) { qWarning() << "Fwupd Error: cannot make cache directory!"; return {}; } return cacheDir.filePath(kind + QLatin1Char('/') + basename); } void FwupdBackend::checkForUpdates() { if (m_fetching) return; auto fw = new QFutureWatcher(this); fw->setFuture(QtConcurrent::run([this] () -> GPtrArray* { const uint cacheAge = (24*60*60); // Check for updates every day g_autoptr(GError) error = nullptr; /* get devices */ GPtrArray* devices = fwupd_client_get_devices(client, nullptr, nullptr); g_autoptr(GPtrArray) remotes = fwupd_client_get_remotes(client, nullptr, &error); for(uint i = 0; remotes && i < remotes->len; i++) { FwupdRemote *remote = (FwupdRemote *)g_ptr_array_index(remotes, i); if (!fwupd_remote_get_enabled(remote)) continue; if (fwupd_remote_get_kind(remote) == FWUPD_REMOTE_KIND_LOCAL) continue; refreshRemote(this, remote, cacheAge); } return devices; } )); connect(fw, &QFutureWatcher::finished, this, [this, fw]() { m_fetching = true; emit fetchingChanged(); auto devices = fw->result(); for(uint i = 0; devices && i < devices->len; i++) { FwupdDevice *device = (FwupdDevice *) g_ptr_array_index(devices, i); addResourceToList(createDevice(device)); } g_ptr_array_unref(devices); addUpdates(); addHistoricalUpdates(); m_fetching = false; emit fetchingChanged(); emit initialized(); fw->deleteLater(); }); } int FwupdBackend::updatesCount() const { return m_updater->updatesCount(); } ResultsStream* FwupdBackend::search(const AbstractResourcesBackend::Filters& filter) { if (filter.resourceUrl.scheme() == QLatin1String("fwupd")) { return findResourceByPackageName(filter.resourceUrl); } else if (!filter.resourceUrl.isEmpty()) { return new ResultsStream(QStringLiteral("FwupdStream-void"), {}); } auto stream = new ResultsStream(QStringLiteral("FwupdStream")); auto f = [this, stream, filter] () { QVector ret; foreach(AbstractResource* r, m_resources) { if (r->state() < filter.state) continue; if (filter.search.isEmpty() || r->name().contains(filter.search, Qt::CaseInsensitive) || r->comment().contains(filter.search, Qt::CaseInsensitive)) { ret += r; } } if (!ret.isEmpty()) Q_EMIT stream->resourcesFound(ret); stream->finish(); }; if (isFetching()) { connect(this, &FwupdBackend::initialized, stream, f); } else { QTimer::singleShot(0, this, f); } return stream; } ResultsStream * FwupdBackend::findResourceByPackageName(const QUrl& search) { auto res = search.scheme() == QLatin1String("fwupd") ? m_resources.value(search.host().replace(QLatin1Char('.'), QLatin1Char(' '))) : nullptr; if (!res) { return new ResultsStream(QStringLiteral("FwupdStream"), {}); } else return new ResultsStream(QStringLiteral("FwupdStream"), { res }); } AbstractBackendUpdater* FwupdBackend::backendUpdater() const { return m_updater; } AbstractReviewsBackend* FwupdBackend::reviewsBackend() const { return nullptr; } Transaction* FwupdBackend::installApplication(AbstractResource* app, const AddonList& addons) { Q_ASSERT(addons.isEmpty()); return installApplication(app); } Transaction* FwupdBackend::installApplication(AbstractResource* app) { return new FwupdTransaction(qobject_cast(app), this); } Transaction* FwupdBackend::removeApplication(AbstractResource* /*app*/) { qWarning() << "should not have reached here, it's not possible to uninstall a firmware"; return nullptr; } AbstractResource * FwupdBackend::resourceForFile(const QUrl& path) { g_autoptr(GError) error = nullptr; QMimeDatabase db; QMimeType type = db.mimeTypeForFile(path.fileName()); FwupdResource* app = nullptr; if (type.isValid() && type.inherits(QStringLiteral("application/vnd.ms-cab-compressed"))) { g_autofree gchar *filename = path.fileName().toUtf8().data(); g_autoptr(GPtrArray) devices = fwupd_client_get_details(client, filename, nullptr, &error); if (devices) { FwupdDevice *device = (FwupdDevice *)g_ptr_array_index(devices, 0); app = createRelease(device); app->setState(AbstractResource::None); for(uint i = 1; i < devices->len; i++) { FwupdDevice *device = (FwupdDevice *)g_ptr_array_index(devices, i); FwupdResource* app_ = createRelease(device); app_->setState(AbstractResource::None); } addResourceToList(app); connect(app, &FwupdResource::stateChanged, this, &FwupdBackend::updatesCountChanged); } else { handleError(&error); } } return app; } QString FwupdBackend::displayName() const { return QStringLiteral("Firmware Updates"); } bool FwupdBackend::hasApplications() const { return false; } #include "FwupdBackend.moc" diff --git a/libdiscover/backends/FwupdBackend/FwupdBackend.h b/libdiscover/backends/FwupdBackend/FwupdBackend.h index c932025b..c18f5cf7 100644 --- a/libdiscover/backends/FwupdBackend/FwupdBackend.h +++ b/libdiscover/backends/FwupdBackend/FwupdBackend.h @@ -1,110 +1,108 @@ /*************************************************************************** * Copyright © 2013 Aleix Pol Gonzalez * * Copyright © 2018 Abhijeet Sharma * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #ifndef FWUPDBACKEND_H #define FWUPDBACKEND_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include } #include class QAction; class StandardBackendUpdater; class FwupdResource; class FwupdBackend : public AbstractResourcesBackend { Q_OBJECT Q_PROPERTY(int startElements MEMBER m_startElements) Q_ENUMS(Modes) public: explicit FwupdBackend(QObject* parent = nullptr); ~FwupdBackend(); int updatesCount() const override; AbstractBackendUpdater* backendUpdater() const override; AbstractReviewsBackend* reviewsBackend() const override; ResultsStream* search(const AbstractResourcesBackend::Filters & search) override; ResultsStream * findResourceByPackageName(const QUrl& search) ; QHash resources() const { return m_resources; } bool isValid() const override { return true; } // No external file dependencies that could cause runtime errors Transaction* installApplication(AbstractResource* app) override; Transaction* installApplication(AbstractResource* app, const AddonList& addons) override; Transaction* removeApplication(AbstractResource* app) override; bool isFetching() const override { return m_fetching; } AbstractResource * resourceForFile(const QUrl & ) override; void checkForUpdates() override; QString displayName() const override; bool hasApplications() const override; FwupdClient *client; void handleError(GError **perror); Q_SIGNALS: void initialized(); private: void refreshRemotes(); - FwupdResource * createRelease(FwupdDevice *device); - FwupdResource * createApp(FwupdDevice *device); void addUpdates(); void addResourceToList(FwupdResource *res); void addHistoricalUpdates(); - static void setReleaseDetails(FwupdResource *res, FwupdRelease *release); QSet getAllUpdates(); static QMap gchecksumToQChryptographicHash(); static QString cacheFile(const QString &kind, const QString &baseName); static void refreshRemote(FwupdBackend* backend, FwupdRemote *remote, uint cacheAge); static QByteArray getChecksum(const QString &filename, QCryptographicHash::Algorithm hashAlgorithm); static bool downloadFile(const QUrl &uri, const QString &filename); - static QString buildDeviceID(FwupdDevice* device); - static void setDeviceDetails(FwupdResource *res, FwupdDevice *device); + static FwupdResource * createDevice(FwupdDevice *device); + FwupdResource * createRelease(FwupdDevice *device); + FwupdResource * createApp(FwupdDevice *device); QHash m_resources; StandardBackendUpdater* m_updater; bool m_fetching = false; int m_startElements; QList m_toUpdate; }; #endif // FWUPDBACKEND_H diff --git a/libdiscover/backends/FwupdBackend/FwupdResource.cpp b/libdiscover/backends/FwupdBackend/FwupdResource.cpp index c813365a..db2b4298 100644 --- a/libdiscover/backends/FwupdBackend/FwupdResource.cpp +++ b/libdiscover/backends/FwupdBackend/FwupdResource.cpp @@ -1,194 +1,241 @@ /*************************************************************************** * Copyright © 2013 Aleix Pol Gonzalez * * Copyright © 2018 Abhijeet Sharma * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "FwupdResource.h" #include #include #include #include FwupdResource::FwupdResource(QString name, AbstractResourcesBackend* parent) : AbstractResource(parent) , m_name(std::move(name)) , m_state(State::Broken) { Q_ASSERT(!m_name.isEmpty()); setObjectName(m_name); } QList FwupdResource::addonsInformation() { return m_addons; } QString FwupdResource::availableVersion() const { return m_version; } -QStringList FwupdResource::allResourceNames() const -{ - return { m_name }; -} - QStringList FwupdResource::categories() { return m_categories; } QString FwupdResource::comment() { return m_summary; } int FwupdResource::size() { return m_size; } QUrl FwupdResource::homepage() { return m_homepage; } QUrl FwupdResource::helpURL() { return {}; } QUrl FwupdResource::bugURL() { return {}; } QUrl FwupdResource::donationURL() { return {}; } QVariant FwupdResource::icon() const { return m_iconName; } QString FwupdResource::installedVersion() const { return m_version; } QString FwupdResource::license() { return m_license; } QString FwupdResource::longDescription() { return m_description; } QString FwupdResource::name() const { return m_name; } QString FwupdResource::vendor() const { return m_vendor; } QString FwupdResource::origin() const { return m_origin; } QString FwupdResource::packageName() const { return m_name; } QString FwupdResource::section() { return QStringLiteral("Firmware Updates"); } AbstractResource::State FwupdResource::state() { return m_state; } void FwupdResource::fetchChangelog() { QString log = longDescription(); log.replace(QLatin1Char('\n'), QLatin1String("
")); emit changelogFetched(log); } void FwupdResource::setState(AbstractResource::State state) { if(m_state != state) { m_state = state; emit stateChanged(); } } void FwupdResource::setAddons(const AddonList& addons) { Q_FOREACH(const QString& toInstall, addons.addonsToInstall()) { setAddonInstalled(toInstall, true); } Q_FOREACH(const QString& toRemove, addons.addonsToRemove()) { setAddonInstalled(toRemove, false); } } void FwupdResource::setAddonInstalled(const QString& addon, bool installed) { for(auto & elem : m_addons) { if(elem.name() == addon) { elem.setInstalled(installed); } } } void FwupdResource::invokeApplication() const { qWarning() << "Not Launchable"; } QUrl FwupdResource::url() const { return m_homepage; } QString FwupdResource::executeLabel() const { - return i18n("Not Invokable"); + return QStringLiteral("Not Invokable"); +} + +void FwupdResource::setReleaseDetails(FwupdRelease* release) +{ + m_origin = QString::fromUtf8(fwupd_release_get_remote_id(release)); + m_summary = QString::fromUtf8(fwupd_release_get_summary(release)); + m_vendor = QString::fromUtf8(fwupd_release_get_vendor(release)); + m_size = fwupd_release_get_size(release); + m_version = QString::fromUtf8(fwupd_release_get_version(release)); + m_description = QString::fromUtf8((fwupd_release_get_description(release))); + m_homepage = QUrl(QString::fromUtf8(fwupd_release_get_homepage(release))); + m_license = QString::fromUtf8(fwupd_release_get_license(release)); + m_updateURI = QString::fromUtf8(fwupd_release_get_uri(release)); +} + +void FwupdResource::setDeviceDetails(FwupdDevice* dev) +{ + isLiveUpdatable = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_UPDATABLE); + isOnlyOffline = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_ONLY_OFFLINE); + needsReboot = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_NEEDS_REBOOT); + isDeviceRemoval = !fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_INTERNAL); + needsBootLoader = fwupd_device_has_flag(dev, FWUPD_DEVICE_FLAG_NEEDS_BOOTLOADER); + + GPtrArray *guids = fwupd_device_get_guids(dev); + if (guids->len > 0) + { + QString guidStr = QString::fromUtf8((char *)g_ptr_array_index(guids, 0)); + for(uint i = 1; i < guids->len; i++) + { + guidStr += QLatin1Char(',') + QString::fromUtf8((char *)g_ptr_array_index(guids, i)); + } + guidString = guidStr; + } + if (fwupd_device_get_name(dev)) + { + QString vendorDesc = QString::fromUtf8(fwupd_device_get_name(dev)); + const QString vendorName = QString::fromUtf8(fwupd_device_get_vendor(dev)); + + if (!vendorDesc.startsWith(vendorName)) + vendorDesc = vendorName + QLatin1Char(' ') + vendorDesc; + m_name = vendorDesc; + } + m_summary = QString::fromUtf8(fwupd_device_get_summary(dev)); + m_vendor = QString::fromUtf8(fwupd_device_get_vendor(dev)); + m_releaseDate = QDateTime::fromSecsSinceEpoch(fwupd_device_get_created(dev)).date(); + m_version = QString::fromUtf8(fwupd_device_get_version(dev)); + m_description = QString::fromUtf8((fwupd_device_get_description(dev))); + + if (fwupd_device_get_icons(dev)->len >= 1) + m_iconName = QString::fromUtf8((const gchar *)g_ptr_array_index(fwupd_device_get_icons(dev), 0));// Check wether given icon exists or not! + else + m_iconName = QString::fromUtf8("device-notifier"); } diff --git a/libdiscover/backends/FwupdBackend/FwupdResource.h b/libdiscover/backends/FwupdBackend/FwupdResource.h index 6edc067d..d26d8eba 100644 --- a/libdiscover/backends/FwupdBackend/FwupdResource.h +++ b/libdiscover/backends/FwupdBackend/FwupdResource.h @@ -1,117 +1,104 @@ /*************************************************************************** * Copyright © 2013 Aleix Pol Gonzalez * * Copyright © 2018 Abhijeet Sharma * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License or (at your option) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #ifndef FWUPDRESOURCE_H #define FWUPDRESOURCE_H #include "FwupdBackend.h" #include #include class AddonList; class FwupdResource : public AbstractResource { Q_OBJECT public: explicit FwupdResource(QString name, AbstractResourcesBackend* parent); QList addonsInformation() override; QString section() override; QString origin() const override; QString longDescription() override; QString availableVersion() const override; QString installedVersion() const override; QString license() override; int size() override; QUrl homepage() override; QUrl helpURL() override; QUrl bugURL() override; QUrl donationURL() override; QStringList categories() override; AbstractResource::State state() override; QVariant icon() const override; QString comment() override; QString name() const override; QString packageName() const override; QString vendor() const; bool isTechnical() const override { return true; } bool canExecute() const override { return false; } void invokeApplication() const override; void fetchChangelog() override; QUrl url() const override; QString executeLabel() const override; + QDate releaseDate() const override { return m_releaseDate; } + QString sourceIcon() const override { return {}; } + void setDeviceID(const QString &deviceId) { m_deviceID = deviceId; } + void setIsDeviceLocked(bool locked) { isDeviceLocked = locked; } + void setDescription(const QString &description) { m_description = description; } + void setId(const QString &id) { m_id = id; } - void setState(State state); - void setSize(int size) { m_size = size; } - void setAddons(const AddonList& addons); - void setId(const QString &id){m_id = id;} - void setName(const QString &name){ m_name = name;} - void setSummary(const QString &summary){ m_summary = summary;} - void setDescription(const QString &description){ m_description = description;} - void setVersion(const QString &version){ m_version = version;} - void setVendor(const QString &vendor){ m_vendor = vendor;} - void setHomePage(const QUrl &homepage){ m_homepage = homepage;} - void setLicense(const QString &license){ m_license = license;} - void setIconName(const QString &iconName){ m_iconName = iconName;} - void setReleaseDate(const QDate &date){ m_releaseDate = date;} - void setOrigin(const QString &origin){ m_origin = origin;} - virtual QStringList allResourceNames() const; - - void setIsDeviceLocked(bool status){ isDeviceLocked = status;} - void setDeviceID(const QString &deviceID){ m_deviceID = deviceID;} - void setUpdateURI(const QString &updateURI){m_updateURI = updateURI;} - + void setState(AbstractResource::State state); void setAddonInstalled(const QString& addon, bool installed); - QString sourceIcon() const override { return m_iconName; } - QDate releaseDate() const override { return m_releaseDate; } + void setReleaseDetails(FwupdRelease *release); + void setDeviceDetails(FwupdDevice* device); public: QString m_id; QString m_name; QString m_summary; QString m_description; QString m_version; QString m_vendor; QStringList m_categories; QString m_license; QDate m_releaseDate; AbstractResource::State m_state; QUrl m_homepage; QString m_iconName; QList m_addons; - int m_size; + int m_size = 0; QString m_deviceID; QString m_updateURI; QString m_file; bool isDeviceLocked = false; // True if device is locked! bool isOnlyOffline = false; // True if only offline updates bool isLiveUpdatable = false; // True if device is live updatable bool needsReboot = false; // True if device needs Reboot bool isDeviceRemoval = false; //True if device is Removal bool needsBootLoader = false; //True if BootLoader Required QString guidString; QString m_origin; }; #endif // FWUPDRESOURCE_H