From e53e3d188b9da424af5e44e51bff265f077ce05e Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 24 May 2016 00:14:24 +0600 Subject: CLOUD: Add DropboxListDirectoryRequest Does multiple CurlJsonRequests while Dropbox returns "has_more" = true. --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 114 +++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp new file mode 100644 index 0000000000..e28a445d63 --- /dev/null +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -0,0 +1,114 @@ +/* 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/dropboxlistdirectoryrequest.h" +#include "backends/cloud/iso8601.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace Dropbox { + +DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive): + Networking::Request(0), _filesCallback(cb), _token(token), _complete(false) { + Common::BaseCallback<> *innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback);//new Common::GlobalFunctionCallback(printJson); //okay + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Content-Type: application/json"); + + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("path", new Common::JSONValue(path)); + jsonRequestParameters.setVal("recursive", new Common::JSONValue(recursive)); + jsonRequestParameters.setVal("include_media_info", new Common::JSONValue(false)); + jsonRequestParameters.setVal("include_deleted", new Common::JSONValue(false)); + + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + ConnMan.addRequest(request); +} + +void DropboxListDirectoryRequest::responseCallback(void *jsonPtr) { + Common::JSONValue *json = (Common::JSONValue *)jsonPtr; + if (json) { + Common::JSONObject response = json->asObject(); + + if (response.contains("error") || response.contains("error_summary")) { + warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str()); + _complete = true; + delete json; + return; + } + + //TODO: check that all keys exist to avoid segfaults + //TODO: get more files in the folder to check "has_more" case + + Common::JSONArray items = response.getVal("entries")->asArray(); + for (uint32 i = 0; i < items.size(); ++i) { + Common::JSONObject item = items[i]->asObject(); + Common::String path = item.getVal("path_lower")->asString(); + bool isDirectory = (item.getVal(".tag")->asString() == "folder"); + uint32 size = 0, timestamp = 0; + if (!isDirectory) { + size = item.getVal("size")->asNumber(); + timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString()); + } + _files.push_back(StorageFile(path, size, timestamp, isDirectory)); + } + + bool hasMore = response.getVal("has_more")->asBool(); + + if (hasMore) { + Common::BaseCallback<> *innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Content-Type: application/json"); + + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("cursor", new Common::JSONValue(response.getVal("cursor")->asString())); + + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + ConnMan.addRequest(request); + } else { + _complete = true; + } + } else { + warning("null, not json"); + _complete = true; + } + + delete json; +} + +bool DropboxListDirectoryRequest::handle() { + if (_complete && _filesCallback) { + (*_filesCallback)(_files); + } + + return _complete; +} + + +} //end of namespace Dropbox +} //end of namespace Cloud -- cgit v1.2.3 From 826a2a921cd0b0a72f71dd6f323097a2f449fab0 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 24 May 2016 11:57:49 +0600 Subject: CLOUD: Add DownloadRequest stub It reads the passed NetworkReadStream and prints its contents onto console (for now). It would be writing contents into file. To simplify work with raw NetworkReadStream there is a new CurlRequest. It basically does nothing, but as ConnMan handles transfers only if there is an active Request, you need some Request to get NetworkReadStream working. Thus, there is a CurlRequest, which is active until NetworkReadStream is completely read. CurlRequest also has useful addHeader() and addPostField() methods in order to customize the request easily. Use execute() method to get its NetworkReadStream. DropboxStorage implements streamFile() and download() API methods. As DownloadRequest is incomplete, it is not actually downloading a file, though. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index e28a445d63..5e5957b12c 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -24,6 +24,7 @@ #include "backends/cloud/iso8601.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" +#include "common/json.h" namespace Cloud { namespace Dropbox { -- cgit v1.2.3 From 62ccf1f902100febfb1be02b67e84a6e4938ebbf Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 26 May 2016 17:56:13 +0600 Subject: CLOUD: Add RequestInfo struct ConnectionManager upgrade: it now contains a special struct for each request, so you can access request status and data by request id. --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 34 +++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 5e5957b12c..3dada884a0 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -30,24 +30,33 @@ namespace Cloud { namespace Dropbox { DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive): - Networking::Request(0), _filesCallback(cb), _token(token), _complete(false) { - Common::BaseCallback<> *innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback);//new Common::GlobalFunctionCallback(printJson); //okay + Networking::Request(0), _requestedPath(path), _requestedRecursive(recursive), _filesCallback(cb), + _token(token), _complete(false), _requestId(-1) { + startupWork(); +} + +void DropboxListDirectoryRequest::startupWork() { + _files.clear(); + _complete = false; + + Common::BaseCallback<> *innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); Common::JSONObject jsonRequestParameters; - jsonRequestParameters.setVal("path", new Common::JSONValue(path)); - jsonRequestParameters.setVal("recursive", new Common::JSONValue(recursive)); + jsonRequestParameters.setVal("path", new Common::JSONValue(_requestedPath)); + jsonRequestParameters.setVal("recursive", new Common::JSONValue(_requestedRecursive)); jsonRequestParameters.setVal("include_media_info", new Common::JSONValue(false)); jsonRequestParameters.setVal("include_deleted", new Common::JSONValue(false)); Common::JSONValue value(jsonRequestParameters); request->addPostField(Common::JSON::stringify(&value)); - ConnMan.addRequest(request); + _requestId = ConnMan.addRequest(request); } + void DropboxListDirectoryRequest::responseCallback(void *jsonPtr) { Common::JSONValue *json = (Common::JSONValue *)jsonPtr; if (json) { @@ -103,13 +112,24 @@ void DropboxListDirectoryRequest::responseCallback(void *jsonPtr) { } bool DropboxListDirectoryRequest::handle() { - if (_complete && _filesCallback) { - (*_filesCallback)(_files); + if (_complete && _filesCallback) { + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_filesCallback) (*_filesCallback)(_files); } return _complete; } +void DropboxListDirectoryRequest::restart() { + if (_requestId != -1) { + Networking::RequestInfo &info = ConnMan.getRequestInfo(_requestId); + //TODO: I'm really not sure some CurlRequest would handle this (it must stop corresponding CURL transfer) + info.state = Networking::FINISHED; //may be CANCELED or INTERRUPTED or something? + _requestId = -1; + } + + startupWork(); +} } //end of namespace Dropbox } //end of namespace Cloud -- cgit v1.2.3 From f4547f44df32ce1f49a6a36df083e7703751adcd Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 26 May 2016 19:02:55 +0600 Subject: CLOUD: Add RequestIdPair struct Can be used with Callback (means it's still type safe). It's used to pass not only Request id to user's callback, but also a value user wanted. void *data field is removed from RequestInfo. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 3dada884a0..be9304081e 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -25,6 +25,7 @@ #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "common/json.h" +#include "backends/cloud/storage.h" namespace Cloud { namespace Dropbox { @@ -39,7 +40,7 @@ void DropboxListDirectoryRequest::startupWork() { _files.clear(); _complete = false; - Common::BaseCallback<> *innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::DataCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); @@ -57,8 +58,8 @@ void DropboxListDirectoryRequest::startupWork() { } -void DropboxListDirectoryRequest::responseCallback(void *jsonPtr) { - Common::JSONValue *json = (Common::JSONValue *)jsonPtr; +void DropboxListDirectoryRequest::responseCallback(Networking::RequestDataPair pair) { + Common::JSONValue *json = (Common::JSONValue *)pair.value; if (json) { Common::JSONObject response = json->asObject(); @@ -88,7 +89,7 @@ void DropboxListDirectoryRequest::responseCallback(void *jsonPtr) { bool hasMore = response.getVal("has_more")->asBool(); if (hasMore) { - Common::BaseCallback<> *innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::DataCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); @@ -114,7 +115,7 @@ void DropboxListDirectoryRequest::responseCallback(void *jsonPtr) { bool DropboxListDirectoryRequest::handle() { if (_complete && _filesCallback) { ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_filesCallback) (*_filesCallback)(_files); + if (_filesCallback) (*_filesCallback)(Storage::RequestFileArrayPair(_id, _files)); } return _complete; -- cgit v1.2.3 From a7b28605a01b59de6f3acc9df4cd1cac707c39e7 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 26 May 2016 19:09:06 +0600 Subject: CLOUD: Change Request::handle() With new ConnectionManager upgrade Requests indicate that they are finished with RequestInfo.state. No need to use handle() return value anymore. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index be9304081e..31f015a1cd 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -112,13 +112,11 @@ void DropboxListDirectoryRequest::responseCallback(Networking::RequestDataPair p delete json; } -bool DropboxListDirectoryRequest::handle() { - if (_complete && _filesCallback) { +void DropboxListDirectoryRequest::handle() { + if (_complete) { ConnMan.getRequestInfo(_id).state = Networking::FINISHED; if (_filesCallback) (*_filesCallback)(Storage::RequestFileArrayPair(_id, _files)); } - - return _complete; } void DropboxListDirectoryRequest::restart() { -- cgit v1.2.3 From b246c17850687e7b15b644b761fbfe835ffc1c32 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 26 May 2016 19:22:27 +0600 Subject: CLOUD: Fix CurlJsonRequest to use JsonCallback Type safety first. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 31f015a1cd..3158149c02 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -40,7 +40,7 @@ void DropboxListDirectoryRequest::startupWork() { _files.clear(); _complete = false; - Networking::DataCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); @@ -58,8 +58,8 @@ void DropboxListDirectoryRequest::startupWork() { } -void DropboxListDirectoryRequest::responseCallback(Networking::RequestDataPair pair) { - Common::JSONValue *json = (Common::JSONValue *)pair.value; +void DropboxListDirectoryRequest::responseCallback(Networking::RequestJsonPair pair) { + Common::JSONValue *json = pair.value; if (json) { Common::JSONObject response = json->asObject(); @@ -89,7 +89,7 @@ void DropboxListDirectoryRequest::responseCallback(Networking::RequestDataPair p bool hasMore = response.getVal("has_more")->asBool(); if (hasMore) { - Networking::DataCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); -- cgit v1.2.3 From 98150beb38f73b56c7bc76f95dcc1d72290e4ac7 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 15:21:06 +0600 Subject: CLOUD: Refactor ConnectionManager/Requests system ConnectionManager now storages Request * (not generates ids for it), Requests have control on their RequestState, RequestIdPair is now called Response and storages Request * with some response together. All related classes are changed to use it in more clean and understandable way. Request, RequestState and Response are carefully commented/documented. --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 3158149c02..04fbf46ac6 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -32,7 +32,7 @@ namespace Dropbox { DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive): Networking::Request(0), _requestedPath(path), _requestedRecursive(recursive), _filesCallback(cb), - _token(token), _complete(false), _requestId(-1) { + _token(token), _complete(false), _innerRequest(nullptr) { startupWork(); } @@ -40,7 +40,7 @@ void DropboxListDirectoryRequest::startupWork() { _files.clear(); _complete = false; - Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); @@ -54,11 +54,11 @@ void DropboxListDirectoryRequest::startupWork() { Common::JSONValue value(jsonRequestParameters); request->addPostField(Common::JSON::stringify(&value)); - _requestId = ConnMan.addRequest(request); + _innerRequest = ConnMan.addRequest(request); } -void DropboxListDirectoryRequest::responseCallback(Networking::RequestJsonPair pair) { +void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair) { Common::JSONValue *json = pair.value; if (json) { Common::JSONObject response = json->asObject(); @@ -89,7 +89,7 @@ void DropboxListDirectoryRequest::responseCallback(Networking::RequestJsonPair p bool hasMore = response.getVal("has_more")->asBool(); if (hasMore) { - Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); @@ -113,22 +113,28 @@ void DropboxListDirectoryRequest::responseCallback(Networking::RequestJsonPair p } void DropboxListDirectoryRequest::handle() { - if (_complete) { - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_filesCallback) (*_filesCallback)(Storage::RequestFileArrayPair(_id, _files)); - } + if (_complete) finishFiles(_files); } void DropboxListDirectoryRequest::restart() { - if (_requestId != -1) { - Networking::RequestInfo &info = ConnMan.getRequestInfo(_requestId); + if (_innerRequest) { //TODO: I'm really not sure some CurlRequest would handle this (it must stop corresponding CURL transfer) - info.state = Networking::FINISHED; //may be CANCELED or INTERRUPTED or something? - _requestId = -1; + _innerRequest->finish(); //may be CANCELED or INTERRUPTED or something? + _innerRequest = nullptr; } startupWork(); } +void DropboxListDirectoryRequest::finish() { + Common::Array files; + finishFiles(files); +} + +void DropboxListDirectoryRequest::finishFiles(Common::Array &files) { + Request::finish(); + if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); +} + } //end of namespace Dropbox } //end of namespace Cloud -- cgit v1.2.3 From 81c34adaef269524b1f53adcac722aa6a9730075 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sat, 28 May 2016 20:10:38 +0200 Subject: Fix comment formatting --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 04fbf46ac6..6ea90c150d 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -136,5 +136,5 @@ void DropboxListDirectoryRequest::finishFiles(Common::Array &files) if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); } -} //end of namespace Dropbox -} //end of namespace Cloud +} // End of namespace Dropbox +} // End of namespace Cloud -- cgit v1.2.3 From b9e3730ccd9a76101ef0cb8812f41c371a24d0d6 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 30 May 2016 13:35:53 +0600 Subject: CLOUD: Add UploadStatus struct It contains not just "success" flag, but also "file" struct, so the caller can find out some information about uploaded file - like timestamp. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 6ea90c150d..89e92facb8 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -76,11 +76,11 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair Common::JSONArray items = response.getVal("entries")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { Common::JSONObject item = items[i]->asObject(); - Common::String path = item.getVal("path_lower")->asString(); + Common::String path = item.getVal("path_lower")->asString(); bool isDirectory = (item.getVal(".tag")->asString() == "folder"); uint32 size = 0, timestamp = 0; if (!isDirectory) { - size = item.getVal("size")->asNumber(); + size = item.getVal("size")->asIntegerNumber(); timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString()); } _files.push_back(StorageFile(path, size, timestamp, isDirectory)); -- cgit v1.2.3 From aa987e5c52899bfafff4f1f84479a67761569109 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 30 May 2016 18:13:31 +0600 Subject: CLOUD: Add ListDirectoryStatus struct It contains flags to indicate whether Request was interrupted or failed, so dependent Requests may see that list is incomplete. --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 97 ++++++++++++---------- 1 file changed, 55 insertions(+), 42 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 89e92facb8..2796a4c19e 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -22,23 +22,32 @@ #include "backends/cloud/dropbox/dropboxlistdirectoryrequest.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 "backends/cloud/storage.h" namespace Cloud { namespace Dropbox { -DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive): - Networking::Request(0), _requestedPath(path), _requestedRecursive(recursive), _filesCallback(cb), - _token(token), _complete(false), _innerRequest(nullptr) { - startupWork(); +DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, bool recursive): + Networking::Request(0), _requestedPath(path), _requestedRecursive(recursive), _listDirectoryCallback(cb), + _token(token), _workingRequest(nullptr), _ignoreCallback(false) { + start(); } -void DropboxListDirectoryRequest::startupWork() { +DropboxListDirectoryRequest::~DropboxListDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _listDirectoryCallback; +} + +void DropboxListDirectoryRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); _files.clear(); - _complete = false; + _ignoreCallback = false; Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); @@ -54,39 +63,50 @@ void DropboxListDirectoryRequest::startupWork() { Common::JSONValue value(jsonRequestParameters); request->addPostField(Common::JSON::stringify(&value)); - _innerRequest = ConnMan.addRequest(request); + _workingRequest = ConnMan.addRequest(request); } void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + ListDirectoryStatus status(_files); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request; + if (rq && rq->getNetworkReadStream()) + status.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + Common::JSONValue *json = pair.value; if (json) { Common::JSONObject response = json->asObject(); if (response.contains("error") || response.contains("error_summary")) { warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str()); - _complete = true; + status.failed = true; + status.response = json->stringify(); + finishStatus(status); delete json; return; } - //TODO: check that all keys exist to avoid segfaults - //TODO: get more files in the folder to check "has_more" case - - Common::JSONArray items = response.getVal("entries")->asArray(); - for (uint32 i = 0; i < items.size(); ++i) { - Common::JSONObject item = items[i]->asObject(); - Common::String path = item.getVal("path_lower")->asString(); - bool isDirectory = (item.getVal(".tag")->asString() == "folder"); - uint32 size = 0, timestamp = 0; - if (!isDirectory) { - size = item.getVal("size")->asIntegerNumber(); - timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString()); + //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults + + if (response.contains("entries")) { + Common::JSONArray items = response.getVal("entries")->asArray(); + for (uint32 i = 0; i < items.size(); ++i) { + Common::JSONObject item = items[i]->asObject(); + Common::String path = item.getVal("path_lower")->asString(); + bool isDirectory = (item.getVal(".tag")->asString() == "folder"); + uint32 size = 0, timestamp = 0; + if (!isDirectory) { + size = item.getVal("size")->asIntegerNumber(); + timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString()); + } + _files.push_back(StorageFile(path, size, timestamp, isDirectory)); } - _files.push_back(StorageFile(path, size, timestamp, isDirectory)); } - bool hasMore = response.getVal("has_more")->asBool(); + bool hasMore = (response.contains("has_more") && response.getVal("has_more")->asBool()); if (hasMore) { Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); @@ -100,40 +120,33 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair Common::JSONValue value(jsonRequestParameters); request->addPostField(Common::JSON::stringify(&value)); - ConnMan.addRequest(request); - } else { - _complete = true; + _workingRequest = ConnMan.addRequest(request); + } else { + finishStatus(status); } } else { warning("null, not json"); - _complete = true; + status.failed = true; + finishStatus(status); } delete json; } -void DropboxListDirectoryRequest::handle() { - if (_complete) finishFiles(_files); -} +void DropboxListDirectoryRequest::handle() {} -void DropboxListDirectoryRequest::restart() { - if (_innerRequest) { - //TODO: I'm really not sure some CurlRequest would handle this (it must stop corresponding CURL transfer) - _innerRequest->finish(); //may be CANCELED or INTERRUPTED or something? - _innerRequest = nullptr; - } - - startupWork(); -} +void DropboxListDirectoryRequest::restart() { start(); } void DropboxListDirectoryRequest::finish() { Common::Array files; - finishFiles(files); + ListDirectoryStatus status(files); + status.interrupted = true; + finishStatus(status); } -void DropboxListDirectoryRequest::finishFiles(Common::Array &files) { +void DropboxListDirectoryRequest::finishStatus(ListDirectoryStatus status) { Request::finish(); - if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, status)); } } // End of namespace Dropbox -- cgit v1.2.3 From eb63b50b7f0841e40365f3fbafa9810e8b190872 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 01:51:32 +0600 Subject: CLOUD: Refactor Request Added ErrorResponse and ErrorCallback. Each Request now has an ErrorCallback, which should be called instead of usual callback in case of failure. --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 72 +++++++++++----------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 2796a4c19e..d782f81a69 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -31,8 +31,8 @@ namespace Cloud { namespace Dropbox { -DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, bool recursive): - Networking::Request(0), _requestedPath(path), _requestedRecursive(recursive), _listDirectoryCallback(cb), +DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), _requestedPath(path), _requestedRecursive(recursive), _listDirectoryCallback(cb), _token(token), _workingRequest(nullptr), _ignoreCallback(false) { start(); } @@ -49,8 +49,9 @@ void DropboxListDirectoryRequest::start() { _files.clear(); _ignoreCallback = false; - Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder"); + Networking::JsonCallback callback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxListDirectoryRequest::errorCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, "https://api.dropboxapi.com/2/files/list_folder"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); @@ -66,33 +67,32 @@ void DropboxListDirectoryRequest::start() { _workingRequest = ConnMan.addRequest(request); } - -void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair) { +void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - ListDirectoryStatus status(_files); - Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request; + Networking::ErrorResponse error(this); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq && rq->getNetworkReadStream()) - status.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - Common::JSONValue *json = pair.value; + Common::JSONValue *json = response.value; if (json) { - Common::JSONObject response = json->asObject(); + Common::JSONObject responseObjecct = json->asObject(); - if (response.contains("error") || response.contains("error_summary")) { - warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str()); - status.failed = true; - status.response = json->stringify(); - finishStatus(status); + if (responseObjecct.contains("error") || responseObjecct.contains("error_summary")) { + warning("Dropbox returned error: %s", responseObjecct.getVal("error_summary")->asString().c_str()); + error.failed = true; + error.response = json->stringify(); + finishError(error); delete json; return; } //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults - if (response.contains("entries")) { - Common::JSONArray items = response.getVal("entries")->asArray(); + if (responseObjecct.contains("entries")) { + Common::JSONArray items = responseObjecct.getVal("entries")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { Common::JSONObject item = items[i]->asObject(); Common::String path = item.getVal("path_lower")->asString(); @@ -106,47 +106,47 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse pair } } - bool hasMore = (response.contains("has_more") && response.getVal("has_more")->asBool()); + bool hasMore = (responseObjecct.contains("has_more") && responseObjecct.getVal("has_more")->asBool()); - if (hasMore) { - Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); + if (hasMore) { + Networking::JsonCallback callback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxListDirectoryRequest::errorCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); Common::JSONObject jsonRequestParameters; - jsonRequestParameters.setVal("cursor", new Common::JSONValue(response.getVal("cursor")->asString())); + jsonRequestParameters.setVal("cursor", new Common::JSONValue(responseObjecct.getVal("cursor")->asString())); Common::JSONValue value(jsonRequestParameters); request->addPostField(Common::JSON::stringify(&value)); _workingRequest = ConnMan.addRequest(request); } else { - finishStatus(status); + finishSuccess(_files); } } else { warning("null, not json"); - status.failed = true; - finishStatus(status); + error.failed = true; + finishError(error); } delete json; } +void DropboxListDirectoryRequest::errorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + void DropboxListDirectoryRequest::handle() {} void DropboxListDirectoryRequest::restart() { start(); } -void DropboxListDirectoryRequest::finish() { - Common::Array files; - ListDirectoryStatus status(files); - status.interrupted = true; - finishStatus(status); -} - -void DropboxListDirectoryRequest::finishStatus(ListDirectoryStatus status) { - Request::finish(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, status)); +void DropboxListDirectoryRequest::finishSuccess(Common::Array &files) { + Request::finishSuccess(); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace Dropbox -- cgit v1.2.3 From 3e6503743c2f5d90c64bf37e943338c33fc58d2b Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 10 Jun 2016 15:01:56 +0600 Subject: CLOUD: Add Request::date() Used in SavesSyncRequest to update Storage's last sync date. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index d782f81a69..933ea2bd8e 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -71,6 +71,8 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq && rq->getNetworkReadStream()) @@ -137,6 +139,7 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp void DropboxListDirectoryRequest::errorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -144,6 +147,8 @@ void DropboxListDirectoryRequest::handle() {} void DropboxListDirectoryRequest::restart() { start(); } +Common::String DropboxListDirectoryRequest::date() const { return _date; } + void DropboxListDirectoryRequest::finishSuccess(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); -- cgit v1.2.3 From f3a392359be2f6d05bac107a5f7bd168c178e428 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 21 Jun 2016 17:07:23 +0600 Subject: CLOUD: Fix finishSuccess() warning --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 933ea2bd8e..dcbca3131e 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -125,7 +125,7 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp _workingRequest = ConnMan.addRequest(request); } else { - finishSuccess(_files); + finishListing(_files); } } else { warning("null, not json"); @@ -149,7 +149,7 @@ void DropboxListDirectoryRequest::restart() { start(); } Common::String DropboxListDirectoryRequest::date() const { return _date; } -void DropboxListDirectoryRequest::finishSuccess(Common::Array &files) { +void DropboxListDirectoryRequest::finishListing(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } -- cgit v1.2.3 From 438ba985a4a97a8695a6e6fdda6930694976c07b Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 21 Jul 2016 11:44:36 +0600 Subject: JANITORIAL: Remove spaces at the end of the line I knew there were some, but I wanted to fix them once, instead of doing it all the time. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index dcbca3131e..cc82f123b1 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -81,7 +81,7 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp Common::JSONValue *json = response.value; if (json) { Common::JSONObject responseObjecct = json->asObject(); - + if (responseObjecct.contains("error") || responseObjecct.contains("error_summary")) { warning("Dropbox returned error: %s", responseObjecct.getVal("error_summary")->asString().c_str()); error.failed = true; @@ -91,7 +91,7 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp return; } - //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults + //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults if (responseObjecct.contains("entries")) { Common::JSONArray items = responseObjecct.getVal("entries")->asArray(); @@ -110,7 +110,7 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp bool hasMore = (responseObjecct.contains("has_more") && responseObjecct.getVal("has_more")->asBool()); - if (hasMore) { + if (hasMore) { Networking::JsonCallback callback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxListDirectoryRequest::errorCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); @@ -124,9 +124,9 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp request->addPostField(Common::JSON::stringify(&value)); _workingRequest = ConnMan.addRequest(request); - } else { + } else { finishListing(_files); - } + } } else { warning("null, not json"); error.failed = true; @@ -149,7 +149,7 @@ void DropboxListDirectoryRequest::restart() { start(); } Common::String DropboxListDirectoryRequest::date() const { return _date; } -void DropboxListDirectoryRequest::finishListing(Common::Array &files) { +void DropboxListDirectoryRequest::finishListing(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } -- cgit v1.2.3 From d57fca4665e65bca1cf487fb109d020d1233e800 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 22 Jul 2016 15:38:24 +0300 Subject: CLOUD: JANITORIAL: Fix code formatting --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index cc82f123b1..def9155f4e 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -39,13 +39,15 @@ DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, C DropboxListDirectoryRequest::~DropboxListDirectoryRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _listDirectoryCallback; } void DropboxListDirectoryRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _files.clear(); _ignoreCallback = false; @@ -69,9 +71,11 @@ void DropboxListDirectoryRequest::start() { void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; - if (response.request) _date = response.request->date(); + if (response.request) + _date = response.request->date(); Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -138,8 +142,10 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp void DropboxListDirectoryRequest::errorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); + if (_ignoreCallback) + return; + if (error.request) + _date = error.request->date(); finishError(error); } @@ -151,7 +157,8 @@ Common::String DropboxListDirectoryRequest::date() const { return _date; } void DropboxListDirectoryRequest::finishListing(Common::Array &files) { Request::finishSuccess(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); + if (_listDirectoryCallback) + (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace Dropbox -- cgit v1.2.3 From f3959e140106334b33cf74832fc5b20d27407d0a Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 22 Jul 2016 20:02:36 +0600 Subject: CLOUD: Upload ListDirectory Requests Lots of checks to avoid JSON-related segfaults added. --- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index def9155f4e..2e1d61812a 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -71,8 +71,10 @@ void DropboxListDirectoryRequest::start() { void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) + if (_ignoreCallback) { + delete response.value; return; + } if (response.request) _date = response.request->date(); -- cgit v1.2.3 From d57e0c89b5b20dac247cb2f43450014d84719ba6 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 22 Jul 2016 20:54:02 +0600 Subject: CLOUD: #define all OAuth2/API-related URLs --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 133 +++++++++++++++------ 1 file changed, 94 insertions(+), 39 deletions(-) (limited to 'backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp') diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp index 2e1d61812a..8b00f7c2bf 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp @@ -31,6 +31,9 @@ namespace Cloud { namespace Dropbox { +#define DROPBOX_API_LIST_FOLDER "https://api.dropboxapi.com/2/files/list_folder" +#define DROPBOX_API_LIST_FOLDER_CONTINUE "https://api.dropboxapi.com/2/files/list_folder/continue" + DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): Networking::Request(nullptr, ecb), _requestedPath(path), _requestedRecursive(recursive), _listDirectoryCallback(cb), _token(token), _workingRequest(nullptr), _ignoreCallback(false) { @@ -53,7 +56,7 @@ void DropboxListDirectoryRequest::start() { Networking::JsonCallback callback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxListDirectoryRequest::errorCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, "https://api.dropboxapi.com/2/files/list_folder"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, DROPBOX_API_LIST_FOLDER); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); @@ -71,6 +74,7 @@ void DropboxListDirectoryRequest::start() { void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; + if (_ignoreCallback) { delete response.value; return; @@ -85,58 +89,109 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); Common::JSONValue *json = response.value; - if (json) { - Common::JSONObject responseObjecct = json->asObject(); + if (json == nullptr) { + error.response = "Failed to parse JSON, null passed!"; + finishError(error); + return; + } + + if (!json->isObject()) { + error.response = "Passed JSON is not an object!"; + finishError(error); + delete json; + return; + } + + Common::JSONObject responseObject = json->asObject(); + + if (responseObject.contains("error") || responseObject.contains("error_summary")) { + if (responseObject.contains("error_summary") && responseObject.getVal("error_summary")->isString()) { + warning("Dropbox returned error: %s", responseObject.getVal("error_summary")->asString().c_str()); + } + error.failed = true; + error.response = json->stringify(); + finishError(error); + delete json; + return; + } - if (responseObjecct.contains("error") || responseObjecct.contains("error_summary")) { - warning("Dropbox returned error: %s", responseObjecct.getVal("error_summary")->asString().c_str()); - error.failed = true; - error.response = json->stringify(); + //check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults + if (responseObject.contains("entries")) { + if (!responseObject.getVal("entries")->isArray()) { + error.response = Common::String::format( + "\"entries\" found, but that's not an array!\n%s", + responseObject.getVal("entries")->stringify(true).c_str() + ); finishError(error); delete json; return; } - //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults - - if (responseObjecct.contains("entries")) { - Common::JSONArray items = responseObjecct.getVal("entries")->asArray(); - for (uint32 i = 0; i < items.size(); ++i) { - Common::JSONObject item = items[i]->asObject(); - Common::String path = item.getVal("path_lower")->asString(); - bool isDirectory = (item.getVal(".tag")->asString() == "folder"); - uint32 size = 0, timestamp = 0; - if (!isDirectory) { - size = item.getVal("size")->asIntegerNumber(); - timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString()); - } - _files.push_back(StorageFile(path, size, timestamp, isDirectory)); + Common::JSONArray items = responseObject.getVal("entries")->asArray(); + for (uint32 i = 0; i < items.size(); ++i) { + if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "DropboxListDirectoryRequest")) + continue; + + Common::JSONObject item = items[i]->asObject(); + + if (!Networking::CurlJsonRequest::jsonContainsString(item, "path_lower", "DropboxListDirectoryRequest")) + continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, ".tag", "DropboxListDirectoryRequest")) + continue; + + Common::String path = item.getVal("path_lower")->asString(); + bool isDirectory = (item.getVal(".tag")->asString() == "folder"); + uint32 size = 0, timestamp = 0; + if (!isDirectory) { + if (!Networking::CurlJsonRequest::jsonContainsString(item, "server_modified", "DropboxListDirectoryRequest")) + continue; + if (!Networking::CurlJsonRequest::jsonContainsIntegerNumber(item, "size", "DropboxListDirectoryRequest")) + continue; + + size = item.getVal("size")->asIntegerNumber(); + timestamp = ISO8601::convertToTimestamp(item.getVal("server_modified")->asString()); } + _files.push_back(StorageFile(path, size, timestamp, isDirectory)); } + } - bool hasMore = (responseObjecct.contains("has_more") && responseObjecct.getVal("has_more")->asBool()); + bool hasMore = false; + if (responseObject.contains("has_more")) { + if (!responseObject.getVal("has_more")->isBool()) { + warning("DropboxListDirectoryRequest: \"has_more\" is not a boolean"); + debug(9, "%s", responseObject.getVal("has_more")->stringify(true).c_str()); + error.response = "\"has_more\" is not a boolean!"; + finishError(error); + delete json; + return; + } - if (hasMore) { - Networking::JsonCallback callback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxListDirectoryRequest::errorCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, "https://api.dropboxapi.com/2/files/list_folder/continue"); - request->addHeader("Authorization: Bearer " + _token); - request->addHeader("Content-Type: application/json"); + hasMore = responseObject.getVal("has_more")->asBool(); + } - Common::JSONObject jsonRequestParameters; - jsonRequestParameters.setVal("cursor", new Common::JSONValue(responseObjecct.getVal("cursor")->asString())); + if (hasMore) { + if (!Networking::CurlJsonRequest::jsonContainsString(responseObject, "cursor", "DropboxListDirectoryRequest")) { + error.response = "\"has_more\" found, but \"cursor\" is not (or it's not a string)!"; + finishError(error); + delete json; + return; + } - Common::JSONValue value(jsonRequestParameters); - request->addPostField(Common::JSON::stringify(&value)); + Networking::JsonCallback callback = new Common::Callback(this, &DropboxListDirectoryRequest::responseCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxListDirectoryRequest::errorCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, DROPBOX_API_LIST_FOLDER_CONTINUE); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Content-Type: application/json"); - _workingRequest = ConnMan.addRequest(request); - } else { - finishListing(_files); - } + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("cursor", new Common::JSONValue(responseObject.getVal("cursor")->asString())); + + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + _workingRequest = ConnMan.addRequest(request); } else { - warning("null, not json"); - error.failed = true; - finishError(error); + finishListing(_files); } delete json; -- cgit v1.2.3