diff --git a/interface/resources/qml/hifi/AvatarPackager.qml b/interface/resources/qml/hifi/AvatarPackager.qml index b3535395db..ff275923ac 100644 --- a/interface/resources/qml/hifi/AvatarPackager.qml +++ b/interface/resources/qml/hifi/AvatarPackager.qml @@ -127,9 +127,12 @@ Windows.ScrollingWindow { property alias showModalOverlay: modalOverlay.visible function openProject(path) { - AvatarPackagerCore.openAvatarProject(path); - avatarProject.reset(); - avatarPackager.state = "project"; + let project = AvatarPackagerCore.openAvatarProject(path); + if (project) { + avatarProject.reset(); + avatarPackager.state = "project"; + } + return project; } AvatarPackagerHeader { @@ -213,9 +216,8 @@ Windows.ScrollingWindow { browser.selectedFile.connect(function(fileUrl) { let fstFilePath = fileDialogHelper.urlToPath(fileUrl); - let currentAvatarProject = AvatarPackagerCore.openAvatarProject(fstFilePath); + let currentAvatarProject = avatarPackager.openProject(fstFilePath); if (currentAvatarProject) { - avatarPackager.state = AvatarPackagerState.project; avatarPackager.showModalOverlay = false; } }); diff --git a/interface/src/avatar/AvatarProject.cpp b/interface/src/avatar/AvatarProject.cpp index 038ded64d8..17ed4b6921 100644 --- a/interface/src/avatar/AvatarProject.cpp +++ b/interface/src/avatar/AvatarProject.cpp @@ -162,10 +162,9 @@ void AvatarProject::appendDirectory(QString prefix, QDir dir) { constexpr auto flags = QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot | QDir::Hidden; for (auto& entry : dir.entryInfoList({}, flags)) { if (entry.isFile()) { - //_projectFiles.append(prefix + "/" + entry.fileName()); - _projectFiles.append({ entry.absoluteFilePath(), prefix + "/" + entry.fileName() }); + _projectFiles.append({ entry.absoluteFilePath(), prefix + entry.fileName() }); } else if (entry.isDir()) { - appendDirectory(prefix + dir.dirName() + "/", entry.absoluteFilePath()); + appendDirectory(prefix + entry.fileName() + "/", entry.absoluteFilePath()); } } } @@ -188,12 +187,8 @@ MarketplaceItemUploader* AvatarProject::upload(bool updateExisting) { if (updateExisting) { itemID = _fst->getMarketplaceID(); } - QStringList projectFilePaths; - for (auto& path : _projectFiles) { - projectFilePaths.append(path.absolutePath); - } - auto uploader = new MarketplaceItemUploader(getProjectName(), "Empty description", QFileInfo(getFSTPath()).fileName(), itemID, - projectFilePaths); + auto uploader = new MarketplaceItemUploader(getProjectName(), "Empty description", QFileInfo(getFSTPath()).fileName(), + itemID, _projectFiles); connect(uploader, &MarketplaceItemUploader::completed, this, [this, uploader]() { if (uploader->getError() == MarketplaceItemUploader::Error::None) { _fst->setMarketplaceID(uploader->getMarketplaceID()); diff --git a/interface/src/avatar/MarketplaceItemUploader.cpp b/interface/src/avatar/MarketplaceItemUploader.cpp index 6bc499c0fb..33cfb85c8e 100644 --- a/interface/src/avatar/MarketplaceItemUploader.cpp +++ b/interface/src/avatar/MarketplaceItemUploader.cpp @@ -31,18 +31,15 @@ MarketplaceItemUploader::MarketplaceItemUploader(QString title, QString description, QString rootFilename, QUuid marketplaceID, - QStringList filePaths) : + QList filePaths) : _title(title), _description(description), _rootFilename(rootFilename), _marketplaceID(marketplaceID), _filePaths(filePaths) { - qWarning() << "File paths: " << _filePaths.join(", "); - //_marketplaceID = QUuid::fromString(QLatin1String("{50dbd62f-cb6b-4be4-afb8-1ef8bd2dffa8}")); } void MarketplaceItemUploader::setState(State newState) { Q_ASSERT(_state != State::Complete); Q_ASSERT(_error == Error::None); Q_ASSERT(newState != _state); - qDebug() << "Setting uploader state to: " << newState; _state = newState; emit stateChanged(newState); @@ -113,13 +110,12 @@ void MarketplaceItemUploader::doGetCategories() { }; bool success; - int id; - std::tie(success, id) = extractCategoryID(); - qDebug() << "Done " << success << id; + std::tie(success, _categoryID) = extractCategoryID(); if (!success) { qWarning() << "Failed to find marketplace category id"; setError(Error::Unknown); } else { + qDebug() << "Marketplace Avatar category ID is" << _categoryID; doUploadAvatar(); } } else { @@ -133,24 +129,26 @@ void MarketplaceItemUploader::doUploadAvatar() { //buffer.open(QIODevice::WriteOnly); QuaZip zip{ &buffer }; if (!zip.open(QuaZip::Mode::mdAdd)) { - qWarning() << "Failed to open zip!!"; + qWarning() << "Failed to open zip"; + setError(Error::Unknown); + return; } for (auto& filePath : _filePaths) { - qWarning() << "Zipping: " << filePath; - QFileInfo fileInfo{ filePath }; + qWarning() << "Zipping: " << filePath.absolutePath << filePath.relativePath; + QFileInfo fileInfo{ filePath.absolutePath }; QuaZipFile zipFile{ &zip }; - if (!zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileInfo.fileName()))) { + if (!zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(filePath.relativePath))) { qWarning() << "Could not open zip file:" << zipFile.getZipError(); setError(Error::Unknown); return; } - QFile file{ filePath }; + QFile file{ filePath.absolutePath }; if (file.open(QIODevice::ReadOnly)) { zipFile.write(file.readAll()); } else { - qWarning() << "Failed to open: " << filePath; + qWarning() << "Failed to open: " << filePath.absolutePath; } file.close(); zipFile.close(); @@ -175,28 +173,26 @@ void MarketplaceItemUploader::doUploadAvatar() { } auto accountManager = DependencyManager::get(); auto request = accountManager->createRequest(path, AccountManagerAuth::Required); - qWarning() << "Request url is: " << request.url(); - - QJsonObject root{ { "marketplace_item", - QJsonObject{ { "title", _title }, - { "description", _description }, - { "root_file_key", _rootFilename }, - { "category_ids", QJsonArray({ 5 }) }, - { "license", 0 }, - { "files", QString::fromLatin1(_fileData.toBase64()) } } } }; request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json"); - QJsonDocument doc{ root }; - qWarning() << "data: " << doc.toJson(); + // TODO(huffman) add JSON escaping + auto escapeJson = [](QString str) -> QString { return str; }; + + QString jsonString = "{\"marketplace_item\":{"; + jsonString += "\"title\":\"" + escapeJson(_title) + "\""; + jsonString += ",\"description\":\"" + escapeJson(_description) + "\""; + jsonString += ",\"root_file_key\":\"" + escapeJson(_rootFilename) + "\""; + jsonString += ",\"category_ids\":[" + QStringLiteral("%1").arg(_categoryID) + "]"; + jsonString += ",\"license\":0"; + jsonString += ",\"files\":\"" + QString::fromLatin1(_fileData.toBase64()) + "\"}}"; - _fileData.toBase64(); QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkReply* reply{ nullptr }; if (creating) { - reply = networkAccessManager.post(request, doc.toJson()); + reply = networkAccessManager.post(request, jsonString.toUtf8()); } else { - reply = networkAccessManager.put(request, doc.toJson()); + reply = networkAccessManager.put(request, jsonString.toUtf8()); } connect(reply, &QNetworkReply::uploadProgress, this, [this](float bytesSent, float bytesTotal) { @@ -210,11 +206,9 @@ void MarketplaceItemUploader::doUploadAvatar() { connect(reply, &QNetworkReply::finished, this, [this, reply]() { _responseData = reply->readAll(); - qWarning() << "Finished request " << _responseData; auto error = reply->error(); if (error == QNetworkReply::NoError) { - auto doc = QJsonDocument::fromJson(_responseData.toLatin1()); auto status = doc.object()["status"].toString(); if (status == "success") { @@ -223,9 +217,11 @@ void MarketplaceItemUploader::doUploadAvatar() { setState(State::WaitingForInventory); doWaitForInventory(); } else { + qWarning() << "Got error response while uploading avatar: " << _responseData; setError(Error::Unknown); } } else { + qWarning() << "Got error while uploading avatar: " << reply->error() << reply->errorString() << _responseData; setError(Error::Unknown); } }); @@ -265,7 +261,7 @@ void MarketplaceItemUploader::doWaitForInventory() { } auto data = root["data"]; if (!data.isObject()) { - return false; + return false; } auto assets = data.toObject()["assets"]; if (!assets.isArray()) { diff --git a/interface/src/avatar/MarketplaceItemUploader.h b/interface/src/avatar/MarketplaceItemUploader.h index 4b8b675255..4fb1713b7d 100644 --- a/interface/src/avatar/MarketplaceItemUploader.h +++ b/interface/src/avatar/MarketplaceItemUploader.h @@ -13,6 +13,8 @@ #ifndef hifi_MarketplaceItemUploader_h #define hifi_MarketplaceItemUploader_h +#include "ProjectFile.h" + #include #include @@ -50,7 +52,7 @@ public: QString description, QString rootFilename, QUuid marketplaceID, - QStringList filePaths); + QList filePaths); Q_INVOKABLE void send(); @@ -91,13 +93,15 @@ private: QString _description; QString _rootFilename; QUuid _marketplaceID; + int _categoryID; int _itemVersion; QString _responseData; int _numRequestsForInventory{ 0 }; - QStringList _filePaths; + QString _rootFilePath; + QList _filePaths; QByteArray _fileData; }; diff --git a/libraries/avatars/src/ProjectFile.h b/libraries/avatars/src/ProjectFile.h index df92513a1b..82930a3464 100644 --- a/libraries/avatars/src/ProjectFile.h +++ b/libraries/avatars/src/ProjectFile.h @@ -1,6 +1,8 @@ #ifndef hifi_AvatarProjectFile_h #define hifi_AvatarProjectFile_h +#include + class ProjectFilePath { Q_GADGET; public: