diff options
Diffstat (limited to 'backends/cloud/dropbox')
-rw-r--r-- | backends/cloud/dropbox/dropboxstorage.cpp | 20 | ||||
-rw-r--r-- | backends/cloud/dropbox/dropboxstorage.h | 3 | ||||
-rw-r--r-- | backends/cloud/dropbox/dropboxuploadrequest.cpp | 163 | ||||
-rw-r--r-- | backends/cloud/dropbox/dropboxuploadrequest.h | 60 |
4 files changed, 244 insertions, 2 deletions
diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index b1dd865ee2..1220a99035 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -23,15 +23,16 @@ #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h" +#include "backends/cloud/dropbox/dropboxuploadrequest.h" #include "backends/cloud/downloadrequest.h" #include "backends/cloud/folderdownloadrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "common/config-manager.h" #include "common/debug.h" +#include "common/file.h" #include "common/json.h" #include <curl/curl.h> -#include <common/file.h> namespace Cloud { namespace Dropbox { @@ -99,10 +100,18 @@ void DropboxStorage::printFiles(FileArrayResponse pair) { debug("\t%s", files[i].name().c_str()); } +void DropboxStorage::printBool(BoolResponse pair) { + debug("bool: %s", (pair.value?"true":"false")); +} + Networking::Request *DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); } +Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback) { + return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback)); +} + Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) { Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("path", new Common::JSONValue(path)); @@ -139,11 +148,20 @@ Networking::Request *DropboxStorage::syncSaves(BoolCallback callback) { //"" is root in Dropbox, not "/" //this must create all these directories: //return download("/remote/test.jpg", "local/a/b/c/d/test.jpg", 0); + /* return downloadFolder( "/not_flat", "local/not_flat_1_level/", new Common::Callback<DropboxStorage, FileArrayResponse>(this, &DropboxStorage::printFiles), false ); + */ + Common::File *file = new Common::File(); + if (!file->open("final.bmp")) { + warning("no such file"); + delete file; + return nullptr; + } + return upload("/remote/test3.bmp", file, new Common::Callback<DropboxStorage, BoolResponse>(this, &DropboxStorage::printBool)); } Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index da508d7844..cc515fef41 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -46,6 +46,7 @@ class DropboxStorage: public Cloud::Storage { void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); void printFiles(FileArrayResponse pair); + void printBool(BoolResponse pair); public: virtual ~DropboxStorage(); @@ -69,7 +70,7 @@ public: virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); /** Calls the callback when finished. */ - virtual Networking::Request *upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback); /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback); diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp new file mode 100644 index 0000000000..d068078502 --- /dev/null +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -0,0 +1,163 @@ +/* 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/dropbox/dropboxuploadrequest.h" +#include "backends/cloud/storage.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/curljsonrequest.h" +#include "common/json.h" +#include "common/debug.h" + +namespace Cloud { +namespace Dropbox { + +DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::BoolCallback callback): + Networking::Request(0), _token(token), _savePath(path), _contentsStream(contents), _boolCallback(callback), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +DropboxUploadRequest::~DropboxUploadRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _contentsStream; + delete _boolCallback; +} + + +void DropboxUploadRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + if (!_contentsStream->seek(0)) { + warning("DropboxUploadRequest: cannot restart because stream couldn't seek(0)"); + finish(); + } + _ignoreCallback = false; + + uploadNextPart(); +} + +void DropboxUploadRequest::uploadNextPart() { + const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; + + Common::String url = "https://content.dropboxapi.com/2/files/upload_session/"; + Common::JSONObject jsonRequestParameters; + + if (_contentsStream->pos() == 0 || _sessionId == "") { + url += "start"; + jsonRequestParameters.setVal("close", new Common::JSONValue(false)); + } else { + if (_contentsStream->size() - _contentsStream->pos() <= UPLOAD_PER_ONE_REQUEST) { + url += "finish"; + Common::JSONObject jsonCursor, jsonCommit; + jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId)); + jsonCursor.setVal("offset", new Common::JSONValue(_contentsStream->pos())); + jsonCommit.setVal("path", new Common::JSONValue(_savePath)); + jsonCommit.setVal("mode", new Common::JSONValue("overwrite")); + jsonCommit.setVal("autorename", new Common::JSONValue(false)); + jsonCommit.setVal("mute", new Common::JSONValue(false)); + jsonRequestParameters.setVal("cursor", new Common::JSONValue(jsonCursor)); + jsonRequestParameters.setVal("commit", new Common::JSONValue(jsonCommit)); + } else { + url += "append_v2"; + Common::JSONObject jsonCursor; + jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId)); + jsonCursor.setVal("offset", new Common::JSONValue(_contentsStream->pos())); + jsonRequestParameters.setVal("cursor", new Common::JSONValue(jsonCursor)); + jsonRequestParameters.setVal("close", new Common::JSONValue(false)); + } + } + + Common::JSONValue value(jsonRequestParameters); + Networking::JsonCallback innerCallback = new Common::Callback<DropboxUploadRequest, Networking::JsonResponse>(this, &DropboxUploadRequest::partUploadedCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, url); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Content-Type: application/octet-stream"); + request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); + + byte *buffer = new byte[UPLOAD_PER_ONE_REQUEST]; + uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST); + request->setBuffer(buffer, size); + + _workingRequest = ConnMan.addRequest(request); +} + +void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) { + if (_ignoreCallback) return; + _workingRequest = nullptr; + + Common::JSONValue *json = pair.value; + if (json) { + bool needsFinishRequest = false; + + if (json->isObject()) { + Common::JSONObject response = json->asObject(); + + //debug("%s", json->stringify(true).c_str()); + + if (response.contains("error") || response.contains("error_summary")) { + warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str()); + delete json; + finish(); + return; + } + + if (response.contains("server_modified")) { + //finished + finishBool(true); + return; + } + + if (_sessionId == "") { + if (response.contains("session_id")) + _sessionId = response.getVal("session_id")->asString(); + else + warning("no session_id found in Dropbox's response"); + needsFinishRequest = true; + } + } + + if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) + finishBool(true); + else + uploadNextPart(); + } else { + warning("null, not json"); + finish(); + } + + delete json; +} + +void DropboxUploadRequest::handle() {} + +void DropboxUploadRequest::restart() { start(); } + +void DropboxUploadRequest::finish() { finishBool(false); } + +void DropboxUploadRequest::finishBool(bool success) { + Request::finish(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +} // End of namespace Dropbox +} // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxuploadrequest.h b/backends/cloud/dropbox/dropboxuploadrequest.h new file mode 100644 index 0000000000..a7d7a6c581 --- /dev/null +++ b/backends/cloud/dropbox/dropboxuploadrequest.h @@ -0,0 +1,60 @@ +/* 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_DROPBOX_DROPBOXUPLOADREQUEST_H +#define BACKENDS_CLOUD_DROPBOX_DROPBOXUPLOADREQUEST_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 Dropbox { + +class DropboxUploadRequest: public Networking::Request { + Common::String _token; + Common::String _savePath; + Common::SeekableReadStream *_contentsStream; + Storage::BoolCallback _boolCallback; + Request *_workingRequest; + bool _ignoreCallback; + Common::String _sessionId; + + void start(); + void uploadNextPart(); + void partUploadedCallback(Networking::JsonResponse pair); + void finishBool(bool success); + +public: + DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::BoolCallback callback); + virtual ~DropboxUploadRequest(); + + virtual void handle(); + virtual void restart(); + virtual void finish(); +}; + +} // End of namespace Dropbox +} // End of namespace Cloud + +#endif |