diff --git a/app/app.pri b/app/app.pri index 21388a6a3eab19e9f25988883e0f9348f2d16a11..737e3eba34ea71dcc522e3e8a1f466a72023b313 100644 --- a/app/app.pri +++ b/app/app.pri @@ -9,7 +9,7 @@ HEADERS += \ $${PWD}/src/websockets/websocketserver.h \ $${PWD}/src/handlers/confighandler.h \ $${PWD}/src/handlers/systemhandler.h \ - $${PWD}/src/handlers/ocshandler.h \ + $${PWD}/src/handlers/ocsapihandler.h \ $${PWD}/src/handlers/itemhandler.h SOURCES += \ @@ -17,7 +17,7 @@ SOURCES += \ $${PWD}/src/websockets/websocketserver.cpp \ $${PWD}/src/handlers/confighandler.cpp \ $${PWD}/src/handlers/systemhandler.cpp \ - $${PWD}/src/handlers/ocshandler.cpp \ + $${PWD}/src/handlers/ocsapihandler.cpp \ $${PWD}/src/handlers/itemhandler.cpp RESOURCES += $${PWD}/configs/configs.qrc diff --git a/app/src/handlers/itemhandler.cpp b/app/src/handlers/itemhandler.cpp index eb11a85d3665072ae5e888e13a98fe7da9a7806c..e7e7c8273160ef63cd9963bd2968fe1713c58761 100644 --- a/app/src/handlers/itemhandler.cpp +++ b/app/src/handlers/itemhandler.cpp @@ -1,5 +1,6 @@ #include "itemhandler.h" +#include <QUrlQuery> #include <QJsonValue> #include <QJsonArray> #include <QFileInfo> @@ -25,15 +26,20 @@ QJsonObject ItemHandler::metadataSet() const return metadataSet_; } -void ItemHandler::download(const QString &url, const QString &installType, const QString &providerKey, const QString &contentId) +void ItemHandler::getItem(const QString &command, const QString &url, const QString &installType, const QString &filename, + const QString &providerKey, const QString &contentId) { // Use URL as unique key for metadata, network resource, and installed item QString itemKey = url; QJsonObject metadata; + metadata["command"] = command; metadata["url"] = url; - metadata["filename"] = QUrl(url).fileName(); metadata["install_type"] = installType; + metadata["filename"] = filename; + if (filename.isEmpty()) { + metadata["filename"] = QUrl(url).fileName(); + } metadata["provider"] = providerKey; metadata["content_id"] = contentId; metadata["files"] = QJsonArray(); @@ -64,6 +70,57 @@ void ItemHandler::download(const QString &url, const QString &installType, const emit downloadStarted(result); } +void ItemHandler::getItemByOcsUrl(const QString &ocsUrl) +{ + QUrl ocsUrlObj(ocsUrl); + QUrlQuery query(ocsUrlObj); + + QString scheme = "ocs"; + QString command = "download"; + QString url = ""; + QString type = "downloads"; + QString filename = ""; + + if (!ocsUrlObj.scheme().isEmpty()) { + scheme = ocsUrlObj.scheme(); + } + + if (!ocsUrlObj.host().isEmpty()) { + command = ocsUrlObj.host(); + } + + if (query.hasQueryItem("url") && !query.queryItemValue("url").isEmpty()) { + url = query.queryItemValue("url", QUrl::FullyDecoded); + } + + if (query.hasQueryItem("type") && !query.queryItemValue("type").isEmpty()) { + type = query.queryItemValue("type", QUrl::FullyDecoded); + } + + if (query.hasQueryItem("filename") && !query.queryItemValue("filename").isEmpty()) { + filename = QUrl(query.queryItemValue("filename", QUrl::FullyDecoded)).fileName(); + } + + if (!url.isEmpty() && filename.isEmpty()) { + filename = QUrl(url).fileName(); + } + + // Still support xdg and xdgs schemes for backward compatibility + if ((scheme == "ocs" || scheme == "ocss" || scheme == "xdg" || scheme == "xdgs") + && (command == "download" || command == "install") + && QUrl(url).isValid() + && configHandler_->getAppConfigInstallTypes().contains(type) + && !filename.isEmpty()) { + getItem(command, url, type, filename); + } + else { + QJsonObject result; + result["status"] = QString("error_downloadstart"); + result["message"] = tr("Invalid OCS-URL"); + emit downloadStarted(result); + } +} + void ItemHandler::uninstall(const QString &itemKey) { QJsonObject result; @@ -165,7 +222,12 @@ void ItemHandler::networkResourceFinished(qtlib::NetworkResource *resource) result["message"] = tr("Downloaded"); emit downloadFinished(result); - install(resource); + if (metadata["command"].toString() == "download") { + saveDownloadedFile(resource); + } + else if (metadata["command"].toString() == "install") { + installDownloadedFile(resource); + } } void ItemHandler::setMetadataSet(const QJsonObject &metadataSet) @@ -174,7 +236,45 @@ void ItemHandler::setMetadataSet(const QJsonObject &metadataSet) emit metadataSetChanged(); } -void ItemHandler::install(qtlib::NetworkResource *resource) +void ItemHandler::saveDownloadedFile(qtlib::NetworkResource *resource) +{ + QString itemKey = resource->id(); + + QJsonObject itemMetadataSet = metadataSet(); + QJsonObject metadata = itemMetadataSet[itemKey].toObject(); + + itemMetadataSet.remove(itemKey); + setMetadataSet(itemMetadataSet); + + QJsonObject result; + result["metadata"] = metadata; + result["status"] = QString("success_savestart"); + result["message"] = tr("Saving"); + emit saveStarted(result); + + QString filename = metadata["filename"].toString(); + QString installType = metadata["install_type"].toString(); + + qtlib::Dir destDir(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString()); + destDir.make(); + qtlib::File destFile(destDir.path() + "/" + filename); + + if (!resource->saveData(destFile.path())) { + result["status"] = QString("error_save"); + result["message"] = tr("Failed to save data"); + emit saveFinished(result); + resource->deleteLater(); + return; + } + + result["status"] = QString("success_save"); + result["message"] = tr("Saved"); + emit saveFinished(result); + + resource->deleteLater(); +} + +void ItemHandler::installDownloadedFile(qtlib::NetworkResource *resource) { // Installation pre-process QString itemKey = resource->id(); @@ -187,9 +287,9 @@ void ItemHandler::install(qtlib::NetworkResource *resource) QJsonObject result; result["metadata"] = metadata; - result["status"] = QString("success_installstart"); - result["message"] = tr("Installing"); - emit installStarted(result); + result["status"] = QString("success_savestart"); + result["message"] = tr("Saving"); + emit saveStarted(result); QString filename = metadata["filename"].toString(); QString installType = metadata["install_type"].toString(); @@ -202,15 +302,23 @@ void ItemHandler::install(qtlib::NetworkResource *resource) qtlib::Package package(tempDir.path() + "/" + filename); if (!resource->saveData(package.path())) { - result["status"] = QString("error_install"); + result["status"] = QString("error_save"); result["message"] = tr("Failed to save data"); - emit installFinished(result); + emit saveFinished(result); tempDir.remove(); resource->deleteLater(); return; } + result["status"] = QString("success_save"); + result["message"] = tr("Saved"); + emit saveFinished(result); + // Installation main-process + result["status"] = QString("success_installstart"); + result["message"] = tr("Installing"); + emit installStarted(result); + qtlib::Dir destDir; #ifdef QTLIB_UNIX destDir.setPath(configHandler_->getAppConfigInstallTypes()[installType].toObject()["destination"].toString()); @@ -295,6 +403,7 @@ void ItemHandler::install(qtlib::NetworkResource *resource) } // Installation post-process + metadata.remove("command"); metadata["files"] = installedFiles; metadata["installed_at"] = QDateTime::currentMSecsSinceEpoch(); configHandler_->setUsrConfigInstalledItemsItem(itemKey, metadata); diff --git a/app/src/handlers/itemhandler.h b/app/src/handlers/itemhandler.h index b7bd685309743fe145af708fa0224f7234db682b..5f378c4dbc385704a2a7a5c69890b8b585e23f66 100644 --- a/app/src/handlers/itemhandler.h +++ b/app/src/handlers/itemhandler.h @@ -21,6 +21,8 @@ signals: void downloadStarted(QJsonObject result); void downloadFinished(QJsonObject result); void downloadProgress(QString id, qint64 bytesReceived, qint64 bytesTotal); + void saveStarted(QJsonObject result); + void saveFinished(QJsonObject result); void installStarted(QJsonObject result); void installFinished(QJsonObject result); void uninstallStarted(QJsonObject result); @@ -29,7 +31,9 @@ signals: public slots: QJsonObject metadataSet() const; - void download(const QString &url, const QString &installType, const QString &providerKey = "", const QString &contentId = ""); + void getItem(const QString &command, const QString &url, const QString &installType, const QString &filename = "", + const QString &providerKey = "", const QString &contentId = ""); + void getItemByOcsUrl(const QString &ocsUrl); void uninstall(const QString &itemKey); private slots: @@ -38,7 +42,8 @@ private slots: private: void setMetadataSet(const QJsonObject &metadataSet); - void install(qtlib::NetworkResource *resource); + void saveDownloadedFile(qtlib::NetworkResource *resource); + void installDownloadedFile(qtlib::NetworkResource *resource); ConfigHandler *configHandler_; QJsonObject metadataSet_; diff --git a/app/src/handlers/ocshandler.cpp b/app/src/handlers/ocsapihandler.cpp similarity index 89% rename from app/src/handlers/ocshandler.cpp rename to app/src/handlers/ocsapihandler.cpp index d82a900705c51128149039ec1555ecaa65534825..310ed88a5e7fe20c2a858b7a23de316fe341867d 100644 --- a/app/src/handlers/ocshandler.cpp +++ b/app/src/handlers/ocsapihandler.cpp @@ -1,4 +1,4 @@ -#include "ocshandler.h" +#include "ocsapihandler.h" #include <QJsonValue> @@ -6,11 +6,11 @@ #include "handlers/confighandler.h" -OcsHandler::OcsHandler(ConfigHandler *configHandler, QObject *parent) +OcsApiHandler::OcsApiHandler(ConfigHandler *configHandler, QObject *parent) : QObject(parent), configHandler_(configHandler) {} -bool OcsHandler::addProviders(const QString &providerFileUrl) +bool OcsApiHandler::addProviders(const QString &providerFileUrl) { QJsonArray providers = qtlib::OcsApi::getProviderFile(QUrl(providerFileUrl)); if (!providers.isEmpty()) { @@ -29,7 +29,7 @@ bool OcsHandler::addProviders(const QString &providerFileUrl) return false; } -bool OcsHandler::removeProvider(const QString &providerKey) +bool OcsApiHandler::removeProvider(const QString &providerKey) { if (configHandler_->removeUsrConfigProvidersProvider(providerKey)) { configHandler_->removeUsrConfigCategoriesProvider(providerKey); @@ -38,7 +38,7 @@ bool OcsHandler::removeProvider(const QString &providerKey) return false; } -bool OcsHandler::updateAllCategories(bool force) +bool OcsApiHandler::updateAllCategories(bool force) { QJsonObject providers = configHandler_->getUsrConfigProviders(); if (!providers.isEmpty()) { @@ -50,7 +50,7 @@ bool OcsHandler::updateAllCategories(bool force) return false; } -bool OcsHandler::updateCategories(const QString &providerKey, bool force) +bool OcsApiHandler::updateCategories(const QString &providerKey, bool force) { QJsonObject providers = configHandler_->getUsrConfigProviders(); @@ -133,9 +133,9 @@ bool OcsHandler::updateCategories(const QString &providerKey, bool force) return configHandler_->setUsrConfigCategoriesProvider(providerKey, newProviderCategories); } -QJsonObject OcsHandler::getContents(const QString &providerKeys, const QString &categoryKeys, - const QString &xdgTypes, const QString &packageTypes, - const QString &search, const QString &sortmode, int pagesize, int page) +QJsonObject OcsApiHandler::getContents(const QString &providerKeys, const QString &categoryKeys, + const QString &xdgTypes, const QString &packageTypes, + const QString &search, const QString &sortmode, int pagesize, int page) { QJsonObject responseSet; @@ -191,7 +191,7 @@ QJsonObject OcsHandler::getContents(const QString &providerKeys, const QString & return responseSet; } -QJsonObject OcsHandler::getContent(const QString &providerKey, const QString &contentId) +QJsonObject OcsApiHandler::getContent(const QString &providerKey, const QString &contentId) { QJsonObject response; QJsonObject providers = configHandler_->getUsrConfigProviders(); diff --git a/app/src/handlers/ocshandler.h b/app/src/handlers/ocsapihandler.h similarity index 87% rename from app/src/handlers/ocshandler.h rename to app/src/handlers/ocsapihandler.h index 72b4853817297bab6a71309a1384fdebe2b1fbf3..4e4d3095e50f985c7c39f392eaccc85bdc719e5a 100644 --- a/app/src/handlers/ocshandler.h +++ b/app/src/handlers/ocsapihandler.h @@ -5,12 +5,12 @@ class ConfigHandler; -class OcsHandler : public QObject +class OcsApiHandler : public QObject { Q_OBJECT public: - explicit OcsHandler(ConfigHandler *configHandler, QObject *parent = 0); + explicit OcsApiHandler(ConfigHandler *configHandler, QObject *parent = 0); public slots: bool addProviders(const QString &providerFileUrl); diff --git a/app/src/websockets/websocketserver.cpp b/app/src/websockets/websocketserver.cpp index 793ac1f8952c43827cde1f67ef388aad838db4be..857c9e9e7496aee7551c855bd63aabad11c3ba5f 100644 --- a/app/src/websockets/websocketserver.cpp +++ b/app/src/websockets/websocketserver.cpp @@ -8,7 +8,7 @@ #include "handlers/confighandler.h" #include "handlers/systemhandler.h" -#include "handlers/ocshandler.h" +#include "handlers/ocsapihandler.h" #include "handlers/itemhandler.h" WebSocketServer::WebSocketServer(ConfigHandler *configHandler, const QString &serverName, quint16 serverPort, QObject *parent) @@ -20,12 +20,14 @@ WebSocketServer::WebSocketServer(ConfigHandler *configHandler, const QString &se configHandler_->setParent(this); systemHandler_ = new SystemHandler(this); - ocsHandler_ = new OcsHandler(configHandler_, this); + ocsApiHandler_ = new OcsApiHandler(configHandler_, this); itemHandler_ = new ItemHandler(configHandler_, this); connect(itemHandler_, &ItemHandler::metadataSetChanged, this, &WebSocketServer::itemMetadataSetChanged); connect(itemHandler_, &ItemHandler::downloadStarted, this, &WebSocketServer::itemDownloadStarted); connect(itemHandler_, &ItemHandler::downloadFinished, this, &WebSocketServer::itemDownloadFinished); connect(itemHandler_, &ItemHandler::downloadProgress, this, &WebSocketServer::itemDownloadProgress); + connect(itemHandler_, &ItemHandler::saveStarted, this, &WebSocketServer::itemSaveStarted); + connect(itemHandler_, &ItemHandler::saveFinished, this, &WebSocketServer::itemSaveFinished); connect(itemHandler_, &ItemHandler::installStarted, this, &WebSocketServer::itemInstallStarted); connect(itemHandler_, &ItemHandler::installFinished, this, &WebSocketServer::itemInstallFinished); connect(itemHandler_, &ItemHandler::uninstallStarted, this, &WebSocketServer::itemUninstallStarted); @@ -141,6 +143,20 @@ void WebSocketServer::itemDownloadProgress(QString id, qint64 bytesReceived, qin sendMessage("", "ItemHandler::downloadProgress", data); } +void WebSocketServer::itemSaveStarted(QJsonObject result) +{ + QJsonArray data; + data.append(result); + sendMessage("", "ItemHandler::saveStarted", data); +} + +void WebSocketServer::itemSaveFinished(QJsonObject result) +{ + QJsonArray data; + data.append(result); + sendMessage("", "ItemHandler::saveFinished", data); +} + void WebSocketServer::itemInstallStarted(QJsonObject result) { QJsonArray data; @@ -263,33 +279,37 @@ void WebSocketServer::receiveMessage(const QString &id, const QString &func, con resultData.append(false); #endif } - // OcsHandler - else if (func == "OcsHandler::addProviders") { - resultData.append(ocsHandler_->addProviders(data.at(0).toString())); + // OcsApiHandler + else if (func == "OcsApiHandler::addProviders") { + resultData.append(ocsApiHandler_->addProviders(data.at(0).toString())); } - else if (func == "OcsHandler::removeProvider") { - resultData.append(ocsHandler_->removeProvider(data.at(0).toString())); + else if (func == "OcsApiHandler::removeProvider") { + resultData.append(ocsApiHandler_->removeProvider(data.at(0).toString())); } - else if (func == "OcsHandler::updateAllCategories") { - resultData.append(ocsHandler_->updateAllCategories(data.at(0).toBool())); + else if (func == "OcsApiHandler::updateAllCategories") { + resultData.append(ocsApiHandler_->updateAllCategories(data.at(0).toBool())); } - else if (func == "OcsHandler::updateCategories") { - resultData.append(ocsHandler_->updateCategories(data.at(0).toString(), data.at(1).toBool())); + else if (func == "OcsApiHandler::updateCategories") { + resultData.append(ocsApiHandler_->updateCategories(data.at(0).toString(), data.at(1).toBool())); } - else if (func == "OcsHandler::getContents") { - resultData.append(ocsHandler_->getContents(data.at(0).toString(), data.at(1).toString(), - data.at(2).toString(), data.at(3).toString(), - data.at(4).toString(), data.at(5).toString(), data.at(6).toInt(), data.at(7).toInt())); + else if (func == "OcsApiHandler::getContents") { + resultData.append(ocsApiHandler_->getContents(data.at(0).toString(), data.at(1).toString(), + data.at(2).toString(), data.at(3).toString(), + data.at(4).toString(), data.at(5).toString(), data.at(6).toInt(), data.at(7).toInt())); } - else if (func == "OcsHandler::getContent") { - resultData.append(ocsHandler_->getContent(data.at(0).toString(), data.at(1).toString())); + else if (func == "OcsApiHandler::getContent") { + resultData.append(ocsApiHandler_->getContent(data.at(0).toString(), data.at(1).toString())); } // ItemHandler else if (func == "ItemHandler::metadataSet") { resultData.append(itemHandler_->metadataSet()); } - else if (func == "ItemHandler::download") { - itemHandler_->download(data.at(0).toString(), data.at(1).toString(), data.at(2).toString(), data.at(3).toString()); + else if (func == "ItemHandler::getItem") { + itemHandler_->getItem(data.at(0).toString(), data.at(1).toString(), data.at(2).toString(), data.at(3).toString(), + data.at(4).toString(), data.at(5).toString()); + } + else if (func == "ItemHandler::getItemByOcsUrl") { + itemHandler_->getItemByOcsUrl(data.at(0).toString()); } else if (func == "ItemHandler::uninstall") { itemHandler_->uninstall(data.at(0).toString()); diff --git a/app/src/websockets/websocketserver.h b/app/src/websockets/websocketserver.h index 698bd5c2b1fdd2794d35bfe501ff864ff2494ba7..6bcebf7c28fb7d6ee4987b04ff3a89ab378f0eff 100644 --- a/app/src/websockets/websocketserver.h +++ b/app/src/websockets/websocketserver.h @@ -10,7 +10,7 @@ class QWebSocket; class ConfigHandler; class SystemHandler; -class OcsHandler; +class OcsApiHandler; class ItemHandler; class WebSocketServer : public QObject @@ -42,6 +42,8 @@ private slots: void itemDownloadStarted(QJsonObject result); void itemDownloadFinished(QJsonObject result); void itemDownloadProgress(QString id, qint64 bytesReceived, qint64 bytesTotal); + void itemSaveStarted(QJsonObject result); + void itemSaveFinished(QJsonObject result); void itemInstallStarted(QJsonObject result); void itemInstallFinished(QJsonObject result); void itemUninstallStarted(QJsonObject result); @@ -53,7 +55,7 @@ private: ConfigHandler *configHandler_; SystemHandler *systemHandler_; - OcsHandler *ocsHandler_; + OcsApiHandler *ocsApiHandler_; ItemHandler *itemHandler_; QString serverName_;