ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

dropboxuploadrequest.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "backends/cloud/dropbox/dropboxuploadrequest.h"
00024 #include "backends/cloud/iso8601.h"
00025 #include "backends/cloud/storage.h"
00026 #include "backends/networking/curl/connectionmanager.h"
00027 #include "backends/networking/curl/curljsonrequest.h"
00028 #include "backends/networking/curl/networkreadstream.h"
00029 #include "common/json.h"
00030 
00031 namespace Cloud {
00032 namespace Dropbox {
00033 
00034 #define DROPBOX_API_FILES_UPLOAD "https://content.dropboxapi.com/2/files/upload"
00035 #define DROPBOX_API_FILES_UPLOAD_SESSION "https://content.dropboxapi.com/2/files/upload_session/"
00036 
00037 DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb):
00038     Networking::Request(nullptr, ecb), _token(token), _savePath(path), _contentsStream(contents), _uploadCallback(callback),
00039     _workingRequest(nullptr), _ignoreCallback(false) {
00040     start();
00041 }
00042 
00043 DropboxUploadRequest::~DropboxUploadRequest() {
00044     _ignoreCallback = true;
00045     if (_workingRequest)
00046         _workingRequest->finish();
00047     delete _contentsStream;
00048     delete _uploadCallback;
00049 }
00050 
00051 void DropboxUploadRequest::start() {
00052     _ignoreCallback = true;
00053     if (_workingRequest)
00054         _workingRequest->finish();
00055     if (!_contentsStream) {
00056         warning("DropboxUploadRequest: cannot start because stream is invalid");
00057         finishError(Networking::ErrorResponse(this, false, true, "", -1));
00058         return;
00059     }
00060     if (!_contentsStream->seek(0)) {
00061         warning("DropboxUploadRequest: cannot restart because stream couldn't seek(0)");
00062         finishError(Networking::ErrorResponse(this, false, true, "", -1));
00063         return;
00064     }
00065     _ignoreCallback = false;
00066 
00067     uploadNextPart();
00068 }
00069 
00070 void DropboxUploadRequest::uploadNextPart() {
00071     const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024;
00072 
00073     Common::String url = DROPBOX_API_FILES_UPLOAD_SESSION;
00074     Common::JSONObject jsonRequestParameters;
00075 
00076     if (_contentsStream->pos() == 0 || _sessionId == "") {
00077         if ((uint32)_contentsStream->size() <= UPLOAD_PER_ONE_REQUEST) {
00078             url = DROPBOX_API_FILES_UPLOAD;
00079             jsonRequestParameters.setVal("path", new Common::JSONValue(_savePath));
00080             jsonRequestParameters.setVal("mode", new Common::JSONValue("overwrite"));
00081             jsonRequestParameters.setVal("autorename", new Common::JSONValue(false));
00082             jsonRequestParameters.setVal("mute", new Common::JSONValue(false));
00083         } else {
00084             url += "start";
00085             jsonRequestParameters.setVal("close", new Common::JSONValue(false));
00086         }
00087     } else {
00088         if ((uint32)(_contentsStream->size() - _contentsStream->pos()) <= UPLOAD_PER_ONE_REQUEST) {
00089             url += "finish";
00090             Common::JSONObject jsonCursor, jsonCommit;
00091             jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId));
00092             jsonCursor.setVal("offset", new Common::JSONValue((long long int)_contentsStream->pos()));
00093             jsonCommit.setVal("path", new Common::JSONValue(_savePath));
00094             jsonCommit.setVal("mode", new Common::JSONValue("overwrite"));
00095             jsonCommit.setVal("autorename", new Common::JSONValue(false));
00096             jsonCommit.setVal("mute", new Common::JSONValue(false));
00097             jsonRequestParameters.setVal("cursor", new Common::JSONValue(jsonCursor));
00098             jsonRequestParameters.setVal("commit", new Common::JSONValue(jsonCommit));
00099         } else {
00100             url += "append_v2";
00101             Common::JSONObject jsonCursor;
00102             jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId));
00103             jsonCursor.setVal("offset", new Common::JSONValue((long long int)_contentsStream->pos()));
00104             jsonRequestParameters.setVal("cursor", new Common::JSONValue(jsonCursor));
00105             jsonRequestParameters.setVal("close", new Common::JSONValue(false));
00106         }
00107     }
00108 
00109     Common::JSONValue value(jsonRequestParameters);
00110     Networking::JsonCallback callback = new Common::Callback<DropboxUploadRequest, Networking::JsonResponse>(this, &DropboxUploadRequest::partUploadedCallback);
00111     Networking::ErrorCallback failureCallback = new Common::Callback<DropboxUploadRequest, Networking::ErrorResponse>(this, &DropboxUploadRequest::partUploadedErrorCallback);
00112     Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, url);
00113     request->addHeader("Authorization: Bearer " + _token);
00114     request->addHeader("Content-Type: application/octet-stream");
00115     request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value));
00116 
00117     byte *buffer = new byte[UPLOAD_PER_ONE_REQUEST];
00118     uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST);
00119     request->setBuffer(buffer, size);
00120 
00121     _workingRequest = ConnMan.addRequest(request);
00122 }
00123 
00124 void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse response) {
00125     _workingRequest = nullptr;
00126     if (_ignoreCallback)
00127         return;
00128 
00129     Networking::ErrorResponse error(this, false, true, "", -1);
00130     Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request;
00131     if (rq && rq->getNetworkReadStream())
00132         error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
00133 
00134     Common::JSONValue *json = response.value;
00135     if (json == nullptr) {
00136         error.response = "Failed to parse JSON, null passed!";
00137         finishError(error);
00138         return;
00139     }
00140 
00141     bool needsFinishRequest = false;
00142 
00143     if (json->isObject()) {
00144         Common::JSONObject object = json->asObject();
00145 
00146         //debug(9, "%s", json->stringify(true).c_str());
00147 
00148         if (object.contains("error") || object.contains("error_summary")) {
00149             if (Networking::CurlJsonRequest::jsonContainsString(object, "error_summary", "DropboxUploadRequest")) {
00150                 warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str());
00151             }
00152             error.response = json->stringify(true);
00153             finishError(error);
00154             delete json;
00155             return;
00156         }
00157 
00158         if (Networking::CurlJsonRequest::jsonContainsString(object, "path_lower", "DropboxUploadRequest") &&
00159             Networking::CurlJsonRequest::jsonContainsString(object, "server_modified", "DropboxUploadRequest") &&
00160             Networking::CurlJsonRequest::jsonContainsIntegerNumber(object, "size", "DropboxUploadRequest")) {
00161             //finished
00162             Common::String path = object.getVal("path_lower")->asString();
00163             uint32 size = object.getVal("size")->asIntegerNumber();
00164             uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("server_modified")->asString());
00165             finishUpload(StorageFile(path, size, timestamp, false));
00166             return;
00167         }
00168 
00169         if (_sessionId == "") {
00170             if (Networking::CurlJsonRequest::jsonContainsString(object, "session_id", "DropboxUploadRequest"))
00171                 _sessionId = object.getVal("session_id")->asString();
00172             needsFinishRequest = true;
00173         }
00174     }
00175 
00176     if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) {
00177         warning("DropboxUploadRequest: no file info to return");
00178         finishUpload(StorageFile(_savePath, 0, 0, false));
00179     } else {
00180         uploadNextPart();
00181     }
00182 
00183     delete json;
00184 }
00185 
00186 void DropboxUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) {
00187     _workingRequest = nullptr;
00188     if (_ignoreCallback)
00189         return;
00190     finishError(error);
00191 }
00192 
00193 void DropboxUploadRequest::handle() {}
00194 
00195 void DropboxUploadRequest::restart() { start(); }
00196 
00197 void DropboxUploadRequest::finishUpload(StorageFile file) {
00198     Request::finishSuccess();
00199     if (_uploadCallback)
00200         (*_uploadCallback)(Storage::UploadResponse(this, file));
00201 }
00202 
00203 } // End of namespace Dropbox
00204 } // End of namespace Cloud


Generated on Sat May 18 2019 05:01:00 for ResidualVM by doxygen 1.7.1
curved edge   curved edge