diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index 0d66b365a2..f2690e0a7d 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_policy(SET CMP0046 OLD) include(ExternalProject) -set(QUAZIP_CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON) +set(QUAZIP_CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_PREFIX_PATH=${QT_CMAKE_PREFIX_PATH} -DCMAKE_INSTALL_NAME_DIR:PATH=/lib -DZLIB_ROOT=${ZLIB_ROOT} -DCMAKE_POSITION_INDEPENDENT_CODE=ON) if (APPLE) else () diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index ce672be604..a11fe74c58 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -727,7 +728,7 @@ void DomainServer::setupNodeListAndAssignments() { packetReceiver.registerListener(PacketType::OctreeDataPersist, this, "processOctreeDataPersistMessage"); packetReceiver.registerListener(PacketType::OctreeFileReplacement, this, "handleOctreeFileReplacementRequest"); - packetReceiver.registerListener(PacketType::OctreeFileReplacementFromUrl, this, "handleOctreeFileReplacementFromURLRequest"); + packetReceiver.registerListener(PacketType::DomainContentReplacementFromUrl, this, "handleDomainContentReplacementFromURLRequest"); // set a custom packetVersionMatch as the verify packet operator for the udt::Socket nodeList->setPacketFilterOperator(&DomainServer::isPacketVerified); @@ -736,7 +737,6 @@ void DomainServer::setupNodeListAndAssignments() { auto assetClient = DependencyManager::set(); assetClient->moveToThread(&_assetClientThread); _assetClientThread.start(); - // add whatever static assignments that have been parsed to the queue addStaticAssignmentsToQueue(); } @@ -2136,7 +2136,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url } else if (url.path().startsWith(URI_API_BACKUPS_ID)) { auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length()); auto deferred = makePromise("consolidateBackup"); - deferred->then([connectionPtr, JSON_MIME_TYPE](QString error, QVariantMap result) { + deferred->then([connectionPtr, JSON_MIME_TYPE, id](QString error, QVariantMap result) { if (!connectionPtr) { return; } @@ -2147,7 +2147,14 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url auto path = result["backupFilePath"].toString(); auto file { std::unique_ptr(new QFile(path)) }; if (file->open(QIODevice::ReadOnly)) { - connectionPtr->respond(HTTPConnection::StatusCode200, std::move(file)); + constexpr const char* CONTENT_TYPE_ZIP = "application/zip"; + + auto downloadedFilename = id; + downloadedFilename.replace(QRegularExpression(".zip$"), ".content.zip"); + auto contentDisposition = "attachment; filename=\"" + downloadedFilename + "\""; + connectionPtr->respond(HTTPConnection::StatusCode200, std::move(file), CONTENT_TYPE_ZIP, { + { "Content-Disposition", contentDisposition.toUtf8() } + }); } else { qCritical(domain_server) << "Unable to load consolidated backup at:" << path << result; connectionPtr->respond(HTTPConnection::StatusCode500, "Error opening backup"); @@ -3429,13 +3436,10 @@ void DomainServer::handleOctreeFileReplacement(QByteArray octreeFile) { } } -void DomainServer::handleOctreeFileReplacementFromURLRequest(QSharedPointer message) { +void DomainServer::handleDomainContentReplacementFromURLRequest(QSharedPointer message) { qInfo() << "Received request to replace content from a url"; auto node = DependencyManager::get()->findNodeWithAddr(message->getSenderSockAddr()); - if (node) { - qDebug() << "Found node: " << node->getCanReplaceContent(); - } - if (node->getCanReplaceContent()) { + if (node && node->getCanReplaceContent()) { // Convert message data into our URL QString url(message->getMessage()); QUrl modelsURL = QUrl(url, QUrl::StrictMode); @@ -3448,7 +3452,12 @@ void DomainServer::handleOctreeFileReplacementFromURLRequest(QSharedPointererror(); if (networkError == QNetworkReply::NoError) { - handleOctreeFileReplacement(reply->readAll()); + if (modelsURL.fileName().endsWith(".json.gz")) { + handleOctreeFileReplacement(reply->readAll()); + } else if (modelsURL.fileName().endsWith(".zip")) { + auto deferred = makePromise("recoverFromUploadedBackup"); + _contentManager->recoverFromUploadedBackup(deferred, reply->readAll()); + } } else { qDebug() << "Error downloading JSON from specified file: " << modelsURL; } @@ -3456,12 +3465,9 @@ void DomainServer::handleOctreeFileReplacementFromURLRequest(QSharedPointer message) { auto node = DependencyManager::get()->nodeWithUUID(message->getSourceID()); if (node->getCanReplaceContent()) { handleOctreeFileReplacement(message->readAll()); } -} +} \ No newline at end of file diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 6e9fe28c0a..b118008d3d 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -91,7 +91,7 @@ private slots: void processICEServerHeartbeatDenialPacket(QSharedPointer message); void processICEServerHeartbeatACK(QSharedPointer message); - void handleOctreeFileReplacementFromURLRequest(QSharedPointer message); + void handleDomainContentReplacementFromURLRequest(QSharedPointer message); void handleOctreeFileReplacementRequest(QSharedPointer message); void handleOctreeFileReplacement(QByteArray octreeFile); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc5adc170e..866e9d0599 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -351,6 +351,7 @@ static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; static const QString WEB_VIEW_TAG = "noDownload=true"; static const QString ZIP_EXTENSION = ".zip"; +static const QString CONTENT_ZIP_EXTENSION = ".content.zip"; static const float MIRROR_FULLSCREEN_DISTANCE = 0.389f; @@ -378,7 +379,7 @@ static const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; static const QString DOMAIN_SPAWNING_POINT = "/0, -10, 0"; -const QHash Application::_acceptedExtensions { +const std::vector> Application::_acceptedExtensions { { SVO_EXTENSION, &Application::importSVOFromURL }, { SVO_JSON_EXTENSION, &Application::importSVOFromURL }, { AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl }, @@ -386,6 +387,7 @@ const QHash Application::_acceptedExtensi { JS_EXTENSION, &Application::askToLoadScript }, { FST_EXTENSION, &Application::askToSetAvatarUrl }, { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, + { CONTENT_ZIP_EXTENSION, &Application::askToReplaceDomainContent }, { ZIP_EXTENSION, &Application::importFromZIP }, { JPG_EXTENSION, &Application::importImage }, { PNG_EXTENSION, &Application::importImage } @@ -6173,11 +6175,9 @@ bool Application::canAcceptURL(const QString& urlString) const { } else if (urlString.startsWith(HIFI_URL_SCHEME)) { return true; } - QHashIterator i(_acceptedExtensions); QString lowerPath = url.path().toLower(); - while (i.hasNext()) { - i.next(); - if (lowerPath.endsWith(i.key(), Qt::CaseInsensitive)) { + for (auto& pair : _acceptedExtensions) { + if (lowerPath.endsWith(pair.first, Qt::CaseInsensitive)) { return true; } } @@ -6194,12 +6194,10 @@ bool Application::acceptURL(const QString& urlString, bool defaultUpload) { } QUrl url(urlString); - QHashIterator i(_acceptedExtensions); QString lowerPath = url.path().toLower(); - while (i.hasNext()) { - i.next(); - if (lowerPath.endsWith(i.key(), Qt::CaseInsensitive)) { - AcceptURLMethod method = i.value(); + for (auto& pair : _acceptedExtensions) { + if (lowerPath.endsWith(pair.first, Qt::CaseInsensitive)) { + AcceptURLMethod method = pair.second; return (this->*method)(urlString); } } @@ -6386,13 +6384,11 @@ void Application::replaceDomainContent(const QString& url) { QByteArray urlData(url.toUtf8()); auto limitedNodeList = DependencyManager::get(); const auto& domainHandler = limitedNodeList->getDomainHandler(); - limitedNodeList->eachMatchingNode([](const SharedNodePointer& node) { - return node->getType() == NodeType::EntityServer && node->getActiveSocket(); - }, [&urlData, limitedNodeList, &domainHandler](const SharedNodePointer& octreeNode) { - auto octreeFilePacket = NLPacket::create(PacketType::OctreeFileReplacementFromUrl, urlData.size(), true); - octreeFilePacket->write(urlData); - limitedNodeList->sendPacket(std::move(octreeFilePacket), domainHandler.getSockAddr()); - }); + + auto octreeFilePacket = NLPacket::create(PacketType::DomainContentReplacementFromUrl, urlData.size(), true); + octreeFilePacket->write(urlData); + limitedNodeList->sendPacket(std::move(octreeFilePacket), domainHandler.getSockAddr()); + auto addressManager = DependencyManager::get(); addressManager->handleLookupString(DOMAIN_SPAWNING_POINT); QString newHomeAddress = addressManager->getHost() + DOMAIN_SPAWNING_POINT; diff --git a/interface/src/Application.h b/interface/src/Application.h index 3eed506ead..95aaa9b6cd 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -603,7 +603,7 @@ private: GLCanvas* _glWidget{ nullptr }; typedef bool (Application::* AcceptURLMethod)(const QString &); - static const QHash _acceptedExtensions; + static const std::vector> _acceptedExtensions; glm::uvec2 _renderResolution; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 98a9087d37..09fd31a41e 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -121,7 +121,7 @@ public: ReplicatedAvatarIdentity, ReplicatedKillAvatar, ReplicatedBulkAvatarData, - OctreeFileReplacementFromUrl, + DomainContentReplacementFromUrl, ChallengeOwnership, EntityScriptCallMethod, ChallengeOwnershipRequest, @@ -171,7 +171,7 @@ public: << PacketTypeEnum::Value::DomainServerPathResponse << PacketTypeEnum::Value::DomainServerAddedNode << PacketTypeEnum::Value::DomainServerConnectionToken << PacketTypeEnum::Value::DomainSettingsRequest << PacketTypeEnum::Value::OctreeDataFileRequest << PacketTypeEnum::Value::OctreeDataFileReply - << PacketTypeEnum::Value::OctreeDataPersist << PacketTypeEnum::Value::OctreeFileReplacementFromUrl + << PacketTypeEnum::Value::OctreeDataPersist << PacketTypeEnum::Value::DomainContentReplacementFromUrl << PacketTypeEnum::Value::DomainSettings << PacketTypeEnum::Value::ICEServerPeerInformation << PacketTypeEnum::Value::ICEServerQuery << PacketTypeEnum::Value::ICEServerHeartbeat << PacketTypeEnum::Value::ICEServerHeartbeatACK << PacketTypeEnum::Value::ICEPing