CLOUD: Add OneDriveUploadRequest
Doesn't support server's requested ranges yet. Commit also adds some PUT-related code in NetworkReadStream and CurlRequest.
This commit is contained in:
parent
eb63b50b7f
commit
b39f46788a
14 changed files with 354 additions and 33 deletions
|
@ -131,19 +131,6 @@ Networking::Request *DropboxStorage::upload(Common::String path, Common::Seekabl
|
||||||
return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback));
|
return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
Networking::Request *DropboxStorage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
|
|
||||||
Common::File *f = new Common::File();
|
|
||||||
if (!f->open(localPath)) {
|
|
||||||
warning("DropboxStorage: unable to open file to upload from");
|
|
||||||
if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1));
|
|
||||||
delete errorCallback;
|
|
||||||
delete callback;
|
|
||||||
delete f;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return upload(remotePath, f, callback, errorCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) {
|
Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) {
|
||||||
Common::JSONObject jsonRequestParameters;
|
Common::JSONObject jsonRequestParameters;
|
||||||
jsonRequestParameters.setVal("path", new Common::JSONValue(path));
|
jsonRequestParameters.setVal("path", new Common::JSONValue(path));
|
||||||
|
|
|
@ -75,7 +75,6 @@ public:
|
||||||
|
|
||||||
/** Returns UploadStatus struct with info about uploaded file. */
|
/** Returns UploadStatus struct with info about uploaded file. */
|
||||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback);
|
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback);
|
||||||
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback);
|
|
||||||
|
|
||||||
/** Returns pointer to Networking::NetworkReadStream. */
|
/** Returns pointer to Networking::NetworkReadStream. */
|
||||||
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback);
|
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback);
|
||||||
|
|
|
@ -24,8 +24,10 @@
|
||||||
#include "backends/cloud/onedrive/onedrivestorage.h"
|
#include "backends/cloud/onedrive/onedrivestorage.h"
|
||||||
#include "backends/cloud/onedrive/onedrivetokenrefresher.h"
|
#include "backends/cloud/onedrive/onedrivetokenrefresher.h"
|
||||||
#include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h"
|
#include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h"
|
||||||
|
#include "backends/cloud/onedrive/onedriveuploadrequest.h"
|
||||||
#include "backends/cloud/downloadrequest.h"
|
#include "backends/cloud/downloadrequest.h"
|
||||||
#include "backends/cloud/folderdownloadrequest.h"
|
#include "backends/cloud/folderdownloadrequest.h"
|
||||||
|
#include "backends/cloud/savessyncrequest.h"
|
||||||
#include "backends/networking/curl/connectionmanager.h"
|
#include "backends/networking/curl/connectionmanager.h"
|
||||||
#include "backends/networking/curl/curljsonrequest.h"
|
#include "backends/networking/curl/curljsonrequest.h"
|
||||||
#include "common/cloudmanager.h"
|
#include "common/cloudmanager.h"
|
||||||
|
@ -35,7 +37,6 @@
|
||||||
#include "common/json.h"
|
#include "common/json.h"
|
||||||
#include "common/system.h"
|
#include "common/system.h"
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "../savessyncrequest.h"
|
|
||||||
|
|
||||||
namespace Cloud {
|
namespace Cloud {
|
||||||
namespace OneDrive {
|
namespace OneDrive {
|
||||||
|
@ -168,6 +169,9 @@ Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDir
|
||||||
return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, errorCallback, recursive));
|
return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, errorCallback, recursive));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Networking::Request *OneDriveStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) {
|
||||||
|
return ConnMan.addRequest(new OneDriveUploadRequest(this, path, contents, callback, errorCallback));
|
||||||
|
}
|
||||||
|
|
||||||
Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) {
|
Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) {
|
||||||
Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path;
|
Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path;
|
||||||
|
@ -210,6 +214,13 @@ void OneDriveStorage::printBool(BoolResponse response) {
|
||||||
debug("bool: %s", response.value ? "true" : "false");
|
debug("bool: %s", response.value ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OneDriveStorage::printFile(UploadResponse response) {
|
||||||
|
debug("\nuploaded file info:");
|
||||||
|
debug("\tpath: %s", response.value.path().c_str());
|
||||||
|
debug("\tsize: %u", response.value.size());
|
||||||
|
debug("\ttimestamp: %u", response.value.timestamp());
|
||||||
|
}
|
||||||
|
|
||||||
void OneDriveStorage::printErrorResponse(Networking::ErrorResponse error) {
|
void OneDriveStorage::printErrorResponse(Networking::ErrorResponse error) {
|
||||||
debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode);
|
debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode);
|
||||||
debug("%s", error.response.c_str());
|
debug("%s", error.response.c_str());
|
||||||
|
@ -228,7 +239,11 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback, Networkin
|
||||||
return ConnMan.addRequest(request);
|
return ConnMan.addRequest(request);
|
||||||
*/
|
*/
|
||||||
//return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback<OneDriveStorage, FileArrayResponse>(this, &OneDriveStorage::printFiles), false);
|
//return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback<OneDriveStorage, FileArrayResponse>(this, &OneDriveStorage::printFiles), false);
|
||||||
return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback<OneDriveStorage, BoolResponse>(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO
|
return Storage::upload(
|
||||||
|
"uploads/test.jpg", "test.jpg",
|
||||||
|
new Common::Callback<OneDriveStorage, UploadResponse>(this, &OneDriveStorage::printFile), getErrorPrintingCallback()
|
||||||
|
);
|
||||||
|
//return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback<OneDriveStorage, BoolResponse>(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) {
|
OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) {
|
||||||
|
|
|
@ -53,6 +53,7 @@ class OneDriveStorage: public Cloud::Storage {
|
||||||
void fileDownloaded(BoolResponse response);
|
void fileDownloaded(BoolResponse response);
|
||||||
void printFiles(FileArrayResponse response);
|
void printFiles(FileArrayResponse response);
|
||||||
void printBool(BoolResponse response);
|
void printBool(BoolResponse response);
|
||||||
|
void printFile(UploadResponse response);
|
||||||
void printErrorResponse(Networking::ErrorResponse error);
|
void printErrorResponse(Networking::ErrorResponse error);
|
||||||
|
|
||||||
Networking::ErrorCallback getErrorPrintingCallback();
|
Networking::ErrorCallback getErrorPrintingCallback();
|
||||||
|
@ -80,8 +81,7 @@ public:
|
||||||
virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
|
virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false);
|
||||||
|
|
||||||
/** Returns UploadStatus struct with info about uploaded file. */
|
/** Returns UploadStatus struct with info about uploaded file. */
|
||||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO
|
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback);
|
||||||
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO
|
|
||||||
|
|
||||||
/** Returns pointer to Networking::NetworkReadStream. */
|
/** Returns pointer to Networking::NetworkReadStream. */
|
||||||
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback);
|
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback);
|
||||||
|
|
|
@ -90,6 +90,8 @@ void OneDriveTokenRefresher::finishSuccess(Common::JSONValue *json) {
|
||||||
irrecoverable = false;
|
irrecoverable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (code == "unauthenticated") irrecoverable = false;
|
||||||
|
|
||||||
if (irrecoverable) {
|
if (irrecoverable) {
|
||||||
finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode
|
finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode
|
||||||
delete json;
|
delete json;
|
||||||
|
|
171
backends/cloud/onedrive/onedriveuploadrequest.cpp
Normal file
171
backends/cloud/onedrive/onedriveuploadrequest.cpp
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
/* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "backends/cloud/onedrive/onedriveuploadrequest.h"
|
||||||
|
#include "backends/cloud/onedrive/onedrivestorage.h"
|
||||||
|
#include "backends/cloud/iso8601.h"
|
||||||
|
#include "backends/cloud/storage.h"
|
||||||
|
#include "backends/networking/curl/connectionmanager.h"
|
||||||
|
#include "backends/networking/curl/curljsonrequest.h"
|
||||||
|
#include "backends/networking/curl/networkreadstream.h"
|
||||||
|
#include "common/json.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "onedrivetokenrefresher.h"
|
||||||
|
|
||||||
|
namespace Cloud {
|
||||||
|
namespace OneDrive {
|
||||||
|
|
||||||
|
OneDriveUploadRequest::OneDriveUploadRequest(OneDriveStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb):
|
||||||
|
Networking::Request(nullptr, ecb), _storage(storage), _savePath(path), _contentsStream(contents), _uploadCallback(callback),
|
||||||
|
_workingRequest(nullptr), _ignoreCallback(false) {
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
OneDriveUploadRequest::~OneDriveUploadRequest() {
|
||||||
|
_ignoreCallback = true;
|
||||||
|
if (_workingRequest) _workingRequest->finish();
|
||||||
|
delete _contentsStream;
|
||||||
|
delete _uploadCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneDriveUploadRequest::start() {
|
||||||
|
_ignoreCallback = true;
|
||||||
|
if (_workingRequest) _workingRequest->finish();
|
||||||
|
if (!_contentsStream->seek(0)) {
|
||||||
|
warning("OneDriveUploadRequest: cannot restart because stream couldn't seek(0)");
|
||||||
|
finishError(Networking::ErrorResponse(this, false, true, "", -1));
|
||||||
|
}
|
||||||
|
_ignoreCallback = false;
|
||||||
|
|
||||||
|
uploadNextPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneDriveUploadRequest::uploadNextPart() {
|
||||||
|
const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
if (_uploadUrl == "" && _contentsStream->size() > UPLOAD_PER_ONE_REQUEST) {
|
||||||
|
Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+_savePath+":/upload.createSession"; //folder must exist
|
||||||
|
Networking::JsonCallback callback = new Common::Callback<OneDriveUploadRequest, Networking::JsonResponse>(this, &OneDriveUploadRequest::partUploadedCallback);
|
||||||
|
Networking::ErrorCallback failureCallback = new Common::Callback<OneDriveUploadRequest, Networking::ErrorResponse>(this, &OneDriveUploadRequest::partUploadedErrorCallback);
|
||||||
|
Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str());
|
||||||
|
request->addHeader("Authorization: Bearer " + _storage->accessToken());
|
||||||
|
request->setBuffer(new byte[1], 0); //use POST
|
||||||
|
_workingRequest = ConnMan.addRequest(request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::String url;
|
||||||
|
if (_uploadUrl == "") {
|
||||||
|
url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+_savePath+":/content";
|
||||||
|
} else {
|
||||||
|
url = _uploadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Networking::JsonCallback callback = new Common::Callback<OneDriveUploadRequest, Networking::JsonResponse>(this, &OneDriveUploadRequest::partUploadedCallback);
|
||||||
|
Networking::ErrorCallback failureCallback = new Common::Callback<OneDriveUploadRequest, Networking::ErrorResponse>(this, &OneDriveUploadRequest::partUploadedErrorCallback);
|
||||||
|
Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str());
|
||||||
|
request->addHeader("Authorization: Bearer " + _storage->accessToken());
|
||||||
|
request->usePut();
|
||||||
|
|
||||||
|
uint32 oldPos = _contentsStream->pos();
|
||||||
|
|
||||||
|
byte *buffer = new byte[UPLOAD_PER_ONE_REQUEST];
|
||||||
|
uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST);
|
||||||
|
request->setBuffer(buffer, size);
|
||||||
|
|
||||||
|
//request->addHeader(Common::String::format("Content-Length: %u", size));
|
||||||
|
if (_uploadUrl != "")
|
||||||
|
request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos()-1, _contentsStream->size())); ;
|
||||||
|
|
||||||
|
_workingRequest = ConnMan.addRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse response) {
|
||||||
|
_workingRequest = nullptr;
|
||||||
|
if (_ignoreCallback) return;
|
||||||
|
|
||||||
|
Networking::ErrorResponse error(this, false, true, "", -1);
|
||||||
|
Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request;
|
||||||
|
if (rq && rq->getNetworkReadStream())
|
||||||
|
error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
|
||||||
|
|
||||||
|
Common::JSONValue *json = response.value;
|
||||||
|
if (json) {
|
||||||
|
if (json->isObject()) {
|
||||||
|
Common::JSONObject object = json->asObject();
|
||||||
|
|
||||||
|
if (object.contains("error")) {
|
||||||
|
warning("OneDrive returned error: %s", json->stringify(true).c_str());
|
||||||
|
delete json;
|
||||||
|
error.response = json->stringify(true);
|
||||||
|
finishError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (object.contains("id") && object.contains("name")) {
|
||||||
|
//finished
|
||||||
|
Common::String path = _savePath; //object.getVal("name")->asString();; //object.getVal("id")->asString();
|
||||||
|
uint32 size = object.getVal("size")->asIntegerNumber();
|
||||||
|
uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("lastModifiedDateTime")->asString());
|
||||||
|
finishSuccess(StorageFile(path, size, timestamp, false));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_uploadUrl == "") {
|
||||||
|
if (object.contains("uploadUrl"))
|
||||||
|
_uploadUrl = object.getVal("uploadUrl")->asString();
|
||||||
|
else
|
||||||
|
warning("no uploadUrl found in OneDrive's response");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) {
|
||||||
|
warning("no file info to return");
|
||||||
|
finishSuccess(StorageFile(_savePath, 0, 0, false));
|
||||||
|
} else {
|
||||||
|
uploadNextPart();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warning("null, not json");
|
||||||
|
finishError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete json;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) {
|
||||||
|
_workingRequest = nullptr;
|
||||||
|
if (_ignoreCallback) return;
|
||||||
|
finishError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OneDriveUploadRequest::handle() {}
|
||||||
|
|
||||||
|
void OneDriveUploadRequest::restart() { start(); }
|
||||||
|
|
||||||
|
void OneDriveUploadRequest::finishSuccess(StorageFile file) {
|
||||||
|
Request::finishSuccess();
|
||||||
|
if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace OneDrive
|
||||||
|
} // End of namespace Cloud
|
61
backends/cloud/onedrive/onedriveuploadrequest.h
Normal file
61
backends/cloud/onedrive/onedriveuploadrequest.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BACKENDS_CLOUD_ONEDRIVE_ONEDRIVEUPLOADREQUEST_H
|
||||||
|
#define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVEUPLOADREQUEST_H
|
||||||
|
|
||||||
|
#include "backends/cloud/storage.h"
|
||||||
|
#include "backends/networking/curl/curljsonrequest.h"
|
||||||
|
#include "backends/networking/curl/request.h"
|
||||||
|
#include "common/callback.h"
|
||||||
|
|
||||||
|
namespace Cloud {
|
||||||
|
namespace OneDrive {
|
||||||
|
class OneDriveStorage;
|
||||||
|
|
||||||
|
class OneDriveUploadRequest: public Networking::Request {
|
||||||
|
OneDriveStorage *_storage;
|
||||||
|
Common::String _savePath;
|
||||||
|
Common::SeekableReadStream *_contentsStream;
|
||||||
|
Storage::UploadCallback _uploadCallback;
|
||||||
|
Request *_workingRequest;
|
||||||
|
bool _ignoreCallback;
|
||||||
|
Common::String _uploadUrl;
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void uploadNextPart();
|
||||||
|
void partUploadedCallback(Networking::JsonResponse response);
|
||||||
|
void partUploadedErrorCallback(Networking::ErrorResponse error);
|
||||||
|
void finishSuccess(StorageFile status);
|
||||||
|
|
||||||
|
public:
|
||||||
|
OneDriveUploadRequest(OneDriveStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb);
|
||||||
|
virtual ~OneDriveUploadRequest();
|
||||||
|
|
||||||
|
virtual void handle();
|
||||||
|
virtual void restart();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace OneDrive
|
||||||
|
} // End of namespace Cloud
|
||||||
|
|
||||||
|
#endif
|
42
backends/cloud/storage.cpp
Normal file
42
backends/cloud/storage.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "backends/cloud/storage.h"
|
||||||
|
#include "common/file.h"
|
||||||
|
|
||||||
|
namespace Cloud {
|
||||||
|
|
||||||
|
Networking::Request *Storage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) {
|
||||||
|
Common::File *f = new Common::File();
|
||||||
|
if (!f->open(localPath)) {
|
||||||
|
warning("Storage: unable to open file to upload from");
|
||||||
|
if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1));
|
||||||
|
delete errorCallback;
|
||||||
|
delete callback;
|
||||||
|
delete f;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return upload(remotePath, f, callback, errorCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace Cloud
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
|
|
||||||
/** Returns UploadStatus struct with info about uploaded file. */
|
/** Returns UploadStatus struct with info about uploaded file. */
|
||||||
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) = 0;
|
virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) = 0;
|
||||||
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) = 0;
|
virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback);
|
||||||
|
|
||||||
/** Returns pointer to Networking::NetworkReadStream. */
|
/** Returns pointer to Networking::NetworkReadStream. */
|
||||||
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0;
|
virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0;
|
||||||
|
|
|
@ -23,6 +23,7 @@ ifdef USE_CLOUD
|
||||||
MODULE_OBJS += \
|
MODULE_OBJS += \
|
||||||
cloud/iso8601.o \
|
cloud/iso8601.o \
|
||||||
cloud/manager.o \
|
cloud/manager.o \
|
||||||
|
cloud/storage.o \
|
||||||
cloud/storagefile.o \
|
cloud/storagefile.o \
|
||||||
cloud/downloadrequest.o \
|
cloud/downloadrequest.o \
|
||||||
cloud/folderdownloadrequest.o \
|
cloud/folderdownloadrequest.o \
|
||||||
|
@ -32,7 +33,8 @@ MODULE_OBJS += \
|
||||||
cloud/dropbox/dropboxuploadrequest.o \
|
cloud/dropbox/dropboxuploadrequest.o \
|
||||||
cloud/onedrive/onedrivestorage.o \
|
cloud/onedrive/onedrivestorage.o \
|
||||||
cloud/onedrive/onedrivetokenrefresher.o \
|
cloud/onedrive/onedrivetokenrefresher.o \
|
||||||
cloud/onedrive/onedrivelistdirectoryrequest.o
|
cloud/onedrive/onedrivelistdirectoryrequest.o \
|
||||||
|
cloud/onedrive/onedriveuploadrequest.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef USE_LIBCURL
|
ifdef USE_LIBCURL
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
namespace Networking {
|
namespace Networking {
|
||||||
|
|
||||||
CurlRequest::CurlRequest(DataCallback cb, ErrorCallback ecb, Common::String url):
|
CurlRequest::CurlRequest(DataCallback cb, ErrorCallback ecb, Common::String url):
|
||||||
Request(cb, ecb), _url(url), _stream(nullptr), _headersList(nullptr), _bytesBuffer(nullptr), _bytesBufferSize(0) {}
|
Request(cb, ecb), _url(url), _stream(nullptr), _headersList(nullptr), _bytesBuffer(nullptr), _bytesBufferSize(0), _uploading(false) {}
|
||||||
|
|
||||||
CurlRequest::~CurlRequest() {
|
CurlRequest::~CurlRequest() {
|
||||||
delete _stream;
|
delete _stream;
|
||||||
|
@ -40,8 +40,8 @@ CurlRequest::~CurlRequest() {
|
||||||
|
|
||||||
NetworkReadStream *CurlRequest::makeStream() {
|
NetworkReadStream *CurlRequest::makeStream() {
|
||||||
if (_bytesBuffer)
|
if (_bytesBuffer)
|
||||||
return new NetworkReadStream(_url.c_str(), _headersList, _bytesBuffer, _bytesBufferSize, true);
|
return new NetworkReadStream(_url.c_str(), _headersList, _bytesBuffer, _bytesBufferSize, _uploading, true);
|
||||||
return new NetworkReadStream(_url.c_str(), _headersList, _postFields);
|
return new NetworkReadStream(_url.c_str(), _headersList, _postFields, _uploading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,6 +97,8 @@ void CurlRequest::setBuffer(byte *buffer, uint32 size) {
|
||||||
_bytesBufferSize = size;
|
_bytesBufferSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CurlRequest::usePut() { _uploading = true; }
|
||||||
|
|
||||||
NetworkReadStreamResponse CurlRequest::execute() {
|
NetworkReadStreamResponse CurlRequest::execute() {
|
||||||
if (!_stream) {
|
if (!_stream) {
|
||||||
_stream = makeStream();
|
_stream = makeStream();
|
||||||
|
|
|
@ -44,6 +44,7 @@ protected:
|
||||||
Common::String _postFields;
|
Common::String _postFields;
|
||||||
byte *_bytesBuffer;
|
byte *_bytesBuffer;
|
||||||
uint32 _bytesBufferSize;
|
uint32 _bytesBufferSize;
|
||||||
|
bool _uploading; //using PUT method
|
||||||
|
|
||||||
virtual NetworkReadStream *makeStream();
|
virtual NetworkReadStream *makeStream();
|
||||||
|
|
||||||
|
@ -66,6 +67,9 @@ public:
|
||||||
/** Sets bytes buffer. */
|
/** Sets bytes buffer. */
|
||||||
virtual void setBuffer(byte *buffer, uint32 size);
|
virtual void setBuffer(byte *buffer, uint32 size);
|
||||||
|
|
||||||
|
/** Remembers to use PUT method when it would create NetworkReadStream. */
|
||||||
|
virtual void usePut();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts this Request with ConnMan.
|
* Starts this Request with ConnMan.
|
||||||
* @return its NetworkReadStream in NetworkReadStreamResponse.
|
* @return its NetworkReadStream in NetworkReadStreamResponse.
|
||||||
|
|
|
@ -35,11 +35,17 @@ static size_t curlDataCallback(char *d, size_t n, size_t l, void *p) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields):
|
static size_t curlReadDataCallback(char *d, size_t n, size_t l, void *p) {
|
||||||
NetworkReadStream(url, headersList, (byte *)postFields.c_str(), postFields.size(), false) {}
|
NetworkReadStream *stream = (NetworkReadStream *)p;
|
||||||
|
if (stream) return stream->fillWithSendingContents(d, n*l);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool post) :
|
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading):
|
||||||
_easy(0), _eos(false), _requestComplete(false) {
|
NetworkReadStream(url, headersList, (byte *)postFields.c_str(), postFields.size(), uploading, false) {}
|
||||||
|
|
||||||
|
NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool uploading, bool post):
|
||||||
|
_easy(0), _eos(false), _requestComplete(false), _sendingContentsBuffer(nullptr), _sendingContentsSize(0), _sendingContentsPos(0) {
|
||||||
_easy = curl_easy_init();
|
_easy = curl_easy_init();
|
||||||
curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback);
|
curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback);
|
||||||
curl_easy_setopt(_easy, CURLOPT_WRITEDATA, this); //so callback can call us
|
curl_easy_setopt(_easy, CURLOPT_WRITEDATA, this); //so callback can call us
|
||||||
|
@ -49,9 +55,17 @@ NetworkReadStream::NetworkReadStream(const char *url, curl_slist *headersList, b
|
||||||
curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L);
|
curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L);
|
||||||
curl_easy_setopt(_easy, CURLOPT_FOLLOWLOCATION, 1L); //probably it's OK to have it always on
|
curl_easy_setopt(_easy, CURLOPT_FOLLOWLOCATION, 1L); //probably it's OK to have it always on
|
||||||
curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList);
|
curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList);
|
||||||
if (post || bufferSize != 0) {
|
if (uploading) {
|
||||||
curl_easy_setopt(_easy, CURLOPT_POSTFIELDSIZE, bufferSize);
|
curl_easy_setopt(_easy, CURLOPT_UPLOAD, 1L);
|
||||||
curl_easy_setopt(_easy, CURLOPT_COPYPOSTFIELDS, buffer);
|
curl_easy_setopt(_easy, CURLOPT_READDATA, this);
|
||||||
|
curl_easy_setopt(_easy, CURLOPT_READFUNCTION, curlReadDataCallback);
|
||||||
|
_sendingContentsBuffer = buffer;
|
||||||
|
_sendingContentsSize = bufferSize;
|
||||||
|
} else {
|
||||||
|
if (post || bufferSize != 0) {
|
||||||
|
curl_easy_setopt(_easy, CURLOPT_POSTFIELDSIZE, bufferSize);
|
||||||
|
curl_easy_setopt(_easy, CURLOPT_COPYPOSTFIELDS, buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ConnMan.registerEasyHandle(_easy);
|
ConnMan.registerEasyHandle(_easy);
|
||||||
}
|
}
|
||||||
|
@ -87,4 +101,14 @@ long NetworkReadStream::httpResponseCode() const {
|
||||||
return responseCode;
|
return responseCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 NetworkReadStream::fillWithSendingContents(char *bufferToFill, uint32 maxSize) {
|
||||||
|
uint32 size = _sendingContentsSize - _sendingContentsPos;
|
||||||
|
if (size > maxSize) size = maxSize;
|
||||||
|
for (uint32 i = 0; i < size; ++i) {
|
||||||
|
bufferToFill[i] = _sendingContentsBuffer[_sendingContentsPos + i];
|
||||||
|
}
|
||||||
|
_sendingContentsPos += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Cloud
|
} // End of namespace Cloud
|
||||||
|
|
|
@ -35,10 +35,13 @@ namespace Networking {
|
||||||
class NetworkReadStream: public Common::MemoryReadWriteStream {
|
class NetworkReadStream: public Common::MemoryReadWriteStream {
|
||||||
CURL *_easy;
|
CURL *_easy;
|
||||||
bool _eos, _requestComplete;
|
bool _eos, _requestComplete;
|
||||||
|
byte *_sendingContentsBuffer;
|
||||||
|
uint32 _sendingContentsSize;
|
||||||
|
uint32 _sendingContentsPos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields);
|
NetworkReadStream(const char *url, curl_slist *headersList, Common::String postFields, bool uploading = false);
|
||||||
NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool post = true);
|
NetworkReadStream(const char *url, curl_slist *headersList, byte *buffer, uint32 bufferSize, bool uploading = false, bool post = true);
|
||||||
virtual ~NetworkReadStream();
|
virtual ~NetworkReadStream();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,6 +85,15 @@ public:
|
||||||
* @note This method should be called when eos() == true.
|
* @note This method should be called when eos() == true.
|
||||||
*/
|
*/
|
||||||
long httpResponseCode() const;
|
long httpResponseCode() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills the passed buffer with _sendingContentsBuffer contents.
|
||||||
|
* It works similarly to read(), expect it's not for reading
|
||||||
|
* Stream's contents, but for sending our own data to the server.
|
||||||
|
*
|
||||||
|
* @returns how many bytes were actually read (filled in)
|
||||||
|
*/
|
||||||
|
uint32 fillWithSendingContents(char *bufferToFill, uint32 maxSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Networking
|
} // End of namespace Networking
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue