Files
scummvm-cursorfix/backends/networking/sdl_net/handlers/connectcloudhandler.cpp
2026-02-02 04:50:13 +01:00

145 lines
5.0 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* 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 3 of the License, or
* (at your option) any later version.
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "backends/networking/sdl_net/handlers/connectcloudhandler.h"
#include "backends/fs/fs-factory.h"
#include "backends/cloud/cloudmanager.h"
#include "backends/networking/http/httpjsonrequest.h"
#include "backends/networking/sdl_net/getclienthandler.h"
#include "backends/networking/sdl_net/handlerutils.h"
#include "backends/networking/sdl_net/localwebserver.h"
#include "backends/networking/sdl_net/reader.h"
#include "common/formats/json.h"
#include "common/memstream.h"
#include "common/callback.h"
namespace Networking {
ConnectCloudHandler::ConnectCloudHandler() : _storageConnectionCallback(nullptr) {}
ConnectCloudHandler::~ConnectCloudHandler() {}
void ConnectCloudHandler::handle(Client &client) {
client.setHandler(new ConnectCloudClientHandler(this));
}
void ConnectCloudHandler::storageConnected(const Networking::ErrorResponse &response) const {
if (_storageConnectionCallback)
(*_storageConnectionCallback)(response);
}
//
ConnectCloudClientHandler::ConnectCloudClientHandler(const ConnectCloudHandler *cloudHandler):
_cloudHandler(cloudHandler), _clientContent(DisposeAfterUse::YES), _client(nullptr) {}
ConnectCloudClientHandler::~ConnectCloudClientHandler() {}
void ConnectCloudClientHandler::respond(Client &client, const Common::String &response, long responseCode) const {
Common::SeekableReadStream *responseStream = HandlerUtils::makeResponseStreamFromString(response);
GetClientHandler *responseHandler = new GetClientHandler(responseStream);
responseHandler->setResponseCode(responseCode);
responseHandler->setHeader("Access-Control-Allow-Origin", "https://cloud.scummvm.org");
responseHandler->setHeader("Access-Control-Allow-Methods", "POST");
responseHandler->setHeader("Access-Control-Allow-Headers", "Content-Type");
client.setHandler(responseHandler);
}
void ConnectCloudClientHandler::respondWithJson(Client &client, bool error, const Common::String &message, long responseCode) const {
Common::JSONObject response;
response.setVal("error", new Common::JSONValue(error));
response.setVal("message", new Common::JSONValue(message));
Common::JSONValue json = response;
respond(client, json.stringify(true), responseCode);
}
void ConnectCloudClientHandler::handleError(Client &client, const Common::String &message, long responseCode) const {
respondWithJson(client, true, message, responseCode);
}
void ConnectCloudClientHandler::handleSuccess(Client &client, const Common::String &message) const {
respondWithJson(client, false, message);
}
/// public
void ConnectCloudClientHandler::handle(Client *client) {
if (client == nullptr) {
warning("ConnectCloudClientHandler::handle(): empty client pointer");
return;
}
_client = client;
if (client->method() == "OPTIONS") {
respond(*client, "", 200);
return;
}
if (client->method() != "POST") {
handleError(*client, "Method Not Allowed", 405);
return;
}
if (_clientContent.size() > SUSPICIOUS_CONTENT_SIZE) {
handleError(*client, "Bad Request", 400);
return;
}
if (!client->readContent(&_clientContent))
return;
char *contents = Common::JSON::zeroTerminateContents(_clientContent);
Common::JSONValue *json = Common::JSON::parse(contents);
if (json == nullptr) {
handleError(*client, "Not Acceptable", 406);
return;
}
Networking::ErrorCallback callback = new Common::Callback<ConnectCloudClientHandler, const Networking::ErrorResponse &>(this, &ConnectCloudClientHandler::storageConnectionCallback);
Networking::JsonResponse jsonResponse(nullptr, json);
if (!CloudMan.connectStorage(jsonResponse, callback)) { // JSON doesn't have "storage" in it or it was invalid
delete json;
delete callback;
handleError(*client, "Not Acceptable", 406);
}
}
void ConnectCloudClientHandler::storageConnectionCallback(const Networking::ErrorResponse &response) {
if (response.failed || response.interrupted) {
Common::String message = "Failed to connect storage.";
if (response.failed) {
message += " Context: ";
message += response.response.c_str();
}
handleError(*_client, message, 200);
} else {
handleSuccess(*_client, "Storage connected.");
}
_cloudHandler->storageConnected(response);
}
} // End of namespace Networking