From 8429c40362b1e4d4010f808740b79baae69c97ed Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 11 May 2016 01:10:37 +0600 Subject: CLOUD: Add SimpleJSON library as Common::JSON This commit also adds CloudThread class, which work() method is called every second by TimerManager. Right now it prints JSON examples on the console, so that's why it's introduced with SimpleJSON library. --- backends/cloud/cloudthread.cpp | 199 +++++++++++++++++++++++++++++++++++++++++ backends/cloud/cloudthread.h | 35 ++++++++ 2 files changed, 234 insertions(+) create mode 100644 backends/cloud/cloudthread.cpp create mode 100644 backends/cloud/cloudthread.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudthread.cpp b/backends/cloud/cloudthread.cpp new file mode 100644 index 0000000000..ac405e0fd7 --- /dev/null +++ b/backends/cloud/cloudthread.cpp @@ -0,0 +1,199 @@ +#include "cloudthread.h" +#include "../../common/debug.h" +#include "../../common/json.h" + +void example1(); +void example2(); +void example3(); + +void cloudThread(void *thread) { + CloudThread *cloudThread = (CloudThread *)thread; + cloudThread->work(); +}; + +void CloudThread::work() { + if(firstTime) { + firstTime = false; + + example1(); + example2(); + example3(); + } else { + } +} + +/// SimpleJSON examples: + +using Common::JSON; +using Common::JSONValue; +using Common::JSONArray; +using Common::JSONObject; + +// Just some sample JSON text, feel free to change but could break demo +const char* EXAMPLE = "\ +{ \ + \"string_name\" : \"string\tvalue and a \\\"quote\\\" and a unicode char \\u00BE and a c:\\\\path\\\\ or a \\/unix\\/path\\/ :D\", \ + \"bool_name\" : true, \ + \"bool_second\" : FaLsE, \ + \"null_name\" : nULl, \ + \"negative\" : -34.276, \ + \"sub_object\" : { \ + \"foo\" : \"abc\", \ + \"bar\" : 1.35e2, \ + \"blah\" : { \"a\" : \"A\", \"b\" : \"B\", \"c\" : \"C\" } \ + }, \ + \"array_letters\" : [ \"a\", \"b\", \"c\", [ 1, 2, 3 ] ] \ +} "; + +// Example 1 +void example1() +{ + // Parse example data + JSONValue *value = JSON::Parse(EXAMPLE); + + // Did it go wrong? + if (value == NULL) + { + debug("Example code failed to parse, did you change it?\r\n"); + } + else + { + // Retrieve the main object + JSONObject root; + if (value->IsObject() == false) + { + debug("The root element is not an object, did you change the example?\r\n"); + } + else + { + root = value->AsObject(); + + // Retrieving a string + if (root.find("string_name") != root.end() && root["string_name"]->IsString()) + { + debug("string_name:\r\n"); + debug("------------\r\n"); + debug(root["string_name"]->AsString().c_str()); + debug("\r\n\r\n"); + } + + // Retrieving a boolean + if (root.find("bool_second") != root.end() && root["bool_second"]->IsBool()) + { + debug("bool_second:\r\n"); + debug("------------\r\n"); + debug(root["bool_second"]->AsBool() ? "it's true!" : "it's false!"); + debug("\r\n\r\n"); + } + + // Retrieving an array + if (root.find("array_letters") != root.end() && root["array_letters"]->IsArray()) + { + JSONArray array = root["array_letters"]->AsArray(); + debug("array_letters:\r\n"); + debug("--------------\r\n"); + for (unsigned int i = 0; i < array.size(); i++) + { + //wstringstream output; + debug("[%d] => %s\r\n", i, array[i]->Stringify().c_str()); + } + debug("\r\n"); + } + + // Retrieving nested object + if (root.find("sub_object") != root.end() && root["sub_object"]->IsObject()) + { + debug("sub_object:\r\n"); + debug("-----------\r\n"); + debug(root["sub_object"]->Stringify().c_str()); + debug("\r\n\r\n"); + } + } + + delete value; + } +} + +// Example 3 : compact vs. prettyprint +void example2() +{ + const char* EXAMPLE3 = + "{\ + \"SelectedTab\":\"Math\",\ + \"Widgets\":[\ + {\"WidgetPosition\":[0,369,800,582],\"WidgetIndex\":1,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[235,453,283,489],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F2.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":2,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[235,494,283,530],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F3.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":3,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[235,536,283,572],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F4.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":4,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[287,417,400,439],\"IsWidgetVisible\":-1,\"Caption\":\"\",\"EnableCaption\":0,\"Name\":\"F1.Equation\",\"CaptionPosition\":1,\"ControlWidth\":113,\"ControlHeight\":22,\"Font\":0,\"AlignText\":0,\"EnableBorder\":0,\"CaptionOnly\":0,\"Value\":\"FFT(C1)\",\"WidgetIndex\":9,\"WidgetType\":\"WidgetStaticText.1\"},\ + {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":0,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.MeasureOpGui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Measurement To Graph\",\"Value\":\"Amplitude\",\"WidgetIndex\":17,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ + {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":-1,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"FFT\",\"WidgetIndex\":25,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ + {\"WidgetPosition\":[191,452,230,487],\"IsWidgetVisible\":-1,\"Caption\":\"F2\",\"EnableCaption\":0,\"Name\":\"F2.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"Zoom\",\"WidgetIndex\":26,\"WidgetType\":\"WidgetProcessorCombobox.1\"}\ + ]\ + }"; + + // Parse example data + JSONValue *value = JSON::Parse(EXAMPLE3); + if (value) + { + debug("-----------\r\n"); + debug(value->Stringify().c_str()); + debug("\r\n"); + debug("-----------\r\n"); + debug(value->Stringify(true).c_str()); + debug("\r\n"); + debug("-----------\r\n"); + } + + // Clean up + delete value; +} + +// Example 4 : List keys in an object. +void example3() +{ + // Parse the example. + JSONValue *main_object = JSON::Parse(EXAMPLE); + if (main_object == NULL) + { + debug("Example code failed to parse, did you change it?\r\n"); + } + else if (!main_object->IsObject()) + { + debug("Example code is not an object, did you change it?\r\n"); + delete main_object; + } + else + { + // Print the main object. + debug("Main object:\r\n"); + debug(main_object->Stringify(true).c_str()); + debug("-----------\r\n"); + + // Fetch the keys and print them out. + Common::Array keys = main_object->ObjectKeys(); + + Common::Array::iterator iter = keys.begin(); + while (iter != keys.end()) + { + debug("Key: "); + debug((*iter).c_str()); + debug("\r\n"); + + // Get the key's value. + JSONValue *key_value = main_object->Child((*iter).c_str()); + if (key_value) + { + debug("Value: "); + debug(key_value->Stringify().c_str()); + debug("\r\n"); + debug("-----------\r\n"); + } + + // Next key. + iter++; + } + + delete main_object; + } +} diff --git a/backends/cloud/cloudthread.h b/backends/cloud/cloudthread.h new file mode 100644 index 0000000000..dcab42f6ae --- /dev/null +++ b/backends/cloud/cloudthread.h @@ -0,0 +1,35 @@ +/* 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_CLOUDTHREAD_H +#define BACKENDS_CLOUD_CLOUDTHREAD_H + +void cloudThread(void *thread); //this one is passed to TimerManager in main() + +class CloudThread { + bool firstTime; +public: + CloudThread(): firstTime(true) {}; + void work(); +}; + +#endif -- cgit v1.2.3 From a7fb8c72ab0ca60161f5acad42774340ee08abab Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 11 May 2016 12:31:26 +0600 Subject: CLOUD: SimpleJSON refactor Resharper + manual methods & fields renaming. --- backends/cloud/cloudthread.cpp | 101 ++++++++++++++++------------------------- backends/cloud/cloudthread.h | 5 +- 2 files changed, 42 insertions(+), 64 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudthread.cpp b/backends/cloud/cloudthread.cpp index ac405e0fd7..e375d6fb2b 100644 --- a/backends/cloud/cloudthread.cpp +++ b/backends/cloud/cloudthread.cpp @@ -12,14 +12,13 @@ void cloudThread(void *thread) { }; void CloudThread::work() { - if(firstTime) { - firstTime = false; + if (_firstTime) { + _firstTime = false; example1(); example2(); example3(); - } else { - } + } else { } } /// SimpleJSON examples: @@ -30,7 +29,7 @@ using Common::JSONArray; using Common::JSONObject; // Just some sample JSON text, feel free to change but could break demo -const char* EXAMPLE = "\ +const char *EXAMPLE = "\ { \ \"string_name\" : \"string\tvalue and a \\\"quote\\\" and a unicode char \\u00BE and a c:\\\\path\\\\ or a \\/unix\\/path\\/ :D\", \ \"bool_name\" : true, \ @@ -46,66 +45,54 @@ const char* EXAMPLE = "\ } "; // Example 1 -void example1() -{ +void example1() { // Parse example data - JSONValue *value = JSON::Parse(EXAMPLE); + JSONValue *value = JSON::parse(EXAMPLE); // Did it go wrong? - if (value == NULL) - { + if (value == NULL) { debug("Example code failed to parse, did you change it?\r\n"); - } - else - { + } else { // Retrieve the main object JSONObject root; - if (value->IsObject() == false) - { + if (value->isObject() == false) { debug("The root element is not an object, did you change the example?\r\n"); - } - else - { - root = value->AsObject(); + } else { + root = value->asObject(); // Retrieving a string - if (root.find("string_name") != root.end() && root["string_name"]->IsString()) - { + if (root.find("string_name") != root.end() && root["string_name"]->isString()) { debug("string_name:\r\n"); debug("------------\r\n"); - debug(root["string_name"]->AsString().c_str()); + debug(root["string_name"]->asString().c_str()); debug("\r\n\r\n"); } // Retrieving a boolean - if (root.find("bool_second") != root.end() && root["bool_second"]->IsBool()) - { + if (root.find("bool_second") != root.end() && root["bool_second"]->isBool()) { debug("bool_second:\r\n"); debug("------------\r\n"); - debug(root["bool_second"]->AsBool() ? "it's true!" : "it's false!"); + debug(root["bool_second"]->asBool() ? "it's true!" : "it's false!"); debug("\r\n\r\n"); } // Retrieving an array - if (root.find("array_letters") != root.end() && root["array_letters"]->IsArray()) - { - JSONArray array = root["array_letters"]->AsArray(); + if (root.find("array_letters") != root.end() && root["array_letters"]->isArray()) { + JSONArray array = root["array_letters"]->asArray(); debug("array_letters:\r\n"); debug("--------------\r\n"); - for (unsigned int i = 0; i < array.size(); i++) - { + for (unsigned int i = 0; i < array.size(); i++) { //wstringstream output; - debug("[%d] => %s\r\n", i, array[i]->Stringify().c_str()); + debug("[%d] => %s\r\n", i, array[i]->stringify().c_str()); } debug("\r\n"); } // Retrieving nested object - if (root.find("sub_object") != root.end() && root["sub_object"]->IsObject()) - { + if (root.find("sub_object") != root.end() && root["sub_object"]->isObject()) { debug("sub_object:\r\n"); debug("-----------\r\n"); - debug(root["sub_object"]->Stringify().c_str()); + debug(root["sub_object"]->stringify().c_str()); debug("\r\n\r\n"); } } @@ -115,10 +102,9 @@ void example1() } // Example 3 : compact vs. prettyprint -void example2() -{ - const char* EXAMPLE3 = - "{\ +void example2() { + const char *EXAMPLE3 = + "{\ \"SelectedTab\":\"Math\",\ \"Widgets\":[\ {\"WidgetPosition\":[0,369,800,582],\"WidgetIndex\":1,\"WidgetType\":\"WidgetCheckbox.1\"},\ @@ -133,14 +119,13 @@ void example2() }"; // Parse example data - JSONValue *value = JSON::Parse(EXAMPLE3); - if (value) - { + JSONValue *value = JSON::parse(EXAMPLE3); + if (value) { debug("-----------\r\n"); - debug(value->Stringify().c_str()); + debug(value->stringify().c_str()); debug("\r\n"); debug("-----------\r\n"); - debug(value->Stringify(true).c_str()); + debug(value->stringify(true).c_str()); debug("\r\n"); debug("-----------\r\n"); } @@ -150,42 +135,34 @@ void example2() } // Example 4 : List keys in an object. -void example3() -{ +void example3() { // Parse the example. - JSONValue *main_object = JSON::Parse(EXAMPLE); - if (main_object == NULL) - { + JSONValue *main_object = JSON::parse(EXAMPLE); + if (main_object == NULL) { debug("Example code failed to parse, did you change it?\r\n"); - } - else if (!main_object->IsObject()) - { + } else if (!main_object->isObject()) { debug("Example code is not an object, did you change it?\r\n"); delete main_object; - } - else - { + } else { // Print the main object. debug("Main object:\r\n"); - debug(main_object->Stringify(true).c_str()); + debug(main_object->stringify(true).c_str()); debug("-----------\r\n"); // Fetch the keys and print them out. - Common::Array keys = main_object->ObjectKeys(); + Common::Array keys = main_object->objectKeys(); Common::Array::iterator iter = keys.begin(); - while (iter != keys.end()) - { + while (iter != keys.end()) { debug("Key: "); debug((*iter).c_str()); debug("\r\n"); // Get the key's value. - JSONValue *key_value = main_object->Child((*iter).c_str()); - if (key_value) - { + JSONValue *key_value = main_object->child((*iter).c_str()); + if (key_value) { debug("Value: "); - debug(key_value->Stringify().c_str()); + debug(key_value->stringify().c_str()); debug("\r\n"); debug("-----------\r\n"); } diff --git a/backends/cloud/cloudthread.h b/backends/cloud/cloudthread.h index dcab42f6ae..ce448b7274 100644 --- a/backends/cloud/cloudthread.h +++ b/backends/cloud/cloudthread.h @@ -26,9 +26,10 @@ void cloudThread(void *thread); //this one is passed to TimerManager in main() class CloudThread { - bool firstTime; + bool _firstTime; public: - CloudThread(): firstTime(true) {}; + CloudThread(): _firstTime(true) {}; + void work(); }; -- cgit v1.2.3 From 2ac2816d68c11b50796457f7d41896a1ed7d571e Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 11 May 2016 13:45:10 +0600 Subject: CLOUD: Refactor SimpleJSON --- backends/cloud/cloudthread.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudthread.cpp b/backends/cloud/cloudthread.cpp index e375d6fb2b..f8d93d2baa 100644 --- a/backends/cloud/cloudthread.cpp +++ b/backends/cloud/cloudthread.cpp @@ -1,6 +1,28 @@ +/* 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 "cloudthread.h" -#include "../../common/debug.h" -#include "../../common/json.h" +#include "common/debug.h" +#include "common/json.h" void example1(); void example2(); -- cgit v1.2.3 From 7446ffd73bd184610d550a354a8e252b0b7f334d Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 11 May 2016 15:15:23 +0600 Subject: CLOUD: Integrate CloudThread into OSystem Would be changed soon. --- backends/cloud/cloudthread.cpp | 21 +++++++++++++++++++-- backends/cloud/cloudthread.h | 11 ++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudthread.cpp b/backends/cloud/cloudthread.cpp index f8d93d2baa..813354f43f 100644 --- a/backends/cloud/cloudthread.cpp +++ b/backends/cloud/cloudthread.cpp @@ -23,6 +23,8 @@ #include "cloudthread.h" #include "common/debug.h" #include "common/json.h" +#include "common/system.h" +#include "common/timer.h" void example1(); void example2(); @@ -30,10 +32,10 @@ void example3(); void cloudThread(void *thread) { CloudThread *cloudThread = (CloudThread *)thread; - cloudThread->work(); + cloudThread->handler(); }; -void CloudThread::work() { +void CloudThread::handler() { if (_firstTime) { _firstTime = false; @@ -43,6 +45,21 @@ void CloudThread::work() { } else { } } +void CloudThread::setTimeout(int interval) { + Common::TimerManager *manager = g_system->getTimerManager(); + if (!manager->installTimerProc(cloudThread, interval, this, "Cloud Thread")) + warning("Failed to create cloud thread"); +} + +void CloudThread::unsetTimeout() { + Common::TimerManager *manager = g_system->getTimerManager(); + manager->removeTimerProc(cloudThread); +} + +void CloudThread::start() { + setTimeout(1000000); //in one second +} + /// SimpleJSON examples: using Common::JSON; diff --git a/backends/cloud/cloudthread.h b/backends/cloud/cloudthread.h index ce448b7274..334a163dde 100644 --- a/backends/cloud/cloudthread.h +++ b/backends/cloud/cloudthread.h @@ -23,14 +23,19 @@ #ifndef BACKENDS_CLOUD_CLOUDTHREAD_H #define BACKENDS_CLOUD_CLOUDTHREAD_H -void cloudThread(void *thread); //this one is passed to TimerManager in main() - class CloudThread { + friend void cloudThread(void*); //calls private handler() + bool _firstTime; + + void handler(); + void setTimeout(int interval); + void unsetTimeout(); + public: CloudThread(): _firstTime(true) {}; - void work(); + void start(); }; #endif -- cgit v1.2.3 From ca2eeb221455e54505aaef7039cfc0b01b807179 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 11 May 2016 20:24:53 +0600 Subject: CLOUD: Add Cloud::Manager and Cloud::Storage This commit introduces Common::CloudManager, which can be accessed from OSystem. The backend for this manager is Cloud::Manager (defined in backends/cloud/manager.h). It should load all users storages from configs and provide access to current Storage instance. For now it just creates a new one. Cloud::Storage (backends/cloud/storage.h) provides an API to interact with cloud storage, for example, create new directory or sync files. Right now it's not ready and has only two dummy methods: listDirectory() and syncSaves(). There is Cloud::Dropbox::DropboxStorage backend (backends/cloud/dropbox/dropboxstorage.h) for Cloud::Storage. Right now it implements both listDirectory() and syncSaves() with starting timer task and handling it by printing out some JSON examples. --- backends/cloud/cloudthread.cpp | 215 ------------------------------ backends/cloud/cloudthread.h | 41 ------ backends/cloud/dropbox/dropboxstorage.cpp | 205 ++++++++++++++++++++++++++++ backends/cloud/dropbox/dropboxstorage.h | 45 +++++++ backends/cloud/manager.cpp | 41 ++++++ backends/cloud/manager.h | 44 ++++++ backends/cloud/storage.cpp | 49 +++++++ backends/cloud/storage.h | 61 +++++++++ 8 files changed, 445 insertions(+), 256 deletions(-) delete mode 100644 backends/cloud/cloudthread.cpp delete mode 100644 backends/cloud/cloudthread.h create mode 100644 backends/cloud/dropbox/dropboxstorage.cpp create mode 100644 backends/cloud/dropbox/dropboxstorage.h create mode 100644 backends/cloud/manager.cpp create mode 100644 backends/cloud/manager.h create mode 100644 backends/cloud/storage.cpp create mode 100644 backends/cloud/storage.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudthread.cpp b/backends/cloud/cloudthread.cpp deleted file mode 100644 index 813354f43f..0000000000 --- a/backends/cloud/cloudthread.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* 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 "cloudthread.h" -#include "common/debug.h" -#include "common/json.h" -#include "common/system.h" -#include "common/timer.h" - -void example1(); -void example2(); -void example3(); - -void cloudThread(void *thread) { - CloudThread *cloudThread = (CloudThread *)thread; - cloudThread->handler(); -}; - -void CloudThread::handler() { - if (_firstTime) { - _firstTime = false; - - example1(); - example2(); - example3(); - } else { } -} - -void CloudThread::setTimeout(int interval) { - Common::TimerManager *manager = g_system->getTimerManager(); - if (!manager->installTimerProc(cloudThread, interval, this, "Cloud Thread")) - warning("Failed to create cloud thread"); -} - -void CloudThread::unsetTimeout() { - Common::TimerManager *manager = g_system->getTimerManager(); - manager->removeTimerProc(cloudThread); -} - -void CloudThread::start() { - setTimeout(1000000); //in one second -} - -/// SimpleJSON examples: - -using Common::JSON; -using Common::JSONValue; -using Common::JSONArray; -using Common::JSONObject; - -// Just some sample JSON text, feel free to change but could break demo -const char *EXAMPLE = "\ -{ \ - \"string_name\" : \"string\tvalue and a \\\"quote\\\" and a unicode char \\u00BE and a c:\\\\path\\\\ or a \\/unix\\/path\\/ :D\", \ - \"bool_name\" : true, \ - \"bool_second\" : FaLsE, \ - \"null_name\" : nULl, \ - \"negative\" : -34.276, \ - \"sub_object\" : { \ - \"foo\" : \"abc\", \ - \"bar\" : 1.35e2, \ - \"blah\" : { \"a\" : \"A\", \"b\" : \"B\", \"c\" : \"C\" } \ - }, \ - \"array_letters\" : [ \"a\", \"b\", \"c\", [ 1, 2, 3 ] ] \ -} "; - -// Example 1 -void example1() { - // Parse example data - JSONValue *value = JSON::parse(EXAMPLE); - - // Did it go wrong? - if (value == NULL) { - debug("Example code failed to parse, did you change it?\r\n"); - } else { - // Retrieve the main object - JSONObject root; - if (value->isObject() == false) { - debug("The root element is not an object, did you change the example?\r\n"); - } else { - root = value->asObject(); - - // Retrieving a string - if (root.find("string_name") != root.end() && root["string_name"]->isString()) { - debug("string_name:\r\n"); - debug("------------\r\n"); - debug(root["string_name"]->asString().c_str()); - debug("\r\n\r\n"); - } - - // Retrieving a boolean - if (root.find("bool_second") != root.end() && root["bool_second"]->isBool()) { - debug("bool_second:\r\n"); - debug("------------\r\n"); - debug(root["bool_second"]->asBool() ? "it's true!" : "it's false!"); - debug("\r\n\r\n"); - } - - // Retrieving an array - if (root.find("array_letters") != root.end() && root["array_letters"]->isArray()) { - JSONArray array = root["array_letters"]->asArray(); - debug("array_letters:\r\n"); - debug("--------------\r\n"); - for (unsigned int i = 0; i < array.size(); i++) { - //wstringstream output; - debug("[%d] => %s\r\n", i, array[i]->stringify().c_str()); - } - debug("\r\n"); - } - - // Retrieving nested object - if (root.find("sub_object") != root.end() && root["sub_object"]->isObject()) { - debug("sub_object:\r\n"); - debug("-----------\r\n"); - debug(root["sub_object"]->stringify().c_str()); - debug("\r\n\r\n"); - } - } - - delete value; - } -} - -// Example 3 : compact vs. prettyprint -void example2() { - const char *EXAMPLE3 = - "{\ - \"SelectedTab\":\"Math\",\ - \"Widgets\":[\ - {\"WidgetPosition\":[0,369,800,582],\"WidgetIndex\":1,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[235,453,283,489],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F2.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":2,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[235,494,283,530],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F3.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":3,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[235,536,283,572],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F4.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":4,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[287,417,400,439],\"IsWidgetVisible\":-1,\"Caption\":\"\",\"EnableCaption\":0,\"Name\":\"F1.Equation\",\"CaptionPosition\":1,\"ControlWidth\":113,\"ControlHeight\":22,\"Font\":0,\"AlignText\":0,\"EnableBorder\":0,\"CaptionOnly\":0,\"Value\":\"FFT(C1)\",\"WidgetIndex\":9,\"WidgetType\":\"WidgetStaticText.1\"},\ - {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":0,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.MeasureOpGui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Measurement To Graph\",\"Value\":\"Amplitude\",\"WidgetIndex\":17,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ - {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":-1,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"FFT\",\"WidgetIndex\":25,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ - {\"WidgetPosition\":[191,452,230,487],\"IsWidgetVisible\":-1,\"Caption\":\"F2\",\"EnableCaption\":0,\"Name\":\"F2.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"Zoom\",\"WidgetIndex\":26,\"WidgetType\":\"WidgetProcessorCombobox.1\"}\ - ]\ - }"; - - // Parse example data - JSONValue *value = JSON::parse(EXAMPLE3); - if (value) { - debug("-----------\r\n"); - debug(value->stringify().c_str()); - debug("\r\n"); - debug("-----------\r\n"); - debug(value->stringify(true).c_str()); - debug("\r\n"); - debug("-----------\r\n"); - } - - // Clean up - delete value; -} - -// Example 4 : List keys in an object. -void example3() { - // Parse the example. - JSONValue *main_object = JSON::parse(EXAMPLE); - if (main_object == NULL) { - debug("Example code failed to parse, did you change it?\r\n"); - } else if (!main_object->isObject()) { - debug("Example code is not an object, did you change it?\r\n"); - delete main_object; - } else { - // Print the main object. - debug("Main object:\r\n"); - debug(main_object->stringify(true).c_str()); - debug("-----------\r\n"); - - // Fetch the keys and print them out. - Common::Array keys = main_object->objectKeys(); - - Common::Array::iterator iter = keys.begin(); - while (iter != keys.end()) { - debug("Key: "); - debug((*iter).c_str()); - debug("\r\n"); - - // Get the key's value. - JSONValue *key_value = main_object->child((*iter).c_str()); - if (key_value) { - debug("Value: "); - debug(key_value->stringify().c_str()); - debug("\r\n"); - debug("-----------\r\n"); - } - - // Next key. - iter++; - } - - delete main_object; - } -} diff --git a/backends/cloud/cloudthread.h b/backends/cloud/cloudthread.h deleted file mode 100644 index 334a163dde..0000000000 --- a/backends/cloud/cloudthread.h +++ /dev/null @@ -1,41 +0,0 @@ -/* 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_CLOUDTHREAD_H -#define BACKENDS_CLOUD_CLOUDTHREAD_H - -class CloudThread { - friend void cloudThread(void*); //calls private handler() - - bool _firstTime; - - void handler(); - void setTimeout(int interval); - void unsetTimeout(); - -public: - CloudThread(): _firstTime(true) {}; - - void start(); -}; - -#endif diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp new file mode 100644 index 0000000000..b841575bf6 --- /dev/null +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -0,0 +1,205 @@ +/* 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/dropboxstorage.h" +#include "common/debug.h" +#include "common/json.h" + +void example1(); +void example2(); +void example3(); + +namespace Cloud { namespace Dropbox { + +void DropboxStorage::handler() { + if (_firstTime) { + _firstTime = false; + + example1(); + example2(); + example3(); + } else { } +} + +void DropboxStorage::listDirectory(Common::String path) { + setTimeout(1000000); //in one second +} + +void DropboxStorage::syncSaves() { + setTimeout(1000000); //in one second +} + +} } //end of namespace Cloud::Dropbox + +/// SimpleJSON examples: + +using Common::JSON; +using Common::JSONValue; +using Common::JSONArray; +using Common::JSONObject; + +// Just some sample JSON text, feel free to change but could break demo +const char *EXAMPLE = "\ +{ \ + \"string_name\" : \"string\tvalue and a \\\"quote\\\" and a unicode char \\u00BE and a c:\\\\path\\\\ or a \\/unix\\/path\\/ :D\", \ + \"bool_name\" : true, \ + \"bool_second\" : FaLsE, \ + \"null_name\" : nULl, \ + \"negative\" : -34.276, \ + \"sub_object\" : { \ + \"foo\" : \"abc\", \ + \"bar\" : 1.35e2, \ + \"blah\" : { \"a\" : \"A\", \"b\" : \"B\", \"c\" : \"C\" } \ + }, \ + \"array_letters\" : [ \"a\", \"b\", \"c\", [ 1, 2, 3 ] ] \ +} "; + +// Example 1 +void example1() { + // Parse example data + JSONValue *value = JSON::parse(EXAMPLE); + + // Did it go wrong? + if (value == NULL) { + debug("Example code failed to parse, did you change it?\r\n"); + } else { + // Retrieve the main object + JSONObject root; + if (value->isObject() == false) { + debug("The root element is not an object, did you change the example?\r\n"); + } else { + root = value->asObject(); + + // Retrieving a string + if (root.find("string_name") != root.end() && root["string_name"]->isString()) { + debug("string_name:\r\n"); + debug("------------\r\n"); + debug(root["string_name"]->asString().c_str()); + debug("\r\n\r\n"); + } + + // Retrieving a boolean + if (root.find("bool_second") != root.end() && root["bool_second"]->isBool()) { + debug("bool_second:\r\n"); + debug("------------\r\n"); + debug(root["bool_second"]->asBool() ? "it's true!" : "it's false!"); + debug("\r\n\r\n"); + } + + // Retrieving an array + if (root.find("array_letters") != root.end() && root["array_letters"]->isArray()) { + JSONArray array = root["array_letters"]->asArray(); + debug("array_letters:\r\n"); + debug("--------------\r\n"); + for (unsigned int i = 0; i < array.size(); i++) { + //wstringstream output; + debug("[%d] => %s\r\n", i, array[i]->stringify().c_str()); + } + debug("\r\n"); + } + + // Retrieving nested object + if (root.find("sub_object") != root.end() && root["sub_object"]->isObject()) { + debug("sub_object:\r\n"); + debug("-----------\r\n"); + debug(root["sub_object"]->stringify().c_str()); + debug("\r\n\r\n"); + } + } + + delete value; + } +} + +// Example 3 : compact vs. prettyprint +void example2() { + const char *EXAMPLE3 = + "{\ + \"SelectedTab\":\"Math\",\ + \"Widgets\":[\ + {\"WidgetPosition\":[0,369,800,582],\"WidgetIndex\":1,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[235,453,283,489],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F2.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":2,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[235,494,283,530],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F3.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":3,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[235,536,283,572],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F4.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":4,\"WidgetType\":\"WidgetCheckbox.1\"},\ + {\"WidgetPosition\":[287,417,400,439],\"IsWidgetVisible\":-1,\"Caption\":\"\",\"EnableCaption\":0,\"Name\":\"F1.Equation\",\"CaptionPosition\":1,\"ControlWidth\":113,\"ControlHeight\":22,\"Font\":0,\"AlignText\":0,\"EnableBorder\":0,\"CaptionOnly\":0,\"Value\":\"FFT(C1)\",\"WidgetIndex\":9,\"WidgetType\":\"WidgetStaticText.1\"},\ + {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":0,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.MeasureOpGui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Measurement To Graph\",\"Value\":\"Amplitude\",\"WidgetIndex\":17,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ + {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":-1,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"FFT\",\"WidgetIndex\":25,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ + {\"WidgetPosition\":[191,452,230,487],\"IsWidgetVisible\":-1,\"Caption\":\"F2\",\"EnableCaption\":0,\"Name\":\"F2.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"Zoom\",\"WidgetIndex\":26,\"WidgetType\":\"WidgetProcessorCombobox.1\"}\ + ]\ + }"; + + // Parse example data + JSONValue *value = JSON::parse(EXAMPLE3); + if (value) { + debug("-----------\r\n"); + debug(value->stringify().c_str()); + debug("\r\n"); + debug("-----------\r\n"); + debug(value->stringify(true).c_str()); + debug("\r\n"); + debug("-----------\r\n"); + } + + // Clean up + delete value; +} + +// Example 4 : List keys in an object. +void example3() { + // Parse the example. + JSONValue *main_object = JSON::parse(EXAMPLE); + if (main_object == NULL) { + debug("Example code failed to parse, did you change it?\r\n"); + } else if (!main_object->isObject()) { + debug("Example code is not an object, did you change it?\r\n"); + delete main_object; + } else { + // Print the main object. + debug("Main object:\r\n"); + debug(main_object->stringify(true).c_str()); + debug("-----------\r\n"); + + // Fetch the keys and print them out. + Common::Array keys = main_object->objectKeys(); + + Common::Array::iterator iter = keys.begin(); + while (iter != keys.end()) { + debug("Key: "); + debug((*iter).c_str()); + debug("\r\n"); + + // Get the key's value. + JSONValue *key_value = main_object->child((*iter).c_str()); + if (key_value) { + debug("Value: "); + debug(key_value->stringify().c_str()); + debug("\r\n"); + debug("-----------\r\n"); + } + + // Next key. + iter++; + } + + delete main_object; + } +} diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h new file mode 100644 index 0000000000..43ed9dcbee --- /dev/null +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -0,0 +1,45 @@ +/* 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_STORAGE_H +#define BACKENDS_CLOUD_DROPBOX_STORAGE_H + +#include "backends/cloud/storage.h" + +namespace Cloud { namespace Dropbox { + +class DropboxStorage: public Cloud::Storage { + bool _firstTime; + +protected: + virtual void handler(); + +public: + DropboxStorage() : _firstTime(true) {}; + + virtual void listDirectory(Common::String path); + virtual void syncSaves(); +}; + +} } //end of namespace Cloud::Dropbox + +#endif diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp new file mode 100644 index 0000000000..05b23771b0 --- /dev/null +++ b/backends/cloud/manager.cpp @@ -0,0 +1,41 @@ +/* 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/manager.h" +#include "backends/cloud/dropbox/dropboxstorage.h" + +namespace Cloud { + +Manager::Manager(): _currentStorage(new Dropbox::DropboxStorage()) {}; + +Manager::~Manager() { delete _currentStorage; } + +Storage* Manager::getCurrentStorage() { + return _currentStorage; +} + +void Manager::syncSaves() { + Storage* storage = getCurrentStorage(); + if (storage) storage->syncSaves(); +} + +} //end of namespace Cloud \ No newline at end of file diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h new file mode 100644 index 0000000000..11cc595da4 --- /dev/null +++ b/backends/cloud/manager.h @@ -0,0 +1,44 @@ +/* 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_MANAGER_H +#define BACKENDS_CLOUD_MANAGER_H + +#include "common/cloudmanager.h" +#include "common/str.h" + +namespace Cloud { + +class Manager: public Common::CloudManager { + Storage* _currentStorage; + +public: + Manager(); + virtual ~Manager(); + + virtual Storage* getCurrentStorage(); + virtual void syncSaves(); +}; + +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp new file mode 100644 index 0000000000..3272ecf760 --- /dev/null +++ b/backends/cloud/storage.cpp @@ -0,0 +1,49 @@ +/* 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/system.h" +#include "common/timer.h" + +namespace Cloud { + +void cloudThread(void *thread) { + Storage *cloudThread = (Storage *)thread; + cloudThread->handler(); +} + +void Storage::handler() { + unsetTimeout(); +} + +void Storage::setTimeout(int interval) { + Common::TimerManager *manager = g_system->getTimerManager(); + if (!manager->installTimerProc(cloudThread, interval, this, "Cloud Thread")) + ; // warning("Failed to create cloud thread"); +} + +void Storage::unsetTimeout() { + Common::TimerManager *manager = g_system->getTimerManager(); + manager->removeTimerProc(cloudThread); +} + +} //end of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h new file mode 100644 index 0000000000..4afa36f8d8 --- /dev/null +++ b/backends/cloud/storage.h @@ -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_STORAGE_H +#define BACKENDS_CLOUD_STORAGE_H + +#include "common/str.h" + +namespace Cloud { + +class Storage { + friend void cloudThread(void*); //calls handler() + +protected: + virtual void handler(); + virtual void setTimeout(int interval); + virtual void unsetTimeout(); + +public: + Storage() {}; + virtual ~Storage() {}; + + /** + * Lists given directory. + * + * @param path directory to list + */ + + //TODO: actually make it list directories and some callback to pass gathered files list + + virtual void listDirectory(Common::String path) = 0; + + /** + * Starts saves syncing process. + */ + + virtual void syncSaves() = 0; +}; + +} //end of namespace Cloud + +#endif -- cgit v1.2.3 From b272bba7519951f38aa1aa34c70197c7be1b63fd Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 12 May 2016 18:52:57 +0600 Subject: CLOUD: Do minor fixes --- backends/cloud/dropbox/dropboxstorage.cpp | 6 ++++-- backends/cloud/storage.cpp | 2 +- backends/cloud/storage.h | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index b841575bf6..a8e3076aae 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -28,7 +28,8 @@ void example1(); void example2(); void example3(); -namespace Cloud { namespace Dropbox { +namespace Cloud { +namespace Dropbox { void DropboxStorage::handler() { if (_firstTime) { @@ -48,7 +49,8 @@ void DropboxStorage::syncSaves() { setTimeout(1000000); //in one second } -} } //end of namespace Cloud::Dropbox +} //end of namespace Dropbox +} //end of namespace Cloud /// SimpleJSON examples: diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 3272ecf760..ca6b9bf70e 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -26,7 +26,7 @@ namespace Cloud { -void cloudThread(void *thread) { +static void cloudThread(void *thread) { Storage *cloudThread = (Storage *)thread; cloudThread->handler(); } diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 4afa36f8d8..e71b8b7aa0 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -28,7 +28,7 @@ namespace Cloud { class Storage { - friend void cloudThread(void*); //calls handler() + friend void cloudThread(void *); //calls handler() protected: virtual void handler(); @@ -45,7 +45,8 @@ public: * @param path directory to list */ - //TODO: actually make it list directories and some callback to pass gathered files list + //TODO: actually make it list directories + //TODO: add some callback to pass gathered files list virtual void listDirectory(Common::String path) = 0; -- cgit v1.2.3 From 1b89e25580c186fc2cc1821acee942e23fea3682 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 13 May 2016 17:23:28 +0600 Subject: CLOUD: Add first Request Just fooling around with the example Request, but the idea works well. --- backends/cloud/dropbox/dropboxstorage.cpp | 178 ++----------------------- backends/cloud/dropbox/dropboxstorage.h | 9 +- backends/cloud/dropbox/finalcountdownrequest.h | 52 ++++++++ backends/cloud/request.h | 53 ++++++++ backends/cloud/storage.cpp | 28 +++- backends/cloud/storage.h | 14 +- 6 files changed, 148 insertions(+), 186 deletions(-) create mode 100644 backends/cloud/dropbox/finalcountdownrequest.h create mode 100644 backends/cloud/request.h (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index a8e3076aae..8a0772dc3f 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -21,187 +21,25 @@ */ #include "backends/cloud/dropbox/dropboxstorage.h" +#include "backends/cloud/dropbox/finalcountdownrequest.h" #include "common/debug.h" -#include "common/json.h" - -void example1(); -void example2(); -void example3(); namespace Cloud { namespace Dropbox { -void DropboxStorage::handler() { - if (_firstTime) { - _firstTime = false; - - example1(); - example2(); - example3(); - } else { } +static void finalCountdownCallback(void *ptr) { + warning("ladies and gentlemen, this is your callback speaking"); + warning("the returned pointer is %d", ptr); + warning("thank you for your attention"); } void DropboxStorage::listDirectory(Common::String path) { - setTimeout(1000000); //in one second + startTimer(1000000); //in one second } -void DropboxStorage::syncSaves() { - setTimeout(1000000); //in one second +void DropboxStorage::syncSaves() { + addRequest(new FinalCountdownRequest(finalCountdownCallback)); } } //end of namespace Dropbox } //end of namespace Cloud - -/// SimpleJSON examples: - -using Common::JSON; -using Common::JSONValue; -using Common::JSONArray; -using Common::JSONObject; - -// Just some sample JSON text, feel free to change but could break demo -const char *EXAMPLE = "\ -{ \ - \"string_name\" : \"string\tvalue and a \\\"quote\\\" and a unicode char \\u00BE and a c:\\\\path\\\\ or a \\/unix\\/path\\/ :D\", \ - \"bool_name\" : true, \ - \"bool_second\" : FaLsE, \ - \"null_name\" : nULl, \ - \"negative\" : -34.276, \ - \"sub_object\" : { \ - \"foo\" : \"abc\", \ - \"bar\" : 1.35e2, \ - \"blah\" : { \"a\" : \"A\", \"b\" : \"B\", \"c\" : \"C\" } \ - }, \ - \"array_letters\" : [ \"a\", \"b\", \"c\", [ 1, 2, 3 ] ] \ -} "; - -// Example 1 -void example1() { - // Parse example data - JSONValue *value = JSON::parse(EXAMPLE); - - // Did it go wrong? - if (value == NULL) { - debug("Example code failed to parse, did you change it?\r\n"); - } else { - // Retrieve the main object - JSONObject root; - if (value->isObject() == false) { - debug("The root element is not an object, did you change the example?\r\n"); - } else { - root = value->asObject(); - - // Retrieving a string - if (root.find("string_name") != root.end() && root["string_name"]->isString()) { - debug("string_name:\r\n"); - debug("------------\r\n"); - debug(root["string_name"]->asString().c_str()); - debug("\r\n\r\n"); - } - - // Retrieving a boolean - if (root.find("bool_second") != root.end() && root["bool_second"]->isBool()) { - debug("bool_second:\r\n"); - debug("------------\r\n"); - debug(root["bool_second"]->asBool() ? "it's true!" : "it's false!"); - debug("\r\n\r\n"); - } - - // Retrieving an array - if (root.find("array_letters") != root.end() && root["array_letters"]->isArray()) { - JSONArray array = root["array_letters"]->asArray(); - debug("array_letters:\r\n"); - debug("--------------\r\n"); - for (unsigned int i = 0; i < array.size(); i++) { - //wstringstream output; - debug("[%d] => %s\r\n", i, array[i]->stringify().c_str()); - } - debug("\r\n"); - } - - // Retrieving nested object - if (root.find("sub_object") != root.end() && root["sub_object"]->isObject()) { - debug("sub_object:\r\n"); - debug("-----------\r\n"); - debug(root["sub_object"]->stringify().c_str()); - debug("\r\n\r\n"); - } - } - - delete value; - } -} - -// Example 3 : compact vs. prettyprint -void example2() { - const char *EXAMPLE3 = - "{\ - \"SelectedTab\":\"Math\",\ - \"Widgets\":[\ - {\"WidgetPosition\":[0,369,800,582],\"WidgetIndex\":1,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[235,453,283,489],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F2.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":2,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[235,494,283,530],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F3.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":3,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[235,536,283,572],\"IsWidgetVisible\":-1,\"Caption\":\"On\",\"EnableCaption\":-1,\"Name\":\"F4.View\",\"CaptionPosition\":2,\"ControlWidth\":25,\"ControlHeight\":36,\"Font\":0,\"Value\":\"Off\",\"WidgetIndex\":4,\"WidgetType\":\"WidgetCheckbox.1\"},\ - {\"WidgetPosition\":[287,417,400,439],\"IsWidgetVisible\":-1,\"Caption\":\"\",\"EnableCaption\":0,\"Name\":\"F1.Equation\",\"CaptionPosition\":1,\"ControlWidth\":113,\"ControlHeight\":22,\"Font\":0,\"AlignText\":0,\"EnableBorder\":0,\"CaptionOnly\":0,\"Value\":\"FFT(C1)\",\"WidgetIndex\":9,\"WidgetType\":\"WidgetStaticText.1\"},\ - {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":0,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.MeasureOpGui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Measurement To Graph\",\"Value\":\"Amplitude\",\"WidgetIndex\":17,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ - {\"WidgetPosition\":[191,409,230,445],\"IsWidgetVisible\":-1,\"Caption\":\"F1\",\"EnableCaption\":0,\"Name\":\"F1.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"FFT\",\"WidgetIndex\":25,\"WidgetType\":\"WidgetProcessorCombobox.1\"},\ - {\"WidgetPosition\":[191,452,230,487],\"IsWidgetVisible\":-1,\"Caption\":\"F2\",\"EnableCaption\":0,\"Name\":\"F2.Operator1gui\",\"CaptionPosition\":1,\"ControlWidth\":39,\"ControlHeight\":36,\"Font\":0,\"ButtonOnly\":-1,\"PickerTitle\":\"Select Math Operator\",\"Value\":\"Zoom\",\"WidgetIndex\":26,\"WidgetType\":\"WidgetProcessorCombobox.1\"}\ - ]\ - }"; - - // Parse example data - JSONValue *value = JSON::parse(EXAMPLE3); - if (value) { - debug("-----------\r\n"); - debug(value->stringify().c_str()); - debug("\r\n"); - debug("-----------\r\n"); - debug(value->stringify(true).c_str()); - debug("\r\n"); - debug("-----------\r\n"); - } - - // Clean up - delete value; -} - -// Example 4 : List keys in an object. -void example3() { - // Parse the example. - JSONValue *main_object = JSON::parse(EXAMPLE); - if (main_object == NULL) { - debug("Example code failed to parse, did you change it?\r\n"); - } else if (!main_object->isObject()) { - debug("Example code is not an object, did you change it?\r\n"); - delete main_object; - } else { - // Print the main object. - debug("Main object:\r\n"); - debug(main_object->stringify(true).c_str()); - debug("-----------\r\n"); - - // Fetch the keys and print them out. - Common::Array keys = main_object->objectKeys(); - - Common::Array::iterator iter = keys.begin(); - while (iter != keys.end()) { - debug("Key: "); - debug((*iter).c_str()); - debug("\r\n"); - - // Get the key's value. - JSONValue *key_value = main_object->child((*iter).c_str()); - if (key_value) { - debug("Value: "); - debug(key_value->stringify().c_str()); - debug("\r\n"); - debug("-----------\r\n"); - } - - // Next key. - iter++; - } - - delete main_object; - } -} diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 43ed9dcbee..f80854b987 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -27,14 +27,9 @@ namespace Cloud { namespace Dropbox { -class DropboxStorage: public Cloud::Storage { - bool _firstTime; - -protected: - virtual void handler(); - +class DropboxStorage: public Cloud::Storage { public: - DropboxStorage() : _firstTime(true) {}; + DropboxStorage() {}; virtual void listDirectory(Common::String path); virtual void syncSaves(); diff --git a/backends/cloud/dropbox/finalcountdownrequest.h b/backends/cloud/dropbox/finalcountdownrequest.h new file mode 100644 index 0000000000..34e8a807f9 --- /dev/null +++ b/backends/cloud/dropbox/finalcountdownrequest.h @@ -0,0 +1,52 @@ +/* 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_FINALCOUNTDOWNREQUEST_H +#define BACKENDS_CLOUD_DROPBOX_FINALCOUNTDOWNREQUEST_H + +#include "backends/cloud/request.h" + +namespace Cloud { +namespace Dropbox { + +class FinalCountdownRequest : public Cloud::Request { + int _times; + +public: + FinalCountdownRequest(Callback cb) : Request(cb), _times(5) {}; + + virtual bool handle() { + if(--_times == 0) { + warning("It's the final countdown!"); + _callback(0); //meh, don't have anything for you, my caller + return true; + } + + warning("%d...", _times); + return false; + } +}; + +} +} //end of namespace Cloud::Dropbox + +#endif diff --git a/backends/cloud/request.h b/backends/cloud/request.h new file mode 100644 index 0000000000..ae85c234f2 --- /dev/null +++ b/backends/cloud/request.h @@ -0,0 +1,53 @@ +/* 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_REQUEST_H +#define BACKENDS_CLOUD_REQUEST_H + +namespace Cloud { + +class Request { +protected: + /** + * Callback, which should be called before Request returns true in handle(). + * That's the way Requests pass the result to the code which asked to create this request. + */ + + typedef void(*Callback)(void *result); + Callback _callback; + +public: + Request(Callback cb): _callback(cb) {}; + virtual ~Request() {}; + + /** + * Method, which does actual work. Depends on what this Request is doing. + * + * @return true if request's work is complete and it may be removed from Storage's list + */ + + virtual bool handle() = 0; +}; + +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index ca6b9bf70e..597eb6bb13 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -31,19 +31,37 @@ static void cloudThread(void *thread) { cloudThread->handler(); } +Storage::Storage() : _timerStarted(false) {} + +void Storage::addRequest(Request *request) { + _requests.push_back(request); + if (!_timerStarted) startTimer(); +} + void Storage::handler() { - unsetTimeout(); + //TODO: lock mutex here (in case another handler() would be called before this one ends) + warning("handler's here"); + for (Common::Array::iterator i = _requests.begin(); i != _requests.end();) { + if ((*i)->handle()) _requests.erase(i); + else ++i; + } + if (_requests.empty()) stopTimer(); + //TODO: unlock mutex here } -void Storage::setTimeout(int interval) { +void Storage::startTimer(int interval) { Common::TimerManager *manager = g_system->getTimerManager(); - if (!manager->installTimerProc(cloudThread, interval, this, "Cloud Thread")) - ; // warning("Failed to create cloud thread"); + if (manager->installTimerProc(cloudThread, interval, this, "Cloud Thread")) { + _timerStarted = true; + } else { + warning("Failed to create cloud thread"); + } } -void Storage::unsetTimeout() { +void Storage::stopTimer() { Common::TimerManager *manager = g_system->getTimerManager(); manager->removeTimerProc(cloudThread); + _timerStarted = false; } } //end of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index e71b8b7aa0..dcaa6af213 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -24,19 +24,25 @@ #define BACKENDS_CLOUD_STORAGE_H #include "common/str.h" +#include "common/array.h" +#include "backends/cloud/request.h" namespace Cloud { class Storage { friend void cloudThread(void *); //calls handler() + bool _timerStarted; protected: - virtual void handler(); - virtual void setTimeout(int interval); - virtual void unsetTimeout(); + Common::Array _requests; + + virtual void addRequest(Request *request); //starts the timer if it's not started + virtual void handler(); + virtual void startTimer(int interval = 1000000); //1 second is the default interval + virtual void stopTimer(); public: - Storage() {}; + Storage(); virtual ~Storage() {}; /** -- cgit v1.2.3 From 6ad983bb7220eed2f635163a7fcfdac811b80ca0 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 13 May 2016 21:26:47 +0600 Subject: CLOUD: Fix GCC static cloudThread compile error It's not static anymore. --- backends/cloud/dropbox/finalcountdownrequest.h | 2 +- backends/cloud/manager.cpp | 4 ++-- backends/cloud/storage.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/finalcountdownrequest.h b/backends/cloud/dropbox/finalcountdownrequest.h index 34e8a807f9..5ef942180c 100644 --- a/backends/cloud/dropbox/finalcountdownrequest.h +++ b/backends/cloud/dropbox/finalcountdownrequest.h @@ -35,7 +35,7 @@ public: FinalCountdownRequest(Callback cb) : Request(cb), _times(5) {}; virtual bool handle() { - if(--_times == 0) { + if (--_times == 0) { warning("It's the final countdown!"); _callback(0); //meh, don't have anything for you, my caller return true; diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 05b23771b0..58bb0ce83f 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -25,7 +25,7 @@ namespace Cloud { -Manager::Manager(): _currentStorage(new Dropbox::DropboxStorage()) {}; +Manager::Manager(): _currentStorage(new Dropbox::DropboxStorage()) {} Manager::~Manager() { delete _currentStorage; } @@ -38,4 +38,4 @@ void Manager::syncSaves() { if (storage) storage->syncSaves(); } -} //end of namespace Cloud \ No newline at end of file +} //end of namespace Cloud diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 597eb6bb13..23dcd8c379 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -26,7 +26,7 @@ namespace Cloud { -static void cloudThread(void *thread) { +void cloudThread(void *thread) { Storage *cloudThread = (Storage *)thread; cloudThread->handler(); } -- cgit v1.2.3 From 8b585d631b21441dfa3de69d2c7c848d172c73be Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 15 May 2016 00:31:02 +0600 Subject: CLOUD: Add CurlRequest CurlRequest uses own multi_handle, in which it creates an easy_handle to make a request. Every time `handle()` is called it checks whether request is complete and, if it is, stops. --- backends/cloud/dropbox/curlrequest.cpp | 82 ++++++++++++++++++++++++++ backends/cloud/dropbox/curlrequest.h | 48 +++++++++++++++ backends/cloud/dropbox/dropboxstorage.cpp | 21 +++++-- backends/cloud/dropbox/dropboxstorage.h | 3 +- backends/cloud/dropbox/finalcountdownrequest.h | 52 ---------------- backends/cloud/storage.cpp | 5 +- 6 files changed, 151 insertions(+), 60 deletions(-) create mode 100644 backends/cloud/dropbox/curlrequest.cpp create mode 100644 backends/cloud/dropbox/curlrequest.h delete mode 100644 backends/cloud/dropbox/finalcountdownrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/curlrequest.cpp b/backends/cloud/dropbox/curlrequest.cpp new file mode 100644 index 0000000000..216b56c19e --- /dev/null +++ b/backends/cloud/dropbox/curlrequest.cpp @@ -0,0 +1,82 @@ +/* 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. +* +*/ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/dropbox/curlrequest.h" +#include "common/debug.h" +#include + +namespace Cloud { +namespace Dropbox { + +static size_t curlDataCallback(char *d, size_t n, size_t l, void *p) { + debug("%p got %d more bytes", p, n * l); + return n * l; +} + +CurlRequest::CurlRequest(Callback cb, char *url) : Request(cb), _firstTime(true) { + _curlm = curl_multi_init(); + _url = url; +} + +CurlRequest::~CurlRequest() { + curl_multi_cleanup(_curlm); +} + +bool CurlRequest::handle() { + if (_firstTime) { + CURL *eh = curl_easy_init(); + curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, curlDataCallback); + curl_easy_setopt(eh, CURLOPT_WRITEDATA, this); + curl_easy_setopt(eh, CURLOPT_HEADER, 0L); + curl_easy_setopt(eh, CURLOPT_URL, _url); + curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L); + curl_multi_add_handle(_curlm, eh); + + _firstTime = false; + } + + int U; + curl_multi_perform(_curlm, &U); + + int Q; + CURLMsg *_curlMsg; + while ((_curlMsg = curl_multi_info_read(_curlm, &Q))) { + if (_curlMsg->msg == CURLMSG_DONE) { + CURL *e = _curlMsg->easy_handle; + debug("R: %d - %s\n", _curlMsg->data.result, curl_easy_strerror(_curlMsg->data.result)); + curl_multi_remove_handle(_curlm, e); + curl_easy_cleanup(e); + + _callback(0); + return true; + } else { + debug("E: CURLMsg (%d)\n", _curlMsg->msg); + } + } + + return false; +} + +} //end of namespace Dropbox +} //end of namespace Cloud diff --git a/backends/cloud/dropbox/curlrequest.h b/backends/cloud/dropbox/curlrequest.h new file mode 100644 index 0000000000..8453fbb90a --- /dev/null +++ b/backends/cloud/dropbox/curlrequest.h @@ -0,0 +1,48 @@ +/* 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_CURLREQUEST_H +#define BACKENDS_CLOUD_DROPBOX_CURLREQUEST_H + +#include "backends/cloud/request.h" + +typedef void CURLM; + +namespace Cloud { +namespace Dropbox { + +class CurlRequest : public Cloud::Request { + bool _firstTime; + CURLM *_curlm; + char *_url; + +public: + CurlRequest(Callback cb, char *url); + virtual ~CurlRequest(); + + virtual bool handle(); +}; + +} //end of namespace Dropbox +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 8a0772dc3f..142a059457 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -19,18 +19,26 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ +#define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/dropbox/dropboxstorage.h" -#include "backends/cloud/dropbox/finalcountdownrequest.h" +#include "backends/cloud/dropbox/curlrequest.h" #include "common/debug.h" +#include namespace Cloud { namespace Dropbox { -static void finalCountdownCallback(void *ptr) { - warning("ladies and gentlemen, this is your callback speaking"); - warning("the returned pointer is %d", ptr); - warning("thank you for your attention"); +static void curlCallback(void *ptr) { + debug("--- curl request is complete ---"); +} + +DropboxStorage::DropboxStorage() { + curl_global_init(CURL_GLOBAL_ALL); +} + +DropboxStorage::~DropboxStorage() { + curl_global_cleanup(); } void DropboxStorage::listDirectory(Common::String path) { @@ -38,7 +46,8 @@ void DropboxStorage::listDirectory(Common::String path) { } void DropboxStorage::syncSaves() { - addRequest(new FinalCountdownRequest(finalCountdownCallback)); + addRequest(new CurlRequest(curlCallback, "tkachov.ru")); + addRequest(new CurlRequest(curlCallback, "bash.im")); } } //end of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index f80854b987..a0229438be 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -29,7 +29,8 @@ namespace Cloud { namespace Dropbox { class DropboxStorage: public Cloud::Storage { public: - DropboxStorage() {}; + DropboxStorage(); + virtual ~DropboxStorage(); virtual void listDirectory(Common::String path); virtual void syncSaves(); diff --git a/backends/cloud/dropbox/finalcountdownrequest.h b/backends/cloud/dropbox/finalcountdownrequest.h deleted file mode 100644 index 5ef942180c..0000000000 --- a/backends/cloud/dropbox/finalcountdownrequest.h +++ /dev/null @@ -1,52 +0,0 @@ -/* 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_FINALCOUNTDOWNREQUEST_H -#define BACKENDS_CLOUD_DROPBOX_FINALCOUNTDOWNREQUEST_H - -#include "backends/cloud/request.h" - -namespace Cloud { -namespace Dropbox { - -class FinalCountdownRequest : public Cloud::Request { - int _times; - -public: - FinalCountdownRequest(Callback cb) : Request(cb), _times(5) {}; - - virtual bool handle() { - if (--_times == 0) { - warning("It's the final countdown!"); - _callback(0); //meh, don't have anything for you, my caller - return true; - } - - warning("%d...", _times); - return false; - } -}; - -} -} //end of namespace Cloud::Dropbox - -#endif diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 23dcd8c379..0c5f6a39e7 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -42,7 +42,10 @@ void Storage::handler() { //TODO: lock mutex here (in case another handler() would be called before this one ends) warning("handler's here"); for (Common::Array::iterator i = _requests.begin(); i != _requests.end();) { - if ((*i)->handle()) _requests.erase(i); + if ((*i)->handle()) { + delete (*i); + _requests.erase(i); + } else ++i; } if (_requests.empty()) stopTimer(); -- cgit v1.2.3 From 01abba4f1dc9febbe99a4af6af19eb2afa3f618a Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 15 May 2016 11:22:35 +0600 Subject: CLOUD: Add ConnectionManager and NetworkReadStream NetworkReadStream actually saves whole response in the memory now. There is a pause mechanism in libcurl, but if libcurl is requesting something compressed, it would have to uncompress data as it goes even if we paused the request. Even though our own stream won't be notified about this data when when "pause" the request, libcurl's own buffer wound be expanding. --- backends/cloud/curl/connectionmanager.cpp | 72 +++++++++++++++++++++++++++ backends/cloud/curl/connectionmanager.h | 47 +++++++++++++++++ backends/cloud/curl/networkreadstream.cpp | 83 +++++++++++++++++++++++++++++++ backends/cloud/curl/networkreadstream.h | 76 ++++++++++++++++++++++++++++ backends/cloud/dropbox/curlrequest.cpp | 42 +++++----------- backends/cloud/dropbox/curlrequest.h | 13 ++--- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- backends/cloud/request.h | 4 +- backends/cloud/storage.cpp | 7 ++- backends/cloud/storage.h | 2 + 10 files changed, 308 insertions(+), 40 deletions(-) create mode 100644 backends/cloud/curl/connectionmanager.cpp create mode 100644 backends/cloud/curl/connectionmanager.h create mode 100644 backends/cloud/curl/networkreadstream.cpp create mode 100644 backends/cloud/curl/networkreadstream.h (limited to 'backends/cloud') diff --git a/backends/cloud/curl/connectionmanager.cpp b/backends/cloud/curl/connectionmanager.cpp new file mode 100644 index 0000000000..d0a0ad8b5c --- /dev/null +++ b/backends/cloud/curl/connectionmanager.cpp @@ -0,0 +1,72 @@ +/* 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. +* +*/ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/curl/connectionmanager.h" +#include "backends/cloud/curl/networkreadstream.h" +#include "common/debug.h" +#include + +namespace Cloud { + +ConnectionManager::ConnectionManager(): _multi(0) { + curl_global_init(CURL_GLOBAL_ALL); + _multi = curl_multi_init(); +} + +ConnectionManager::~ConnectionManager() { + curl_multi_cleanup(_multi); + curl_global_cleanup(); +} + +NetworkReadStream *ConnectionManager::makeRequest(const char *url) { + NetworkReadStream *stream = new NetworkReadStream(url); + curl_multi_add_handle(_multi, stream->getEasyHandle()); + return stream; +} + +void ConnectionManager::handle() { + int U; + curl_multi_perform(_multi, &U); + + int Q; + CURLMsg *curlMsg; + while ((curlMsg = curl_multi_info_read(_multi, &Q))) { + if (curlMsg->msg == CURLMSG_DONE) { + CURL *e = curlMsg->easy_handle; + + NetworkReadStream *stream; + curl_easy_getinfo(e, CURLINFO_PRIVATE, &stream); + if (stream) stream->done(); + + debug("ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result)); + curl_multi_remove_handle(_multi, e); + } + else { + debug("ConnectionManager: FAILURE (CURLMsg (%d))", curlMsg->msg); + //TODO: notify stream on this case also + } + } +} + +} //end of namespace Cloud diff --git a/backends/cloud/curl/connectionmanager.h b/backends/cloud/curl/connectionmanager.h new file mode 100644 index 0000000000..0ea27201f2 --- /dev/null +++ b/backends/cloud/curl/connectionmanager.h @@ -0,0 +1,47 @@ +/* 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_CURL_CONNECTIONMANAGER_H +#define BACKENDS_CLOUD_CURL_CONNECTIONMANAGER_H + +#include "common/str.h" + +typedef void CURLM; + +namespace Cloud { + +class NetworkReadStream; + +class ConnectionManager { + CURLM *_multi; + +public: + ConnectionManager(); + virtual ~ConnectionManager(); + + NetworkReadStream *makeRequest(const char *url); + void handle(); +}; + +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/curl/networkreadstream.cpp b/backends/cloud/curl/networkreadstream.cpp new file mode 100644 index 0000000000..8adac67569 --- /dev/null +++ b/backends/cloud/curl/networkreadstream.cpp @@ -0,0 +1,83 @@ +/* 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. +* +*/ + +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/curl/networkreadstream.h" +#include "common/debug.h" +#include + +namespace Cloud { + +static size_t curlDataCallback(char *d, size_t n, size_t l, void *p) { + NetworkReadStream *stream = (NetworkReadStream *)p; + if (stream) return stream->dataCallback(d, n, l); + return 0; +} + +NetworkReadStream::NetworkReadStream(const char *url): _easy(0), _eos(false), _requestComplete(false) { + _easy = curl_easy_init(); + curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback); + curl_easy_setopt(_easy, CURLOPT_WRITEDATA, this); //so callback can call us + curl_easy_setopt(_easy, CURLOPT_PRIVATE, this); //so ConnectionManager can call us when request is complete + curl_easy_setopt(_easy, CURLOPT_HEADER, 0L); + curl_easy_setopt(_easy, CURLOPT_URL, url); + curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L); +} + +NetworkReadStream::~NetworkReadStream() { + curl_easy_cleanup(_easy); +} + +bool NetworkReadStream::eos() const { + return _eos; +} + +uint32 NetworkReadStream::read(void *dataPtr, uint32 dataSize) { + uint32 available = _bytes.size(); + + if (available == 0) { + if (_requestComplete) _eos = true; + return 0; + } + + char *data = (char *)dataPtr; + uint32 actuallyRead = (dataSize < available ? dataSize : available); + for (uint32 i = 0; i < actuallyRead; ++i) data[i] = _bytes[i]; + data[actuallyRead] = 0; + _bytes.erase(0, actuallyRead); + return actuallyRead; +} + +void NetworkReadStream::done() { + _requestComplete = true; +} + +size_t NetworkReadStream::dataCallback(char *d, size_t n, size_t l) { + //TODO: return CURL_WRITEFUNC_PAUSE if _bytes is too long + //TODO: remember https://curl.haxx.se/libcurl/c/curl_easy_pause.html (Memory Use / compressed data case) + //TODO: if using pause, don't forget to unpause it somehow from read() up there + _bytes += Common::String(d, n*l); + return n*l; +} + +} //end of namespace Cloud diff --git a/backends/cloud/curl/networkreadstream.h b/backends/cloud/curl/networkreadstream.h new file mode 100644 index 0000000000..e469784e28 --- /dev/null +++ b/backends/cloud/curl/networkreadstream.h @@ -0,0 +1,76 @@ +/* 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_CURL_NETWORKREADSTREAM_H +#define BACKENDS_CLOUD_CURL_NETWORKREADSTREAM_H + +#include "common/stream.h" +#include "common/str.h" + +typedef void CURL; + +namespace Cloud { + +class NetworkReadStream: public Common::ReadStream { + CURL *_easy; + bool _eos, _requestComplete; + Common::String _bytes; + +public: + NetworkReadStream(const char *url); + virtual ~NetworkReadStream(); + + CURL *getEasyHandle() const { return _easy; } + + /** + * Returns true if a read failed because the stream end has been reached. + * This flag is cleared by clearErr(). + * For a SeekableReadStream, it is also cleared by a successful seek. + * + * @note The semantics of any implementation of this method are + * supposed to match those of ISO C feof(). In particular, in a stream + * with N bytes, reading exactly N bytes from the start should *not* + * set eos; only reading *beyond* the available data should set it. + */ + virtual bool eos() const; + + /** + * Read data from the stream. Subclasses must implement this + * method; all other read methods are implemented using it. + * + * @note The semantics of any implementation of this method are + * supposed to match those of ISO C fread(), in particular where + * it concerns setting error and end of file/stream flags. + * + * @param dataPtr pointer to a buffer into which the data is read + * @param dataSize number of bytes to be read + * @return the number of bytes which were actually read. + */ + virtual uint32 read(void *dataPtr, uint32 dataSize); + + void done(); + size_t dataCallback(char *d, size_t n, size_t l); +}; + +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/dropbox/curlrequest.cpp b/backends/cloud/dropbox/curlrequest.cpp index 216b56c19e..1dfdd9e25f 100644 --- a/backends/cloud/dropbox/curlrequest.cpp +++ b/backends/cloud/dropbox/curlrequest.cpp @@ -23,55 +23,37 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/dropbox/curlrequest.h" +#include "backends/cloud/curl/networkreadstream.h" #include "common/debug.h" #include namespace Cloud { namespace Dropbox { -static size_t curlDataCallback(char *d, size_t n, size_t l, void *p) { - debug("%p got %d more bytes", p, n * l); - return n * l; -} - -CurlRequest::CurlRequest(Callback cb, char *url) : Request(cb), _firstTime(true) { - _curlm = curl_multi_init(); +CurlRequest::CurlRequest(Callback cb, const char *url) : Request(cb), _firstTime(true), _stream(0) { _url = url; } CurlRequest::~CurlRequest() { - curl_multi_cleanup(_curlm); + if (_stream) delete _stream; } -bool CurlRequest::handle() { +bool CurlRequest::handle(ConnectionManager& manager) { if (_firstTime) { - CURL *eh = curl_easy_init(); - curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, curlDataCallback); - curl_easy_setopt(eh, CURLOPT_WRITEDATA, this); - curl_easy_setopt(eh, CURLOPT_HEADER, 0L); - curl_easy_setopt(eh, CURLOPT_URL, _url); - curl_easy_setopt(eh, CURLOPT_VERBOSE, 0L); - curl_multi_add_handle(_curlm, eh); - + _stream = manager.makeRequest(_url); _firstTime = false; } - int U; - curl_multi_perform(_curlm, &U); - - int Q; - CURLMsg *_curlMsg; - while ((_curlMsg = curl_multi_info_read(_curlm, &Q))) { - if (_curlMsg->msg == CURLMSG_DONE) { - CURL *e = _curlMsg->easy_handle; - debug("R: %d - %s\n", _curlMsg->data.result, curl_easy_strerror(_curlMsg->data.result)); - curl_multi_remove_handle(_curlm, e); - curl_easy_cleanup(e); + if (_stream) { + const int kBufSize = 10000; + char buf[kBufSize+1]; + uint32 readBytes = _stream->read(buf, kBufSize); + debug("%d", readBytes); + //if(readBytes != 0) debug("%s", buf); + if(_stream->eos()) { _callback(0); return true; - } else { - debug("E: CURLMsg (%d)\n", _curlMsg->msg); } } diff --git a/backends/cloud/dropbox/curlrequest.h b/backends/cloud/dropbox/curlrequest.h index 8453fbb90a..2c8ab6b8f8 100644 --- a/backends/cloud/dropbox/curlrequest.h +++ b/backends/cloud/dropbox/curlrequest.h @@ -25,21 +25,22 @@ #include "backends/cloud/request.h" -typedef void CURLM; - namespace Cloud { + +class NetworkReadStream; + namespace Dropbox { class CurlRequest : public Cloud::Request { bool _firstTime; - CURLM *_curlm; - char *_url; + const char *_url; + NetworkReadStream *_stream; public: - CurlRequest(Callback cb, char *url); + CurlRequest(Callback cb, const char *url); virtual ~CurlRequest(); - virtual bool handle(); + virtual bool handle(ConnectionManager& manager); }; } //end of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 142a059457..9298cde0a1 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -47,7 +47,7 @@ void DropboxStorage::listDirectory(Common::String path) { void DropboxStorage::syncSaves() { addRequest(new CurlRequest(curlCallback, "tkachov.ru")); - addRequest(new CurlRequest(curlCallback, "bash.im")); + addRequest(new CurlRequest(curlCallback, "scummvm.org")); } } //end of namespace Dropbox diff --git a/backends/cloud/request.h b/backends/cloud/request.h index ae85c234f2..b4f5ccab0b 100644 --- a/backends/cloud/request.h +++ b/backends/cloud/request.h @@ -23,6 +23,8 @@ #ifndef BACKENDS_CLOUD_REQUEST_H #define BACKENDS_CLOUD_REQUEST_H +#include "backends/cloud/curl/connectionmanager.h" + namespace Cloud { class Request { @@ -45,7 +47,7 @@ public: * @return true if request's work is complete and it may be removed from Storage's list */ - virtual bool handle() = 0; + virtual bool handle(ConnectionManager& manager) = 0; }; } //end of namespace Cloud diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 0c5f6a39e7..d7217a57cd 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -21,6 +21,7 @@ */ #include "backends/cloud/storage.h" +#include "common/debug.h" #include "common/system.h" #include "common/timer.h" @@ -40,15 +41,17 @@ void Storage::addRequest(Request *request) { void Storage::handler() { //TODO: lock mutex here (in case another handler() would be called before this one ends) - warning("handler's here"); + debug("\nhandler's here"); for (Common::Array::iterator i = _requests.begin(); i != _requests.end();) { - if ((*i)->handle()) { + if ((*i)->handle(_connectionManager)) { delete (*i); _requests.erase(i); } else ++i; } if (_requests.empty()) stopTimer(); + + _connectionManager.handle(); //TODO: unlock mutex here } diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index dcaa6af213..0949ff8505 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -26,6 +26,7 @@ #include "common/str.h" #include "common/array.h" #include "backends/cloud/request.h" +#include "backends/cloud/curl/connectionmanager.h" namespace Cloud { @@ -35,6 +36,7 @@ class Storage { protected: Common::Array _requests; + ConnectionManager _connectionManager; virtual void addRequest(Request *request); //starts the timer if it's not started virtual void handler(); -- cgit v1.2.3 From 9c22b7cc64a3bd074f7cec012bd2f29f210d4ccf Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 16 May 2016 01:05:40 +0600 Subject: CLOUD: Rewrite NetworkReadStream Now it is based on MemoryReadWriteStream, which is introduced by this commit. This stream is using ring buffer and is dynamically increasing its size when necessary. --- backends/cloud/curl/connectionmanager.cpp | 72 --------------------------- backends/cloud/curl/connectionmanager.h | 47 ----------------- backends/cloud/curl/networkreadstream.cpp | 83 ------------------------------- backends/cloud/curl/networkreadstream.h | 76 ---------------------------- backends/cloud/dropbox/curlrequest.cpp | 4 +- backends/cloud/dropbox/curlrequest.h | 9 ++-- backends/cloud/request.h | 4 +- backends/cloud/storage.h | 4 +- 8 files changed, 11 insertions(+), 288 deletions(-) delete mode 100644 backends/cloud/curl/connectionmanager.cpp delete mode 100644 backends/cloud/curl/connectionmanager.h delete mode 100644 backends/cloud/curl/networkreadstream.cpp delete mode 100644 backends/cloud/curl/networkreadstream.h (limited to 'backends/cloud') diff --git a/backends/cloud/curl/connectionmanager.cpp b/backends/cloud/curl/connectionmanager.cpp deleted file mode 100644 index d0a0ad8b5c..0000000000 --- a/backends/cloud/curl/connectionmanager.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* 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. -* -*/ - -#define FORBIDDEN_SYMBOL_ALLOW_ALL - -#include "backends/cloud/curl/connectionmanager.h" -#include "backends/cloud/curl/networkreadstream.h" -#include "common/debug.h" -#include - -namespace Cloud { - -ConnectionManager::ConnectionManager(): _multi(0) { - curl_global_init(CURL_GLOBAL_ALL); - _multi = curl_multi_init(); -} - -ConnectionManager::~ConnectionManager() { - curl_multi_cleanup(_multi); - curl_global_cleanup(); -} - -NetworkReadStream *ConnectionManager::makeRequest(const char *url) { - NetworkReadStream *stream = new NetworkReadStream(url); - curl_multi_add_handle(_multi, stream->getEasyHandle()); - return stream; -} - -void ConnectionManager::handle() { - int U; - curl_multi_perform(_multi, &U); - - int Q; - CURLMsg *curlMsg; - while ((curlMsg = curl_multi_info_read(_multi, &Q))) { - if (curlMsg->msg == CURLMSG_DONE) { - CURL *e = curlMsg->easy_handle; - - NetworkReadStream *stream; - curl_easy_getinfo(e, CURLINFO_PRIVATE, &stream); - if (stream) stream->done(); - - debug("ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result)); - curl_multi_remove_handle(_multi, e); - } - else { - debug("ConnectionManager: FAILURE (CURLMsg (%d))", curlMsg->msg); - //TODO: notify stream on this case also - } - } -} - -} //end of namespace Cloud diff --git a/backends/cloud/curl/connectionmanager.h b/backends/cloud/curl/connectionmanager.h deleted file mode 100644 index 0ea27201f2..0000000000 --- a/backends/cloud/curl/connectionmanager.h +++ /dev/null @@ -1,47 +0,0 @@ -/* 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_CURL_CONNECTIONMANAGER_H -#define BACKENDS_CLOUD_CURL_CONNECTIONMANAGER_H - -#include "common/str.h" - -typedef void CURLM; - -namespace Cloud { - -class NetworkReadStream; - -class ConnectionManager { - CURLM *_multi; - -public: - ConnectionManager(); - virtual ~ConnectionManager(); - - NetworkReadStream *makeRequest(const char *url); - void handle(); -}; - -} //end of namespace Cloud - -#endif diff --git a/backends/cloud/curl/networkreadstream.cpp b/backends/cloud/curl/networkreadstream.cpp deleted file mode 100644 index 8adac67569..0000000000 --- a/backends/cloud/curl/networkreadstream.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* 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. -* -*/ - -#define FORBIDDEN_SYMBOL_ALLOW_ALL - -#include "backends/cloud/curl/networkreadstream.h" -#include "common/debug.h" -#include - -namespace Cloud { - -static size_t curlDataCallback(char *d, size_t n, size_t l, void *p) { - NetworkReadStream *stream = (NetworkReadStream *)p; - if (stream) return stream->dataCallback(d, n, l); - return 0; -} - -NetworkReadStream::NetworkReadStream(const char *url): _easy(0), _eos(false), _requestComplete(false) { - _easy = curl_easy_init(); - curl_easy_setopt(_easy, CURLOPT_WRITEFUNCTION, curlDataCallback); - curl_easy_setopt(_easy, CURLOPT_WRITEDATA, this); //so callback can call us - curl_easy_setopt(_easy, CURLOPT_PRIVATE, this); //so ConnectionManager can call us when request is complete - curl_easy_setopt(_easy, CURLOPT_HEADER, 0L); - curl_easy_setopt(_easy, CURLOPT_URL, url); - curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L); -} - -NetworkReadStream::~NetworkReadStream() { - curl_easy_cleanup(_easy); -} - -bool NetworkReadStream::eos() const { - return _eos; -} - -uint32 NetworkReadStream::read(void *dataPtr, uint32 dataSize) { - uint32 available = _bytes.size(); - - if (available == 0) { - if (_requestComplete) _eos = true; - return 0; - } - - char *data = (char *)dataPtr; - uint32 actuallyRead = (dataSize < available ? dataSize : available); - for (uint32 i = 0; i < actuallyRead; ++i) data[i] = _bytes[i]; - data[actuallyRead] = 0; - _bytes.erase(0, actuallyRead); - return actuallyRead; -} - -void NetworkReadStream::done() { - _requestComplete = true; -} - -size_t NetworkReadStream::dataCallback(char *d, size_t n, size_t l) { - //TODO: return CURL_WRITEFUNC_PAUSE if _bytes is too long - //TODO: remember https://curl.haxx.se/libcurl/c/curl_easy_pause.html (Memory Use / compressed data case) - //TODO: if using pause, don't forget to unpause it somehow from read() up there - _bytes += Common::String(d, n*l); - return n*l; -} - -} //end of namespace Cloud diff --git a/backends/cloud/curl/networkreadstream.h b/backends/cloud/curl/networkreadstream.h deleted file mode 100644 index e469784e28..0000000000 --- a/backends/cloud/curl/networkreadstream.h +++ /dev/null @@ -1,76 +0,0 @@ -/* 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_CURL_NETWORKREADSTREAM_H -#define BACKENDS_CLOUD_CURL_NETWORKREADSTREAM_H - -#include "common/stream.h" -#include "common/str.h" - -typedef void CURL; - -namespace Cloud { - -class NetworkReadStream: public Common::ReadStream { - CURL *_easy; - bool _eos, _requestComplete; - Common::String _bytes; - -public: - NetworkReadStream(const char *url); - virtual ~NetworkReadStream(); - - CURL *getEasyHandle() const { return _easy; } - - /** - * Returns true if a read failed because the stream end has been reached. - * This flag is cleared by clearErr(). - * For a SeekableReadStream, it is also cleared by a successful seek. - * - * @note The semantics of any implementation of this method are - * supposed to match those of ISO C feof(). In particular, in a stream - * with N bytes, reading exactly N bytes from the start should *not* - * set eos; only reading *beyond* the available data should set it. - */ - virtual bool eos() const; - - /** - * Read data from the stream. Subclasses must implement this - * method; all other read methods are implemented using it. - * - * @note The semantics of any implementation of this method are - * supposed to match those of ISO C fread(), in particular where - * it concerns setting error and end of file/stream flags. - * - * @param dataPtr pointer to a buffer into which the data is read - * @param dataSize number of bytes to be read - * @return the number of bytes which were actually read. - */ - virtual uint32 read(void *dataPtr, uint32 dataSize); - - void done(); - size_t dataCallback(char *d, size_t n, size_t l); -}; - -} //end of namespace Cloud - -#endif diff --git a/backends/cloud/dropbox/curlrequest.cpp b/backends/cloud/dropbox/curlrequest.cpp index 1dfdd9e25f..ecc868cb51 100644 --- a/backends/cloud/dropbox/curlrequest.cpp +++ b/backends/cloud/dropbox/curlrequest.cpp @@ -23,7 +23,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/dropbox/curlrequest.h" -#include "backends/cloud/curl/networkreadstream.h" +#include "backends/networking/curl/networkreadstream.h" #include "common/debug.h" #include @@ -38,7 +38,7 @@ CurlRequest::~CurlRequest() { if (_stream) delete _stream; } -bool CurlRequest::handle(ConnectionManager& manager) { +bool CurlRequest::handle(Networking::ConnectionManager &manager) { if (_firstTime) { _stream = manager.makeRequest(_url); _firstTime = false; diff --git a/backends/cloud/dropbox/curlrequest.h b/backends/cloud/dropbox/curlrequest.h index 2c8ab6b8f8..3d5d4adb72 100644 --- a/backends/cloud/dropbox/curlrequest.h +++ b/backends/cloud/dropbox/curlrequest.h @@ -25,22 +25,23 @@ #include "backends/cloud/request.h" -namespace Cloud { - +namespace Networking { class NetworkReadStream; +} +namespace Cloud { namespace Dropbox { class CurlRequest : public Cloud::Request { bool _firstTime; const char *_url; - NetworkReadStream *_stream; + Networking::NetworkReadStream *_stream; public: CurlRequest(Callback cb, const char *url); virtual ~CurlRequest(); - virtual bool handle(ConnectionManager& manager); + virtual bool handle(Networking::ConnectionManager &manager); }; } //end of namespace Dropbox diff --git a/backends/cloud/request.h b/backends/cloud/request.h index b4f5ccab0b..d85a68d570 100644 --- a/backends/cloud/request.h +++ b/backends/cloud/request.h @@ -23,7 +23,7 @@ #ifndef BACKENDS_CLOUD_REQUEST_H #define BACKENDS_CLOUD_REQUEST_H -#include "backends/cloud/curl/connectionmanager.h" +#include "backends/networking/curl/connectionmanager.h" namespace Cloud { @@ -47,7 +47,7 @@ public: * @return true if request's work is complete and it may be removed from Storage's list */ - virtual bool handle(ConnectionManager& manager) = 0; + virtual bool handle(Networking::ConnectionManager &manager) = 0; }; } //end of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 0949ff8505..84b6157a22 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -26,7 +26,7 @@ #include "common/str.h" #include "common/array.h" #include "backends/cloud/request.h" -#include "backends/cloud/curl/connectionmanager.h" +#include "backends/networking/curl/connectionmanager.h" namespace Cloud { @@ -36,7 +36,7 @@ class Storage { protected: Common::Array _requests; - ConnectionManager _connectionManager; + Networking::ConnectionManager _connectionManager; virtual void addRequest(Request *request); //starts the timer if it's not started virtual void handler(); -- cgit v1.2.3 From 03217cd5c3de3c17739a246f5967dfd4a14eb120 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 17 May 2016 01:19:49 +0600 Subject: CLOUD: Add CurlJsonRequest Now we can do REST API request by creating CurlJsonRequest and waiting for it to call our callback. Passed pointer is Common::JSONValue. This commit also does some minor variable renaming fixes. --- backends/cloud/dropbox/curlrequest.cpp | 64 ------------------------------- backends/cloud/dropbox/curlrequest.h | 50 ------------------------ backends/cloud/dropbox/dropboxstorage.cpp | 20 +++++++--- 3 files changed, 14 insertions(+), 120 deletions(-) delete mode 100644 backends/cloud/dropbox/curlrequest.cpp delete mode 100644 backends/cloud/dropbox/curlrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/curlrequest.cpp b/backends/cloud/dropbox/curlrequest.cpp deleted file mode 100644 index ecc868cb51..0000000000 --- a/backends/cloud/dropbox/curlrequest.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* 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. -* -*/ - -#define FORBIDDEN_SYMBOL_ALLOW_ALL - -#include "backends/cloud/dropbox/curlrequest.h" -#include "backends/networking/curl/networkreadstream.h" -#include "common/debug.h" -#include - -namespace Cloud { -namespace Dropbox { - -CurlRequest::CurlRequest(Callback cb, const char *url) : Request(cb), _firstTime(true), _stream(0) { - _url = url; -} - -CurlRequest::~CurlRequest() { - if (_stream) delete _stream; -} - -bool CurlRequest::handle(Networking::ConnectionManager &manager) { - if (_firstTime) { - _stream = manager.makeRequest(_url); - _firstTime = false; - } - - if (_stream) { - const int kBufSize = 10000; - char buf[kBufSize+1]; - uint32 readBytes = _stream->read(buf, kBufSize); - debug("%d", readBytes); - //if(readBytes != 0) debug("%s", buf); - - if(_stream->eos()) { - _callback(0); - return true; - } - } - - return false; -} - -} //end of namespace Dropbox -} //end of namespace Cloud diff --git a/backends/cloud/dropbox/curlrequest.h b/backends/cloud/dropbox/curlrequest.h deleted file mode 100644 index 3d5d4adb72..0000000000 --- a/backends/cloud/dropbox/curlrequest.h +++ /dev/null @@ -1,50 +0,0 @@ -/* 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_CURLREQUEST_H -#define BACKENDS_CLOUD_DROPBOX_CURLREQUEST_H - -#include "backends/cloud/request.h" - -namespace Networking { -class NetworkReadStream; -} - -namespace Cloud { -namespace Dropbox { - -class CurlRequest : public Cloud::Request { - bool _firstTime; - const char *_url; - Networking::NetworkReadStream *_stream; - -public: - CurlRequest(Callback cb, const char *url); - virtual ~CurlRequest(); - - virtual bool handle(Networking::ConnectionManager &manager); -}; - -} //end of namespace Dropbox -} //end of namespace Cloud - -#endif diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 9298cde0a1..2db915de38 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -22,15 +22,23 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/dropbox/dropboxstorage.h" -#include "backends/cloud/dropbox/curlrequest.h" +#include "backends/networking/curl/curljsonrequest.h" #include "common/debug.h" +#include "common/json.h" #include namespace Cloud { namespace Dropbox { -static void curlCallback(void *ptr) { - debug("--- curl request is complete ---"); +static void curlJsonCallback(void *ptr) { + Common::JSONValue *json = (Common::JSONValue *)ptr; + if (json) { + debug("curlJsonCallback:"); + debug("%s", json->stringify(true).c_str()); + delete json; + } else { + debug("curlJsonCallback: got NULL instead of JSON!"); + } } DropboxStorage::DropboxStorage() { @@ -45,9 +53,9 @@ void DropboxStorage::listDirectory(Common::String path) { startTimer(1000000); //in one second } -void DropboxStorage::syncSaves() { - addRequest(new CurlRequest(curlCallback, "tkachov.ru")); - addRequest(new CurlRequest(curlCallback, "scummvm.org")); +void DropboxStorage::syncSaves() { + //not so Dropbox, just testing JSON requesting & parsing: + addRequest(new Networking::CurlJsonRequest(curlJsonCallback, "https://api.vk.com/method/users.get?v=5.50&user_ids=205387401")); } } //end of namespace Dropbox -- cgit v1.2.3 From 5df8c5140292520bafe92efa94935a776d63d108 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 17 May 2016 20:17:41 +0600 Subject: CLOUD: Fix CurlJsonRequest It's using MemoryWriteStreamDynamic instead of String and it prepares raw byte contents of this stream for JSON::parse(). --- backends/cloud/dropbox/dropboxstorage.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 2db915de38..729283bcfa 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -56,6 +56,7 @@ void DropboxStorage::listDirectory(Common::String path) { void DropboxStorage::syncSaves() { //not so Dropbox, just testing JSON requesting & parsing: addRequest(new Networking::CurlJsonRequest(curlJsonCallback, "https://api.vk.com/method/users.get?v=5.50&user_ids=205387401")); + addRequest(new Networking::CurlJsonRequest(curlJsonCallback, "https://api.vk.com/method/users.get?v=5.50&user_ids=28870501")); } } //end of namespace Dropbox -- cgit v1.2.3 From e743a65636a674def45e955cb7a5632aead2a033 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 18 May 2016 14:08:05 +0600 Subject: CLOUD: Add Dropbox into CloudManager's configs This commit adds: * ConfMan's new "cloud" domain; * CloudManager's init() method, where it loads keys from "cloud" configs domain; * CurlJsonRequest's addHeader() and addPostField() methods; * temporary Storage's printInfo() method; * DropboxStorage's implementation of printInfo(), which is using access token and user id; * DropboxStorage's loadFromConfig() static method to load access token and user id from configs and create a Storage instance with those; * temporary DropboxStorage's authThroughConsole() static method, which guides user through auth process from the console. So, in CloudManager's init() implementation ScummVM checks that there is "current_storage_type" key in "cloud" domain of configs, and loads corresponding storage if there is such key. If there is no such key, ScummVM offers user to auth with Dropbox. That's done through console, and thus it's temporary (it also requires restarting ScummVM twice and manually editing config.ini file). --- backends/cloud/dropbox/dropboxstorage.cpp | 110 ++++++++++++++++++++++++++++-- backends/cloud/dropbox/dropboxstorage.h | 39 +++++++++-- backends/cloud/manager.cpp | 15 +++- backends/cloud/manager.h | 2 + backends/cloud/storage.h | 6 ++ 5 files changed, 159 insertions(+), 13 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 729283bcfa..add6bff54c 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -23,6 +23,7 @@ #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/networking/curl/curljsonrequest.h" +#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include @@ -30,18 +31,44 @@ namespace Cloud { namespace Dropbox { -static void curlJsonCallback(void *ptr) { +Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth +Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow + +static void printJsonCallback(void *ptr) { + Common::JSONValue *json = (Common::JSONValue *)ptr; + if (json) { + debug("printJsonCallback:"); + debug("%s", json->stringify(true).c_str()); + delete json; + } else { + debug("printJsonCallback: got NULL instead of JSON!"); + } +} + +static void saveAccessTokenCallback(void *ptr) { Common::JSONValue *json = (Common::JSONValue *)ptr; if (json) { - debug("curlJsonCallback:"); + debug("saveAccessTokenCallback:"); debug("%s", json->stringify(true).c_str()); + + Common::JSONObject result = json->asObject(); + if (!result.contains("access_token") || !result.contains("uid")) { + warning("Bad response, no token/uid passed"); + } else { + ConfMan.set("current_storage_type", "Dropbox", "cloud"); + ConfMan.set("current_storage_access_token", result.getVal("access_token")->asString(), "cloud"); + ConfMan.set("current_storage_user_id", result.getVal("uid")->asString(), "cloud"); + ConfMan.removeKey("dropbox_code", "cloud"); + debug("Now please restart ScummVM to apply the changes."); + } + delete json; } else { - debug("curlJsonCallback: got NULL instead of JSON!"); + debug("saveAccessTokenCallback: got NULL instead of JSON!"); } } -DropboxStorage::DropboxStorage() { +DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) { curl_global_init(CURL_GLOBAL_ALL); } @@ -54,9 +81,78 @@ void DropboxStorage::listDirectory(Common::String path) { } void DropboxStorage::syncSaves() { - //not so Dropbox, just testing JSON requesting & parsing: - addRequest(new Networking::CurlJsonRequest(curlJsonCallback, "https://api.vk.com/method/users.get?v=5.50&user_ids=205387401")); - addRequest(new Networking::CurlJsonRequest(curlJsonCallback, "https://api.vk.com/method/users.get?v=5.50&user_ids=28870501")); + //not syncing, but already something: + printInfo(); +} + +void DropboxStorage::printInfo() { + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(printJsonCallback, "https://api.dropboxapi.com/1/account/info"); + request->addHeader("Authorization: Bearer " + _token); + addRequest(request); +} + +DropboxStorage *DropboxStorage::loadFromConfig() { + KEY = ConfMan.get("DROPBOX_KEY", "cloud"); + SECRET = ConfMan.get("DROPBOX_SECRET", "cloud"); + + if (!ConfMan.hasKey("current_storage_access_token", "cloud")) { + warning("No access_token found"); + return 0; + } + + if (!ConfMan.hasKey("current_storage_user_id", "cloud")) { + warning("No user_id found"); + return 0; + } + + Common::String accessToken = ConfMan.get("current_storage_access_token", "cloud"); + Common::String userId = ConfMan.get("current_storage_user_id", "cloud"); + return new DropboxStorage(accessToken, userId); +} + +Common::String DropboxStorage::getAuthLink() { + Common::String url = "https://www.dropbox.com/1/oauth2/authorize"; + url += "?response_type=code"; + url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting + //url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening + url += "&client_id=" + KEY; + return url; +} + +DropboxStorage *DropboxStorage::authThroughConsole() { + if (!ConfMan.hasKey("DROPBOX_KEY", "cloud") || !ConfMan.hasKey("DROPBOX_SECRET", "cloud")) { + warning("No Dropbox keys available, cannot do auth"); + return 0; + } + + KEY = ConfMan.get("DROPBOX_KEY", "cloud"); + SECRET = ConfMan.get("DROPBOX_SECRET", "cloud"); + + if (ConfMan.hasKey("dropbox_code", "cloud")) { + //phase 2: get access_token using specified code + return getAccessToken(ConfMan.get("dropbox_code", "cloud")); + } + + debug("Navigate to this URL and press \"Allow\":"); + debug("%s\n", getAuthLink().c_str()); + debug("Then, add dropbox_code key in [cloud] section of configuration file. You should copy the value from URL and put it as value for that key.\n"); + debug("Navigate to this URL to get more information on ScummVM's configuration files:"); + debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); + return 0; +} + +DropboxStorage *DropboxStorage::getAccessToken(Common::String code) { + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(saveAccessTokenCallback, "https://api.dropboxapi.com/1/oauth2/token"); + request->addPostField("code=" + code); + request->addPostField("grant_type=authorization_code"); + request->addPostField("client_id=" + KEY); + request->addPostField("client_secret=" + SECRET); + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); + + //OK, that's not how I imagined that... + DropboxStorage *storage = new DropboxStorage("", ""); + storage->addRequest(request); + return storage; } } //end of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index a0229438be..f2281f146f 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -24,18 +24,47 @@ #define BACKENDS_CLOUD_DROPBOX_STORAGE_H #include "backends/cloud/storage.h" +#include "../manager.h" -namespace Cloud { namespace Dropbox { +namespace Cloud { +namespace Dropbox { -class DropboxStorage: public Cloud::Storage { -public: - DropboxStorage(); +class DropboxStorage: public Cloud::Storage { + static Common::String KEY, SECRET; + + Common::String _token, _uid; + + /** This private constructor is called from loadFromConfig(). */ + DropboxStorage(Common::String token, Common::String uid); + + static DropboxStorage *getAccessToken(Common::String code); + +public: virtual ~DropboxStorage(); virtual void listDirectory(Common::String path); virtual void syncSaves(); + virtual void printInfo(); + /** + * Load token and user id from configs and return DropboxStorage for those. + * @return pointer to the newly created DropboxStorage or 0 if some problem occured. + */ + static DropboxStorage *loadFromConfig(); + + /** + * Returns Dropbox auth link. + */ + static Common::String DropboxStorage::getAuthLink(); + + /** + * Show message with Dropbox auth instructions. (Temporary) + * Returns temporary DropboxStorage, which does network requests + * to get access token. + */ + static DropboxStorage *authThroughConsole(); }; -} } //end of namespace Cloud::Dropbox +} //end of namespace Dropbox +} //end of namespace Cloud #endif diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 58bb0ce83f..08340e9288 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -22,13 +22,26 @@ #include "backends/cloud/manager.h" #include "backends/cloud/dropbox/dropboxstorage.h" +#include "common/config-manager.h" namespace Cloud { -Manager::Manager(): _currentStorage(new Dropbox::DropboxStorage()) {} +Manager::Manager(): _currentStorage(0) {} Manager::~Manager() { delete _currentStorage; } +void Manager::init() { + if (ConfMan.hasKey("current_storage_type", "cloud")) { + Common::String storageType = ConfMan.get("current_storage_type", "cloud"); + if (storageType == "Dropbox") _currentStorage = Dropbox::DropboxStorage::loadFromConfig(); + else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); + } + else { + //this is temporary console offer to auth with Dropbox (because there is no other storage type yet anyway) + Dropbox::DropboxStorage::authThroughConsole(); + } +} + Storage* Manager::getCurrentStorage() { return _currentStorage; } diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index 11cc595da4..a1f046d71d 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -35,6 +35,8 @@ public: Manager(); virtual ~Manager(); + virtual void init(); + virtual Storage* getCurrentStorage(); virtual void syncSaves(); }; diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 84b6157a22..a5d048d3af 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -63,6 +63,12 @@ public: */ virtual void syncSaves() = 0; + + /** + * Prints user info on console. (Temporary) + */ + + virtual void printInfo() = 0; }; } //end of namespace Cloud -- cgit v1.2.3 From 0a947618fb1faa023df03d355e9749905424dd58 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 18 May 2016 15:21:09 +0600 Subject: CLOUD: Make ConnectionManager singleton With ConnectionManager singleton one can start their Requests without creating Storage instance. Moreover, Storage instance should contain cloud API, not Requests-related handling and timer starting methods. Thus, these methods were moved into ConnectionManager itself. --- backends/cloud/dropbox/dropboxstorage.cpp | 26 +++++------ backends/cloud/dropbox/dropboxstorage.h | 8 ++-- backends/cloud/request.h | 55 ----------------------- backends/cloud/storage.cpp | 73 ------------------------------- backends/cloud/storage.h | 19 +------- 5 files changed, 16 insertions(+), 165 deletions(-) delete mode 100644 backends/cloud/request.h delete mode 100644 backends/cloud/storage.cpp (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index add6bff54c..93f0eebcf6 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -22,6 +22,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/dropbox/dropboxstorage.h" +#include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "common/config-manager.h" #include "common/debug.h" @@ -76,8 +77,7 @@ DropboxStorage::~DropboxStorage() { curl_global_cleanup(); } -void DropboxStorage::listDirectory(Common::String path) { - startTimer(1000000); //in one second +void DropboxStorage::listDirectory(Common::String path) { } void DropboxStorage::syncSaves() { @@ -88,7 +88,7 @@ void DropboxStorage::syncSaves() { void DropboxStorage::printInfo() { Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(printJsonCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); - addRequest(request); + ConnMan.addRequest(request); } DropboxStorage *DropboxStorage::loadFromConfig() { @@ -119,10 +119,10 @@ Common::String DropboxStorage::getAuthLink() { return url; } -DropboxStorage *DropboxStorage::authThroughConsole() { +void DropboxStorage::authThroughConsole() { if (!ConfMan.hasKey("DROPBOX_KEY", "cloud") || !ConfMan.hasKey("DROPBOX_SECRET", "cloud")) { warning("No Dropbox keys available, cannot do auth"); - return 0; + return; } KEY = ConfMan.get("DROPBOX_KEY", "cloud"); @@ -130,29 +130,25 @@ DropboxStorage *DropboxStorage::authThroughConsole() { if (ConfMan.hasKey("dropbox_code", "cloud")) { //phase 2: get access_token using specified code - return getAccessToken(ConfMan.get("dropbox_code", "cloud")); + getAccessToken(ConfMan.get("dropbox_code", "cloud")); + return; } debug("Navigate to this URL and press \"Allow\":"); debug("%s\n", getAuthLink().c_str()); debug("Then, add dropbox_code key in [cloud] section of configuration file. You should copy the value from URL and put it as value for that key.\n"); debug("Navigate to this URL to get more information on ScummVM's configuration files:"); - debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); - return 0; + debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); } -DropboxStorage *DropboxStorage::getAccessToken(Common::String code) { +void DropboxStorage::getAccessToken(Common::String code) { Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(saveAccessTokenCallback, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + KEY); request->addPostField("client_secret=" + SECRET); - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); - - //OK, that's not how I imagined that... - DropboxStorage *storage = new DropboxStorage("", ""); - storage->addRequest(request); - return storage; + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); + ConnMan.addRequest(request); } } //end of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index f2281f146f..0500db5d49 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -24,7 +24,7 @@ #define BACKENDS_CLOUD_DROPBOX_STORAGE_H #include "backends/cloud/storage.h" -#include "../manager.h" +#include "backends/cloud/manager.h" namespace Cloud { namespace Dropbox { @@ -37,7 +37,7 @@ class DropboxStorage: public Cloud::Storage { /** This private constructor is called from loadFromConfig(). */ DropboxStorage(Common::String token, Common::String uid); - static DropboxStorage *getAccessToken(Common::String code); + static void getAccessToken(Common::String code); public: virtual ~DropboxStorage(); @@ -58,10 +58,8 @@ public: /** * Show message with Dropbox auth instructions. (Temporary) - * Returns temporary DropboxStorage, which does network requests - * to get access token. */ - static DropboxStorage *authThroughConsole(); + static void authThroughConsole(); }; } //end of namespace Dropbox diff --git a/backends/cloud/request.h b/backends/cloud/request.h deleted file mode 100644 index d85a68d570..0000000000 --- a/backends/cloud/request.h +++ /dev/null @@ -1,55 +0,0 @@ -/* 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_REQUEST_H -#define BACKENDS_CLOUD_REQUEST_H - -#include "backends/networking/curl/connectionmanager.h" - -namespace Cloud { - -class Request { -protected: - /** - * Callback, which should be called before Request returns true in handle(). - * That's the way Requests pass the result to the code which asked to create this request. - */ - - typedef void(*Callback)(void *result); - Callback _callback; - -public: - Request(Callback cb): _callback(cb) {}; - virtual ~Request() {}; - - /** - * Method, which does actual work. Depends on what this Request is doing. - * - * @return true if request's work is complete and it may be removed from Storage's list - */ - - virtual bool handle(Networking::ConnectionManager &manager) = 0; -}; - -} //end of namespace Cloud - -#endif diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp deleted file mode 100644 index d7217a57cd..0000000000 --- a/backends/cloud/storage.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* 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/debug.h" -#include "common/system.h" -#include "common/timer.h" - -namespace Cloud { - -void cloudThread(void *thread) { - Storage *cloudThread = (Storage *)thread; - cloudThread->handler(); -} - -Storage::Storage() : _timerStarted(false) {} - -void Storage::addRequest(Request *request) { - _requests.push_back(request); - if (!_timerStarted) startTimer(); -} - -void Storage::handler() { - //TODO: lock mutex here (in case another handler() would be called before this one ends) - debug("\nhandler's here"); - for (Common::Array::iterator i = _requests.begin(); i != _requests.end();) { - if ((*i)->handle(_connectionManager)) { - delete (*i); - _requests.erase(i); - } - else ++i; - } - if (_requests.empty()) stopTimer(); - - _connectionManager.handle(); - //TODO: unlock mutex here -} - -void Storage::startTimer(int interval) { - Common::TimerManager *manager = g_system->getTimerManager(); - if (manager->installTimerProc(cloudThread, interval, this, "Cloud Thread")) { - _timerStarted = true; - } else { - warning("Failed to create cloud thread"); - } -} - -void Storage::stopTimer() { - Common::TimerManager *manager = g_system->getTimerManager(); - manager->removeTimerProc(cloudThread); - _timerStarted = false; -} - -} //end of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index a5d048d3af..9e23e97761 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -24,28 +24,13 @@ #define BACKENDS_CLOUD_STORAGE_H #include "common/str.h" -#include "common/array.h" -#include "backends/cloud/request.h" -#include "backends/networking/curl/connectionmanager.h" namespace Cloud { class Storage { - friend void cloudThread(void *); //calls handler() - bool _timerStarted; - -protected: - Common::Array _requests; - Networking::ConnectionManager _connectionManager; - - virtual void addRequest(Request *request); //starts the timer if it's not started - virtual void handler(); - virtual void startTimer(int interval = 1000000); //1 second is the default interval - virtual void stopTimer(); - public: - Storage(); - virtual ~Storage() {}; + Storage() {} + virtual ~Storage() {} /** * Lists given directory. -- cgit v1.2.3 From f913675c43ada5c5f9128d904fd913129da35fe8 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 18 May 2016 15:31:22 +0600 Subject: CLOUD: Add ConnectionManager hotfix Tried to compile these two last commits with GCC and found a few minor problems. --- backends/cloud/dropbox/dropboxstorage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 0500db5d49..afa9447566 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -54,7 +54,7 @@ public: /** * Returns Dropbox auth link. */ - static Common::String DropboxStorage::getAuthLink(); + static Common::String getAuthLink(); /** * Show message with Dropbox auth instructions. (Temporary) -- cgit v1.2.3 From 17eb5f91433f2414dc73f89abfdd316407259b61 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 21 May 2016 00:44:09 +0600 Subject: CLOUD: Add complex callbacks Originally, I intended to add Storage API, StorageFile and StorageInfo stubs. When I tried to implement a simple info() call, I ended up fixing Request to contain some pointer field and all callbacks to have Request* parameter. And, now I have to place callback pointer into Request. which calls another callback. And, eventually, these "simple" callbacks would again require another pointer (to some caller class). --- backends/cloud/dropbox/dropboxstorage.cpp | 42 ++++++++++++--- backends/cloud/dropbox/dropboxstorage.h | 33 ++++++++++-- backends/cloud/manager.cpp | 4 +- backends/cloud/manager.h | 2 +- backends/cloud/storage.h | 85 +++++++++++++++++++++++++------ 5 files changed, 136 insertions(+), 30 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 93f0eebcf6..f2270f79cd 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -35,7 +35,7 @@ namespace Dropbox { Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow -static void printJsonCallback(void *ptr) { +static void printJsonCallback(Networking::Request* rq, void *ptr) { Common::JSONValue *json = (Common::JSONValue *)ptr; if (json) { debug("printJsonCallback:"); @@ -46,7 +46,7 @@ static void printJsonCallback(void *ptr) { } } -static void saveAccessTokenCallback(void *ptr) { +static void saveAccessTokenCallback(Networking::Request* rq, void *ptr) { Common::JSONValue *json = (Common::JSONValue *)ptr; if (json) { debug("saveAccessTokenCallback:"); @@ -69,6 +69,29 @@ static void saveAccessTokenCallback(void *ptr) { } } +void infoCallback(Networking::Request* request, void *jsonPointer) { + if (!request) { + warning("infoCallback: got NULL instead of Request"); + + Common::JSONValue *json = (Common::JSONValue *)jsonPointer; + if (json) delete json; //yeah I know we can delete NULL safely + return; + } + + Storage::InfoCallback callback = (Storage::InfoCallback)request->pointer(); + + Common::JSONValue *json = (Common::JSONValue *)jsonPointer; + if (json) { + //Common::JSONObject result = json->asObject(); + if (callback) { + callback(StorageInfo(json->stringify())); + } + delete json; + } else { + warning("infoCallback: got NULL instead of JSON!"); + } +} + DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) { curl_global_init(CURL_GLOBAL_ALL); } @@ -77,18 +100,21 @@ DropboxStorage::~DropboxStorage() { curl_global_cleanup(); } -void DropboxStorage::listDirectory(Common::String path) { +void syncSavesInfoCallback(StorageInfo info) { + debug("info: %s", info.info().c_str()); } -void DropboxStorage::syncSaves() { - //not syncing, but already something: - printInfo(); +void DropboxStorage::syncSaves(OperationCallback callback) { + //this is not the real syncSaves() implementation + info(syncSavesInfoCallback); } -void DropboxStorage::printInfo() { - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(printJsonCallback, "https://api.dropboxapi.com/1/account/info"); +void DropboxStorage::info(InfoCallback callback) { + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(infoCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); ConnMan.addRequest(request); + + request->setPointer(callback); } DropboxStorage *DropboxStorage::loadFromConfig() { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index afa9447566..d60dec29de 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -42,9 +42,36 @@ class DropboxStorage: public Cloud::Storage { public: virtual ~DropboxStorage(); - virtual void listDirectory(Common::String path); - virtual void syncSaves(); - virtual void printInfo(); + /** Returns pointer to Common::Array. */ + virtual void listDirectory(Common::String path, ListDirectoryCallback callback) {} //TODO + + /** Calls the callback when finished. */ + virtual void upload(Common::String path, Common::ReadStream* contents, OperationCallback callback) {} //TODO + + /** Returns pointer to Common::ReadStream. */ + virtual void download(Common::String path, DownloadCallback callback) {} //TODO + + /** Calls the callback when finished. */ + virtual void remove(Common::String path, OperationCallback callback) {} //TODO + + /** Calls the callback when finished. */ + virtual void syncSaves(OperationCallback callback); + + /** Calls the callback when finished. */ + virtual void createDirectory(Common::String path, OperationCallback callback) {} //TODO + + /** Calls the callback when finished. */ + virtual void touch(Common::String path, OperationCallback callback) {} //TODO + + /** Returns pointer to the ServiceInfo struct. */ + virtual void info(InfoCallback callback); + + /** Returns whether saves sync process is running. */ + virtual bool isSyncing() { return false; } //TODO + + /** Returns whether there are any requests running. */ + virtual bool isWorking() { return false; } //TODO + /** * Load token and user id from configs and return DropboxStorage for those. * @return pointer to the newly created DropboxStorage or 0 if some problem occured. diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 08340e9288..fc271485bf 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -46,9 +46,9 @@ Storage* Manager::getCurrentStorage() { return _currentStorage; } -void Manager::syncSaves() { +void Manager::syncSaves(Storage::OperationCallback callback) { Storage* storage = getCurrentStorage(); - if (storage) storage->syncSaves(); + if (storage) storage->syncSaves(callback); } } //end of namespace Cloud diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index a1f046d71d..47109cc146 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -38,7 +38,7 @@ public: virtual void init(); virtual Storage* getCurrentStorage(); - virtual void syncSaves(); + virtual void syncSaves(Storage::OperationCallback callback); }; } //end of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 9e23e97761..4fb06f6a9d 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -23,37 +23,90 @@ #ifndef BACKENDS_CLOUD_STORAGE_H #define BACKENDS_CLOUD_STORAGE_H +#include "common/array.h" +#include "common/stream.h" #include "common/str.h" namespace Cloud { +class StorageFile { + Common::String _path, _name; + uint32 _size, _timestamp; + bool _isDirectory; + +public: + StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { + _path = pth; + + _name = pth; + for (uint32 i = _name.size() - 1; i >= 0; --i) { + if (_name[i] == '/' || _name[i] == '\\') { + _name.erase(0, i); + break; + } + if (i == 0) break; //OK, I admit that's strange + } + + _size = sz; + _timestamp = ts; + _isDirectory = dir; + } + + Common::String path() const { return _path; } + Common::String name() const { return _name; } + uint32 size() const { return _size; } + uint32 timestamp() const { return _timestamp; } + bool isDirectory() const { return _isDirectory; } +}; + +class StorageInfo { + Common::String _info; + +public: + StorageInfo(Common::String info): _info(info) {} + + Common::String info() const { return _info; } +}; + class Storage { public: + typedef void(*ListDirectoryCallback)(Common::Array& result); + typedef void(*DownloadCallback)(Common::ReadStream* result); + typedef void(*InfoCallback)(StorageInfo result); + typedef void(*OperationCallback)(bool successed); + Storage() {} virtual ~Storage() {} - /** - * Lists given directory. - * - * @param path directory to list - */ + /** Returns pointer to Common::Array. */ + virtual void listDirectory(Common::String path, ListDirectoryCallback callback) = 0; + + /** Calls the callback when finished. */ + virtual void upload(Common::String path, Common::ReadStream* contents, OperationCallback callback) = 0; + + /** Returns pointer to Common::ReadStream. */ + virtual void download(Common::String path, DownloadCallback callback) = 0; + + /** Calls the callback when finished. */ + virtual void remove(Common::String path, OperationCallback callback) = 0; - //TODO: actually make it list directories - //TODO: add some callback to pass gathered files list + /** Calls the callback when finished. */ + virtual void syncSaves(OperationCallback callback) = 0; - virtual void listDirectory(Common::String path) = 0; + /** Calls the callback when finished. */ + virtual void createDirectory(Common::String path, OperationCallback callback) = 0; - /** - * Starts saves syncing process. - */ + /** Calls the callback when finished. */ + virtual void touch(Common::String path, OperationCallback callback) = 0; - virtual void syncSaves() = 0; + /** Returns pointer to the ServiceInfo struct. */ + virtual void info(InfoCallback callback) = 0; - /** - * Prints user info on console. (Temporary) - */ + /** Returns whether saves sync process is running. */ + virtual bool isSyncing() = 0; - virtual void printInfo() = 0; + /** Returns whether there are any requests running. */ + virtual bool isWorking() = 0; }; } //end of namespace Cloud -- cgit v1.2.3 From ca456a7241fb4b46f9c76c86eeecc273ca31d8f6 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 21 May 2016 14:06:50 +0600 Subject: CLOUD: Add object-oriented Callbacks These callbacks can call object's methods, not some global C functions. DropboxStorage::info2() and DropboxStorage::infoMethodCallback() demonstrate the idea. --- backends/cloud/dropbox/dropboxstorage.cpp | 41 +++++++++++++++++++++++++++++-- backends/cloud/dropbox/dropboxstorage.h | 4 +++ 2 files changed, 43 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index f2270f79cd..94bdb43450 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -92,6 +92,30 @@ void infoCallback(Networking::Request* request, void *jsonPointer) { } } +void info2Callback(Networking::Request* request, void *jsonPointer) { + if (!request) { + warning("infoCallback: got NULL instead of Request"); + + Common::JSONValue *json = (Common::JSONValue *)jsonPointer; + if (json) delete json; //yeah I know we can delete NULL safely + return; + } + + Common::BaseCallback *callback = (Common::BaseCallback *)request->pointer(); + + Common::JSONValue *json = (Common::JSONValue *)jsonPointer; + if (json) { + //Common::JSONObject result = json->asObject(); + if (callback) { + (*callback)(new StorageInfo(json->stringify())); + delete callback; + } + delete json; + } else { + warning("infoCallback: got NULL instead of JSON!"); + } +} + DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) { curl_global_init(CURL_GLOBAL_ALL); } @@ -104,9 +128,14 @@ void syncSavesInfoCallback(StorageInfo info) { debug("info: %s", info.info().c_str()); } +void DropboxStorage::infoMethodCallback(void *storageInfo) { + StorageInfo *info = (StorageInfo *)storageInfo; + debug("info: %s", info->info().c_str()); +} + void DropboxStorage::syncSaves(OperationCallback callback) { - //this is not the real syncSaves() implementation - info(syncSavesInfoCallback); + //this is not the real syncSaves() implementation + info2(new Common::Callback(this, &DropboxStorage::infoMethodCallback)); } void DropboxStorage::info(InfoCallback callback) { @@ -117,6 +146,14 @@ void DropboxStorage::info(InfoCallback callback) { request->setPointer(callback); } +void DropboxStorage::info2(Common::Callback *callback) { + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(info2Callback, "https://api.dropboxapi.com/1/account/info"); + request->addHeader("Authorization: Bearer " + _token); + ConnMan.addRequest(request); + + request->setPointer(callback); +} + DropboxStorage *DropboxStorage::loadFromConfig() { KEY = ConfMan.get("DROPBOX_KEY", "cloud"); SECRET = ConfMan.get("DROPBOX_SECRET", "cloud"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index d60dec29de..1cf657bc36 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -25,6 +25,7 @@ #include "backends/cloud/storage.h" #include "backends/cloud/manager.h" +#include "common/callback.h" namespace Cloud { namespace Dropbox { @@ -39,6 +40,8 @@ class DropboxStorage: public Cloud::Storage { static void getAccessToken(Common::String code); + void infoMethodCallback(void *serviceInfoPtr); + public: virtual ~DropboxStorage(); @@ -65,6 +68,7 @@ public: /** Returns pointer to the ServiceInfo struct. */ virtual void info(InfoCallback callback); + void info2(Common::Callback *callback); /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO -- cgit v1.2.3 From e1109c0c328aaf671e2b03b3b4e6de1ae9061754 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 21 May 2016 21:30:25 +0600 Subject: CLOUD: Add CallbackBridge This commit also adds GlobalFunctionCallback, because it was needed in order to replace plain C pointers to functions (which were used in Request) into our object-oriented BaseCallback pointers. --- backends/cloud/dropbox/dropboxstorage.cpp | 20 ++++++++++++++------ backends/cloud/dropbox/dropboxstorage.h | 3 ++- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 94bdb43450..04e9eeef0b 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -46,7 +46,7 @@ static void printJsonCallback(Networking::Request* rq, void *ptr) { } } -static void saveAccessTokenCallback(Networking::Request* rq, void *ptr) { +static void saveAccessTokenCallback(void *ptr) { Common::JSONValue *json = (Common::JSONValue *)ptr; if (json) { debug("saveAccessTokenCallback:"); @@ -139,19 +139,26 @@ void DropboxStorage::syncSaves(OperationCallback callback) { } void DropboxStorage::info(InfoCallback callback) { + /* Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(infoCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); ConnMan.addRequest(request); request->setPointer(callback); + */ } -void DropboxStorage::info2(Common::Callback *callback) { - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(info2Callback, "https://api.dropboxapi.com/1/account/info"); +void DropboxStorage::info2BridgeCallback(Common::BaseCallback *outerCallback, void *ptr) { + //no NULL checks, delete and such yet + Common::JSONValue *json = (Common::JSONValue *)ptr; + (*outerCallback)(new StorageInfo(json->stringify())); +} + +void DropboxStorage::info2(Common::BaseCallback *outerCallback) { + Common::BaseCallback *innerCallback = new Common::CallbackBridge(this, &DropboxStorage::info2BridgeCallback, outerCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); ConnMan.addRequest(request); - - request->setPointer(callback); } DropboxStorage *DropboxStorage::loadFromConfig() { @@ -205,7 +212,8 @@ void DropboxStorage::authThroughConsole() { } void DropboxStorage::getAccessToken(Common::String code) { - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(saveAccessTokenCallback, "https://api.dropboxapi.com/1/oauth2/token"); + Common::BaseCallback *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + KEY); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 1cf657bc36..efd0eea257 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -68,7 +68,8 @@ public: /** Returns pointer to the ServiceInfo struct. */ virtual void info(InfoCallback callback); - void info2(Common::Callback *callback); + void info2(Common::BaseCallback *outerCallback); + void info2BridgeCallback(Common::BaseCallback *outerCallback, void *ptr); /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO -- cgit v1.2.3 From 9e531e3ce7f5b3a1cc87b43beb6f72911cb41bdd Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 21 May 2016 23:21:42 +0600 Subject: CLOUD: Polish Callbacks Cleaned up all example code and old callbacks. New Callback classes are introduced in "common/callback.h" and documented. --- backends/cloud/dropbox/dropboxstorage.cpp | 113 ++++++++---------------------- backends/cloud/dropbox/dropboxstorage.h | 31 ++++---- backends/cloud/manager.cpp | 2 +- backends/cloud/manager.h | 2 +- backends/cloud/storage.h | 26 +++---- 5 files changed, 57 insertions(+), 117 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 04e9eeef0b..964b95bb09 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -35,17 +35,6 @@ namespace Dropbox { Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow -static void printJsonCallback(Networking::Request* rq, void *ptr) { - Common::JSONValue *json = (Common::JSONValue *)ptr; - if (json) { - debug("printJsonCallback:"); - debug("%s", json->stringify(true).c_str()); - delete json; - } else { - debug("printJsonCallback: got NULL instead of JSON!"); - } -} - static void saveAccessTokenCallback(void *ptr) { Common::JSONValue *json = (Common::JSONValue *)ptr; if (json) { @@ -69,53 +58,6 @@ static void saveAccessTokenCallback(void *ptr) { } } -void infoCallback(Networking::Request* request, void *jsonPointer) { - if (!request) { - warning("infoCallback: got NULL instead of Request"); - - Common::JSONValue *json = (Common::JSONValue *)jsonPointer; - if (json) delete json; //yeah I know we can delete NULL safely - return; - } - - Storage::InfoCallback callback = (Storage::InfoCallback)request->pointer(); - - Common::JSONValue *json = (Common::JSONValue *)jsonPointer; - if (json) { - //Common::JSONObject result = json->asObject(); - if (callback) { - callback(StorageInfo(json->stringify())); - } - delete json; - } else { - warning("infoCallback: got NULL instead of JSON!"); - } -} - -void info2Callback(Networking::Request* request, void *jsonPointer) { - if (!request) { - warning("infoCallback: got NULL instead of Request"); - - Common::JSONValue *json = (Common::JSONValue *)jsonPointer; - if (json) delete json; //yeah I know we can delete NULL safely - return; - } - - Common::BaseCallback *callback = (Common::BaseCallback *)request->pointer(); - - Common::JSONValue *json = (Common::JSONValue *)jsonPointer; - if (json) { - //Common::JSONObject result = json->asObject(); - if (callback) { - (*callback)(new StorageInfo(json->stringify())); - delete callback; - } - delete json; - } else { - warning("infoCallback: got NULL instead of JSON!"); - } -} - DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) { curl_global_init(CURL_GLOBAL_ALL); } @@ -124,41 +66,42 @@ DropboxStorage::~DropboxStorage() { curl_global_cleanup(); } -void syncSavesInfoCallback(StorageInfo info) { - debug("info: %s", info.info().c_str()); -} - -void DropboxStorage::infoMethodCallback(void *storageInfo) { - StorageInfo *info = (StorageInfo *)storageInfo; - debug("info: %s", info->info().c_str()); +void DropboxStorage::syncSaves(Common::BaseCallback *callback) { + //this is not the real syncSaves() implementation + info(new Common::Callback(this, &DropboxStorage::infoMethodCallback)); + //that line meant the following: + //"please, do the info API request and, when it's finished, call the infoMethodCallback() of me" } -void DropboxStorage::syncSaves(OperationCallback callback) { - //this is not the real syncSaves() implementation - info2(new Common::Callback(this, &DropboxStorage::infoMethodCallback)); -} - -void DropboxStorage::info(InfoCallback callback) { - /* - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(infoCallback, "https://api.dropboxapi.com/1/account/info"); +void DropboxStorage::info(Common::BaseCallback *outerCallback) { + Common::BaseCallback<> *innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); ConnMan.addRequest(request); - - request->setPointer(callback); - */ + //that callback bridge wraps the outerCallback (passed in arguments from user) into innerCallback + //so, when CurlJsonRequest is finished, it calls the innerCallback + //innerCallback (which is DropboxStorage::infoInnerCallback in this case) processes the void *ptr + //and then calls the outerCallback (which wants to receive StorageInfo, not void *) } -void DropboxStorage::info2BridgeCallback(Common::BaseCallback *outerCallback, void *ptr) { - //no NULL checks, delete and such yet +void DropboxStorage::infoInnerCallback(Common::BaseCallback *outerCallback, void *ptr) { Common::JSONValue *json = (Common::JSONValue *)ptr; - (*outerCallback)(new StorageInfo(json->stringify())); + if (!json) { + warning("NULL passed instead of JSON"); + delete outerCallback; + return; + } + + if (outerCallback) { + (*outerCallback)(StorageInfo(json->stringify())); + delete outerCallback; + } + + delete json; } -void DropboxStorage::info2(Common::BaseCallback *outerCallback) { - Common::BaseCallback *innerCallback = new Common::CallbackBridge(this, &DropboxStorage::info2BridgeCallback, outerCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); - request->addHeader("Authorization: Bearer " + _token); - ConnMan.addRequest(request); +void DropboxStorage::infoMethodCallback(StorageInfo storageInfo) { + debug("info: %s", storageInfo.info().c_str()); } DropboxStorage *DropboxStorage::loadFromConfig() { @@ -212,7 +155,7 @@ void DropboxStorage::authThroughConsole() { } void DropboxStorage::getAccessToken(Common::String code) { - Common::BaseCallback *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); + Common::BaseCallback<> *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index efd0eea257..8cc9312a87 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -24,7 +24,6 @@ #define BACKENDS_CLOUD_DROPBOX_STORAGE_H #include "backends/cloud/storage.h" -#include "backends/cloud/manager.h" #include "common/callback.h" namespace Cloud { @@ -40,36 +39,38 @@ class DropboxStorage: public Cloud::Storage { static void getAccessToken(Common::String code); - void infoMethodCallback(void *serviceInfoPtr); - public: virtual ~DropboxStorage(); - /** Returns pointer to Common::Array. */ - virtual void listDirectory(Common::String path, ListDirectoryCallback callback) {} //TODO + /** Returns pointer to Common::Array. */ + virtual void listDirectory(Common::String path, Common::BaseCallback< Common::Array > *callback) {} //TODO /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream* contents, OperationCallback callback) {} //TODO + virtual void upload(Common::String path, Common::ReadStream* contents, Common::BaseCallback *callback) {} //TODO /** Returns pointer to Common::ReadStream. */ - virtual void download(Common::String path, DownloadCallback callback) {} //TODO + virtual void download(Common::String path, Common::BaseCallback *callback) {} //TODO /** Calls the callback when finished. */ - virtual void remove(Common::String path, OperationCallback callback) {} //TODO + virtual void remove(Common::String path, Common::BaseCallback *callback) {} //TODO /** Calls the callback when finished. */ - virtual void syncSaves(OperationCallback callback); + virtual void syncSaves(Common::BaseCallback *callback); /** Calls the callback when finished. */ - virtual void createDirectory(Common::String path, OperationCallback callback) {} //TODO + virtual void createDirectory(Common::String path, Common::BaseCallback *callback) {} //TODO /** Calls the callback when finished. */ - virtual void touch(Common::String path, OperationCallback callback) {} //TODO + virtual void touch(Common::String path, Common::BaseCallback *callback) {} //TODO + + /** Returns pointer to the StorageInfo struct. */ + virtual void info(Common::BaseCallback *callback); + + /** This is what is called by CurlJsonRequest. */ + void infoInnerCallback(Common::BaseCallback *outerCallback, void *ptr); - /** Returns pointer to the ServiceInfo struct. */ - virtual void info(InfoCallback callback); - void info2(Common::BaseCallback *outerCallback); - void info2BridgeCallback(Common::BaseCallback *outerCallback, void *ptr); + /** This is what is called by infoInnerCallback() (it's its outer callback). */ + void infoMethodCallback(StorageInfo storageInfo); /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index fc271485bf..a9a2b8a232 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -46,7 +46,7 @@ Storage* Manager::getCurrentStorage() { return _currentStorage; } -void Manager::syncSaves(Storage::OperationCallback callback) { +void Manager::syncSaves(Common::BaseCallback *callback) { Storage* storage = getCurrentStorage(); if (storage) storage->syncSaves(callback); } diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index 47109cc146..c247132707 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -38,7 +38,7 @@ public: virtual void init(); virtual Storage* getCurrentStorage(); - virtual void syncSaves(Storage::OperationCallback callback); + virtual void syncSaves(Common::BaseCallback *callback); }; } //end of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 4fb06f6a9d..f2079eb919 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -26,6 +26,7 @@ #include "common/array.h" #include "common/stream.h" #include "common/str.h" +#include "common/callback.h" namespace Cloud { @@ -70,37 +71,32 @@ public: class Storage { public: - typedef void(*ListDirectoryCallback)(Common::Array& result); - typedef void(*DownloadCallback)(Common::ReadStream* result); - typedef void(*InfoCallback)(StorageInfo result); - typedef void(*OperationCallback)(bool successed); - Storage() {} virtual ~Storage() {} - /** Returns pointer to Common::Array. */ - virtual void listDirectory(Common::String path, ListDirectoryCallback callback) = 0; + /** Returns pointer to Common::Array. */ + virtual void listDirectory(Common::String path, Common::BaseCallback< Common::Array > *callback) = 0; /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream* contents, OperationCallback callback) = 0; + virtual void upload(Common::String path, Common::ReadStream* contents, Common::BaseCallback *callback) = 0; /** Returns pointer to Common::ReadStream. */ - virtual void download(Common::String path, DownloadCallback callback) = 0; + virtual void download(Common::String path, Common::BaseCallback *callback) = 0; /** Calls the callback when finished. */ - virtual void remove(Common::String path, OperationCallback callback) = 0; + virtual void remove(Common::String path, Common::BaseCallback *callback) = 0; /** Calls the callback when finished. */ - virtual void syncSaves(OperationCallback callback) = 0; + virtual void syncSaves(Common::BaseCallback *callback) = 0; /** Calls the callback when finished. */ - virtual void createDirectory(Common::String path, OperationCallback callback) = 0; + virtual void createDirectory(Common::String path, Common::BaseCallback *callback) = 0; /** Calls the callback when finished. */ - virtual void touch(Common::String path, OperationCallback callback) = 0; + virtual void touch(Common::String path, Common::BaseCallback *callback) = 0; - /** Returns pointer to the ServiceInfo struct. */ - virtual void info(InfoCallback callback) = 0; + /** Returns pointer to the StorageInfo struct. */ + virtual void info(Common::BaseCallback *callback) = 0; /** Returns whether saves sync process is running. */ virtual bool isSyncing() = 0; -- cgit v1.2.3 From b570499164bf94fc4735bad54e7a722498ae56ea Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 22 May 2016 00:04:00 +0600 Subject: CLOUD: Add Callback typedefs And do some minor cleanup work. --- backends/cloud/dropbox/dropboxstorage.cpp | 10 +++-- backends/cloud/dropbox/dropboxstorage.h | 24 +++++------ backends/cloud/manager.cpp | 2 +- backends/cloud/manager.h | 2 +- backends/cloud/storage.h | 66 ++++++++----------------------- backends/cloud/storagefile.cpp | 48 ++++++++++++++++++++++ backends/cloud/storagefile.h | 53 +++++++++++++++++++++++++ backends/cloud/storageinfo.h | 47 ++++++++++++++++++++++ 8 files changed, 185 insertions(+), 67 deletions(-) create mode 100644 backends/cloud/storagefile.cpp create mode 100644 backends/cloud/storagefile.h create mode 100644 backends/cloud/storageinfo.h (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 964b95bb09..49355fa845 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -66,14 +66,14 @@ DropboxStorage::~DropboxStorage() { curl_global_cleanup(); } -void DropboxStorage::syncSaves(Common::BaseCallback *callback) { +void DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation info(new Common::Callback(this, &DropboxStorage::infoMethodCallback)); //that line meant the following: //"please, do the info API request and, when it's finished, call the infoMethodCallback() of me" } -void DropboxStorage::info(Common::BaseCallback *outerCallback) { +void DropboxStorage::info(StorageInfoCallback outerCallback) { Common::BaseCallback<> *innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); @@ -84,8 +84,8 @@ void DropboxStorage::info(Common::BaseCallback *outerCallback) { //and then calls the outerCallback (which wants to receive StorageInfo, not void *) } -void DropboxStorage::infoInnerCallback(Common::BaseCallback *outerCallback, void *ptr) { - Common::JSONValue *json = (Common::JSONValue *)ptr; +void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, void *jsonPointer) { + Common::JSONValue *json = (Common::JSONValue *)jsonPointer; if (!json) { warning("NULL passed instead of JSON"); delete outerCallback; @@ -93,6 +93,8 @@ void DropboxStorage::infoInnerCallback(Common::BaseCallback *outerC } if (outerCallback) { + //TODO: check that JSON doesn't contain some error message instead of an actual response + //TODO: use JSON fields to construct StorageInfo (*outerCallback)(StorageInfo(json->stringify())); delete outerCallback; } diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 8cc9312a87..3fc38bc1bb 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -39,37 +39,37 @@ class DropboxStorage: public Cloud::Storage { static void getAccessToken(Common::String code); + /** Constructs StorageInfo based on JSON response from cloud. */ + void infoInnerCallback(StorageInfoCallback outerCallback, void *json); + public: virtual ~DropboxStorage(); /** Returns pointer to Common::Array. */ - virtual void listDirectory(Common::String path, Common::BaseCallback< Common::Array > *callback) {} //TODO + virtual void listDirectory(Common::String path, FileArrayCallback callback) {} //TODO /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream* contents, Common::BaseCallback *callback) {} //TODO + virtual void upload(Common::String path, Common::ReadStream* contents, BoolCallback callback) {} //TODO /** Returns pointer to Common::ReadStream. */ - virtual void download(Common::String path, Common::BaseCallback *callback) {} //TODO + virtual void download(Common::String path, ReadStreamCallback callback) {} //TODO /** Calls the callback when finished. */ - virtual void remove(Common::String path, Common::BaseCallback *callback) {} //TODO + virtual void remove(Common::String path, BoolCallback callback) {} //TODO /** Calls the callback when finished. */ - virtual void syncSaves(Common::BaseCallback *callback); + virtual void syncSaves(BoolCallback callback); /** Calls the callback when finished. */ - virtual void createDirectory(Common::String path, Common::BaseCallback *callback) {} //TODO + virtual void createDirectory(Common::String path, BoolCallback callback) {} //TODO /** Calls the callback when finished. */ - virtual void touch(Common::String path, Common::BaseCallback *callback) {} //TODO + virtual void touch(Common::String path, BoolCallback callback) {} //TODO /** Returns pointer to the StorageInfo struct. */ - virtual void info(Common::BaseCallback *callback); - - /** This is what is called by CurlJsonRequest. */ - void infoInnerCallback(Common::BaseCallback *outerCallback, void *ptr); + virtual void info(StorageInfoCallback callback); - /** This is what is called by infoInnerCallback() (it's its outer callback). */ + /** This method is passed into info(). (Temporary) */ void infoMethodCallback(StorageInfo storageInfo); /** Returns whether saves sync process is running. */ diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index a9a2b8a232..7caf241497 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -46,7 +46,7 @@ Storage* Manager::getCurrentStorage() { return _currentStorage; } -void Manager::syncSaves(Common::BaseCallback *callback) { +void Manager::syncSaves(Storage::BoolCallback callback) { Storage* storage = getCurrentStorage(); if (storage) storage->syncSaves(callback); } diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index c247132707..3ad2e0d607 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -38,7 +38,7 @@ public: virtual void init(); virtual Storage* getCurrentStorage(); - virtual void syncSaves(Common::BaseCallback *callback); + virtual void syncSaves(Storage::BoolCallback callback); }; } //end of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index f2079eb919..eaf0ba1cc8 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -27,76 +27,44 @@ #include "common/stream.h" #include "common/str.h" #include "common/callback.h" +#include "backends/cloud/storagefile.h" +#include "backends/cloud/storageinfo.h" namespace Cloud { -class StorageFile { - Common::String _path, _name; - uint32 _size, _timestamp; - bool _isDirectory; - -public: - StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { - _path = pth; - - _name = pth; - for (uint32 i = _name.size() - 1; i >= 0; --i) { - if (_name[i] == '/' || _name[i] == '\\') { - _name.erase(0, i); - break; - } - if (i == 0) break; //OK, I admit that's strange - } - - _size = sz; - _timestamp = ts; - _isDirectory = dir; - } - - Common::String path() const { return _path; } - Common::String name() const { return _name; } - uint32 size() const { return _size; } - uint32 timestamp() const { return _timestamp; } - bool isDirectory() const { return _isDirectory; } -}; - -class StorageInfo { - Common::String _info; - -public: - StorageInfo(Common::String info): _info(info) {} - - Common::String info() const { return _info; } -}; - class Storage { public: + typedef Common::BaseCallback< Common::Array > *FileArrayCallback; + typedef Common::BaseCallback *ReadStreamCallback; + typedef Common::BaseCallback *StorageInfoCallback; + typedef Common::BaseCallback *BoolCallback; + Storage() {} virtual ~Storage() {} - /** Returns pointer to Common::Array. */ - virtual void listDirectory(Common::String path, Common::BaseCallback< Common::Array > *callback) = 0; + /** Returns Common::Array. */ + virtual void listDirectory(Common::String path, FileArrayCallback callback) = 0; /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream* contents, Common::BaseCallback *callback) = 0; + virtual void upload(Common::String path, Common::ReadStream* contents, BoolCallback callback) = 0; /** Returns pointer to Common::ReadStream. */ - virtual void download(Common::String path, Common::BaseCallback *callback) = 0; + virtual void download(Common::String path, ReadStreamCallback callback) = 0; /** Calls the callback when finished. */ - virtual void remove(Common::String path, Common::BaseCallback *callback) = 0; + virtual void remove(Common::String path, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual void syncSaves(Common::BaseCallback *callback) = 0; + virtual void syncSaves(BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual void createDirectory(Common::String path, Common::BaseCallback *callback) = 0; + virtual void createDirectory(Common::String path, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual void touch(Common::String path, Common::BaseCallback *callback) = 0; + virtual void touch(Common::String path, BoolCallback callback) = 0; - /** Returns pointer to the StorageInfo struct. */ - virtual void info(Common::BaseCallback *callback) = 0; + /** Returns the StorageInfo struct. */ + virtual void info(StorageInfoCallback callback) = 0; /** Returns whether saves sync process is running. */ virtual bool isSyncing() = 0; diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp new file mode 100644 index 0000000000..0d40698823 --- /dev/null +++ b/backends/cloud/storagefile.cpp @@ -0,0 +1,48 @@ +/* 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/storagefile.h" + +namespace Cloud { + +StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { + _path = pth; + + _name = pth; + if (_name.size() != 0) { + uint32 i = _name.size() - 1; + while (true) { + if (_name[i] == '/' || _name[i] == '\\') { + _name.erase(0, i); + break; + } + if (i == 0) break; + --i; + } + } + + _size = sz; + _timestamp = ts; + _isDirectory = dir; +} + +} //end of namespace Cloud diff --git a/backends/cloud/storagefile.h b/backends/cloud/storagefile.h new file mode 100644 index 0000000000..8706ba18e9 --- /dev/null +++ b/backends/cloud/storagefile.h @@ -0,0 +1,53 @@ +/* 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_STORAGEFILE_H +#define BACKENDS_CLOUD_STORAGEFILE_H + +#include "common/str.h" + +namespace Cloud { + +/** +* StorageFile represents a file storaged on remote cloud storage. +* It contains basic information about a file, and might be used +* when listing directories or syncing files. +*/ + +class StorageFile { + Common::String _path, _name; + uint32 _size, _timestamp; + bool _isDirectory; + +public: + StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir); + + Common::String path() const { return _path; } + Common::String name() const { return _name; } + uint32 size() const { return _size; } + uint32 timestamp() const { return _timestamp; } + bool isDirectory() const { return _isDirectory; } +}; + +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/storageinfo.h b/backends/cloud/storageinfo.h new file mode 100644 index 0000000000..510acb3778 --- /dev/null +++ b/backends/cloud/storageinfo.h @@ -0,0 +1,47 @@ +/* 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_STORAGEINFO_H +#define BACKENDS_CLOUD_STORAGEINFO_H + +#include "common/str.h" + +namespace Cloud { + +/** +* StorageInfo contains information about remote cloud storage. +* It's disk quota usage, owner name, and such. +*/ + +class StorageInfo { + /** Temporary StorageInfo just contains raw JSON, received from cloud storage. */ + Common::String _info; + +public: + StorageInfo(Common::String info): _info(info) {} + + Common::String info() const { return _info; } +}; + +} //end of namespace Cloud + +#endif -- cgit v1.2.3 From 41e65db7d0468b01f626c6ce21a1b8e6791f58fa Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 23 May 2016 11:23:33 +0600 Subject: CLOUD: Add Storage saving mechanism In this commit CloudManager starts supporting multiple Storage. Now, in its init() it loads all the Storages and determines the current one. It now also has save() method. In that method all Storages are saved with their new saveConfig() method. CloudManager::save() not called from anywhere, though. The only one Storage that could be added is DropboxStorage in case you have no cloud-related config keys or you have no storages connected. --- backends/cloud/dropbox/dropboxstorage.cpp | 25 ++++++++----- backends/cloud/dropbox/dropboxstorage.h | 22 ++++++++++-- backends/cloud/manager.cpp | 59 +++++++++++++++++++++++++------ backends/cloud/manager.h | 6 ++-- backends/cloud/storage.h | 16 +++++++++ 5 files changed, 105 insertions(+), 23 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 49355fa845..d32d86567a 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -45,9 +45,12 @@ static void saveAccessTokenCallback(void *ptr) { if (!result.contains("access_token") || !result.contains("uid")) { warning("Bad response, no token/uid passed"); } else { - ConfMan.set("current_storage_type", "Dropbox", "cloud"); - ConfMan.set("current_storage_access_token", result.getVal("access_token")->asString(), "cloud"); - ConfMan.set("current_storage_user_id", result.getVal("uid")->asString(), "cloud"); + //we suppose that's the first storage + ConfMan.set("storages_number", "1", "cloud"); + ConfMan.set("current_storage", "1", "cloud"); + ConfMan.set("storage1_type", "Dropbox", "cloud"); + ConfMan.set("storage1_access_token", result.getVal("access_token")->asString(), "cloud"); + ConfMan.set("storage1_user_id", result.getVal("uid")->asString(), "cloud"); ConfMan.removeKey("dropbox_code", "cloud"); debug("Now please restart ScummVM to apply the changes."); } @@ -66,6 +69,12 @@ DropboxStorage::~DropboxStorage() { curl_global_cleanup(); } +void DropboxStorage::saveConfig(Common::String keyPrefix) { + ConfMan.set(keyPrefix + "type", "Dropbox", "cloud"); + ConfMan.set(keyPrefix + "access_token", _token, "cloud"); + ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); +} + void DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation info(new Common::Callback(this, &DropboxStorage::infoMethodCallback)); @@ -106,22 +115,22 @@ void DropboxStorage::infoMethodCallback(StorageInfo storageInfo) { debug("info: %s", storageInfo.info().c_str()); } -DropboxStorage *DropboxStorage::loadFromConfig() { +DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { KEY = ConfMan.get("DROPBOX_KEY", "cloud"); SECRET = ConfMan.get("DROPBOX_SECRET", "cloud"); - if (!ConfMan.hasKey("current_storage_access_token", "cloud")) { + if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { warning("No access_token found"); return 0; } - if (!ConfMan.hasKey("current_storage_user_id", "cloud")) { + if (!ConfMan.hasKey(keyPrefix + "user_id", "cloud")) { warning("No user_id found"); return 0; } - Common::String accessToken = ConfMan.get("current_storage_access_token", "cloud"); - Common::String userId = ConfMan.get("current_storage_user_id", "cloud"); + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud"); + Common::String userId = ConfMan.get(keyPrefix + "user_id", "cloud"); return new DropboxStorage(accessToken, userId); } diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 3fc38bc1bb..493fcdd25d 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -45,7 +45,23 @@ class DropboxStorage: public Cloud::Storage { public: virtual ~DropboxStorage(); - /** Returns pointer to Common::Array. */ + /** + * Storage methods, which are used by CloudManager to save + * storage in configuration file. + */ + + /** + * Save storage data using ConfMan. + * @param keyPrefix all saved keys must start with this prefix. + * @note every Storage must write keyPrefix + "type" key + * with common value (e.g. "Dropbox"). + */ + + virtual void saveConfig(Common::String keyPrefix); + + /** Public Cloud API comes down there. */ + + /** Returns Common::Array. */ virtual void listDirectory(Common::String path, FileArrayCallback callback) {} //TODO /** Calls the callback when finished. */ @@ -66,7 +82,7 @@ public: /** Calls the callback when finished. */ virtual void touch(Common::String path, BoolCallback callback) {} //TODO - /** Returns pointer to the StorageInfo struct. */ + /** Returns the StorageInfo struct. */ virtual void info(StorageInfoCallback callback); /** This method is passed into info(). (Temporary) */ @@ -82,7 +98,7 @@ public: * Load token and user id from configs and return DropboxStorage for those. * @return pointer to the newly created DropboxStorage or 0 if some problem occured. */ - static DropboxStorage *loadFromConfig(); + static DropboxStorage *loadFromConfig(Common::String keyPrefix); /** * Returns Dropbox auth link. diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 7caf241497..1c11efbcef 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -26,28 +26,67 @@ namespace Cloud { -Manager::Manager(): _currentStorage(0) {} +Manager::Manager(): _currentStorageIndex(0) {} -Manager::~Manager() { delete _currentStorage; } +Manager::~Manager() { + //TODO: do we have to save storages on manager destruction? + for (uint32 i = 0; i < _storages.size(); ++i) + delete _storages[i]; + _storages.clear(); +} void Manager::init() { - if (ConfMan.hasKey("current_storage_type", "cloud")) { - Common::String storageType = ConfMan.get("current_storage_type", "cloud"); - if (storageType == "Dropbox") _currentStorage = Dropbox::DropboxStorage::loadFromConfig(); - else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); + bool offerDropbox = false; + + if (ConfMan.hasKey("storages_number", "cloud")) { + int storages = ConfMan.getInt("storages_number", "cloud"); + for (int i = 1; i <= storages; ++i) { + Storage *loaded = 0; + Common::String keyPrefix = Common::String::format("storage%d_", i); + if (ConfMan.hasKey(keyPrefix + "type", "cloud")) { + Common::String storageType = ConfMan.get(keyPrefix + "type", "cloud"); + if (storageType == "Dropbox") loaded = Dropbox::DropboxStorage::loadFromConfig(keyPrefix); + else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); + } else { + warning("Cloud storage #%d (out of %d) is missing.", i, storages); + } + if (loaded) _storages.push_back(loaded); + } + + uint32 index = 0; + if (ConfMan.hasKey("current_storage", "cloud")) { + index = ConfMan.getInt("current_storage", "cloud") - 1; //count from 1, all for UX + } + if (index >= _storages.size()) index = 0; + _currentStorageIndex = index; + + if (_storages.size() == 0) offerDropbox = true; + } else { + offerDropbox = true; } - else { + + if (offerDropbox) { //this is temporary console offer to auth with Dropbox (because there is no other storage type yet anyway) Dropbox::DropboxStorage::authThroughConsole(); } } -Storage* Manager::getCurrentStorage() { - return _currentStorage; +void Manager::save() { + ConfMan.set("storages_number", Common::String::format("%d", _storages.size()), "cloud"); + ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex + 1), "cloud"); + for (uint32 i = 0; i < _storages.size(); ++i) + _storages[i]->saveConfig(Common::String::format("storage%d_", i+1)); + ConfMan.flushToDisk(); +} + +Storage *Manager::getCurrentStorage() { + if (_currentStorageIndex < _storages.size()) + return _storages[_currentStorageIndex]; + return 0; } void Manager::syncSaves(Storage::BoolCallback callback) { - Storage* storage = getCurrentStorage(); + Storage *storage = getCurrentStorage(); if (storage) storage->syncSaves(callback); } diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index 3ad2e0d607..e531854ba9 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -29,15 +29,17 @@ namespace Cloud { class Manager: public Common::CloudManager { - Storage* _currentStorage; + Common::Array _storages; + uint _currentStorageIndex; public: Manager(); virtual ~Manager(); virtual void init(); + virtual void save(); - virtual Storage* getCurrentStorage(); + virtual Storage *getCurrentStorage(); virtual void syncSaves(Storage::BoolCallback callback); }; diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index eaf0ba1cc8..a6b6c48fbe 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -42,6 +42,22 @@ public: Storage() {} virtual ~Storage() {} + /** + * Storage methods, which are used by CloudManager to save + * storage in configuration file. + */ + + /** + * Save storage data using ConfMan. + * @param keyPrefix all saved keys must start with this prefix. + * @note every Storage must write keyPrefix + "type" key + * with common value (e.g. "Dropbox"). + */ + + virtual void saveConfig(Common::String keyPrefix) = 0; + + /** Public Cloud API comes down there. */ + /** Returns Common::Array. */ virtual void listDirectory(Common::String path, FileArrayCallback callback) = 0; -- cgit v1.2.3 From a439bd4c33e6f8a47a856d7cb4a4db7c540a85ab Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 23 May 2016 12:00:12 +0600 Subject: CLOUD: Make StorageInfo useful It now contains a few useful methods to get name or quota usage. DropboxStorage returns a finely filled StorageInfo. --- backends/cloud/dropbox/dropboxstorage.cpp | 20 +++++++++++++++----- backends/cloud/storageinfo.h | 16 +++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index d32d86567a..5a881211e3 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -101,10 +101,17 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, void * return; } - if (outerCallback) { - //TODO: check that JSON doesn't contain some error message instead of an actual response - //TODO: use JSON fields to construct StorageInfo - (*outerCallback)(StorageInfo(json->stringify())); + if (outerCallback) { + //Dropbox documentation states there is no errors for this API method + Common::JSONObject info = json->asObject(); + Common::String uid = Common::String::format("%d", info.getVal("uid")->asNumber()); + Common::String name = info.getVal("display_name")->asString(); + Common::String email = info.getVal("email")->asString(); + Common::JSONObject quota = info.getVal("quota_info")->asObject(); + uint32 quotaNormal = quota.getVal("normal")->asNumber(); + uint32 quotaShared = quota.getVal("shared")->asNumber(); + uint32 quotaAllocated = quota.getVal("quota")->asNumber(); + (*outerCallback)(StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated)); delete outerCallback; } @@ -112,7 +119,10 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, void * } void DropboxStorage::infoMethodCallback(StorageInfo storageInfo) { - debug("info: %s", storageInfo.info().c_str()); + debug("\nStorage info:"); + debug("User name: %s", storageInfo.name().c_str()); + debug("Email: %s", storageInfo.email().c_str()); + debug("Disk usage: %u/%u", storageInfo.used(), storageInfo.available()); } DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/storageinfo.h b/backends/cloud/storageinfo.h index 510acb3778..f09563570f 100644 --- a/backends/cloud/storageinfo.h +++ b/backends/cloud/storageinfo.h @@ -32,14 +32,20 @@ namespace Cloud { * It's disk quota usage, owner name, and such. */ -class StorageInfo { - /** Temporary StorageInfo just contains raw JSON, received from cloud storage. */ - Common::String _info; +class StorageInfo { + Common::String _uid, _name, _email; + uint32 _usedBytes, _allocatedBytes; public: - StorageInfo(Common::String info): _info(info) {} + StorageInfo(Common::String uid, Common::String name, Common::String email, uint32 used, uint32 allocated): + _uid(uid), _name(name), _email(email), _usedBytes(used), _allocatedBytes(allocated) {} + + Common::String uid() const { return _uid; } + Common::String name() const { return _name; } + Common::String email() const { return _email; } + uint32 used() const { return _usedBytes; } + uint32 available() const { return _allocatedBytes; } - Common::String info() const { return _info; } }; } //end of namespace Cloud -- cgit v1.2.3 From 735db74b900d1e0a0654ca03983cd91cea36f41e Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 23 May 2016 12:21:45 +0600 Subject: CLOUD: Add DropboxStorage::listDirectory sketch It doesn't support any "has_more", doesn't call user's callback and just prints JSON instead of parsing in into an array of files. I believe it would become DropboxListDirectoryRequest in the next commit. --- backends/cloud/dropbox/dropboxstorage.cpp | 34 +++++++++++++++++++++++++++---- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/storage.h | 2 +- 3 files changed, 32 insertions(+), 6 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 5a881211e3..28d14c6a2e 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -75,11 +75,37 @@ void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); } +void printJson(void *ptr) { + Common::JSONValue *json = (Common::JSONValue *)ptr; + if (json) { + debug("%s", json->stringify(true).c_str()); + } else { + warning("null, not json"); + } +} + +void DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { + //Common::BaseCallback<> *innerCallback = new Common::CallbackBridge >(this, &DropboxStorage::listDirectoryInnerCallback, outerCallback); + Common::BaseCallback<> *innerCallback = 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 DropboxStorage::syncSaves(BoolCallback callback) { - //this is not the real syncSaves() implementation - info(new Common::Callback(this, &DropboxStorage::infoMethodCallback)); - //that line meant the following: - //"please, do the info API request and, when it's finished, call the infoMethodCallback() of me" + //this is not the real syncSaves() implementation + listDirectory("", 0); //"" is root in Dropbox, not "/" } void DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 493fcdd25d..3077b98763 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -62,7 +62,7 @@ public: /** Public Cloud API comes down there. */ /** Returns Common::Array. */ - virtual void listDirectory(Common::String path, FileArrayCallback callback) {} //TODO + virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); /** Calls the callback when finished. */ virtual void upload(Common::String path, Common::ReadStream* contents, BoolCallback callback) {} //TODO diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index a6b6c48fbe..1435be8329 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -59,7 +59,7 @@ public: /** Public Cloud API comes down there. */ /** Returns Common::Array. */ - virtual void listDirectory(Common::String path, FileArrayCallback callback) = 0; + virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; /** Calls the callback when finished. */ virtual void upload(Common::String path, Common::ReadStream* contents, BoolCallback callback) = 0; -- cgit v1.2.3 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 ++++++++++++++++++++ .../cloud/dropbox/dropboxlistdirectoryrequest.h | 51 +++++++++ backends/cloud/dropbox/dropboxstorage.cpp | 32 ++---- backends/cloud/dropbox/dropboxstorage.h | 2 + backends/cloud/iso8601.cpp | 117 +++++++++++++++++++++ backends/cloud/iso8601.h | 37 +++++++ backends/cloud/storagefile.cpp | 2 +- 7 files changed, 330 insertions(+), 25 deletions(-) create mode 100644 backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp create mode 100644 backends/cloud/dropbox/dropboxlistdirectoryrequest.h create mode 100644 backends/cloud/iso8601.cpp create mode 100644 backends/cloud/iso8601.h (limited to 'backends/cloud') 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 diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h new file mode 100644 index 0000000000..03b4fc121a --- /dev/null +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -0,0 +1,51 @@ +/* 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_DROPBOXLISTDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_DROPBOX_DROPBOXLISTDIRECTORYREQUEST_H + +#include "backends/cloud/storage.h" +#include "common/callback.h" +#include "backends/networking/curl/request.h" + +namespace Cloud { +namespace Dropbox { + +class DropboxListDirectoryRequest: public Networking::Request { + Storage::FileArrayCallback _filesCallback; + Common::String _token; + bool _complete; + Common::Array _files; + + void responseCallback(void *jsonPtr); + +public: + DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); + virtual ~DropboxListDirectoryRequest() { delete _filesCallback; } + + virtual bool handle(); +}; + +} //end of namespace Dropbox +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 28d14c6a2e..6de9424efc 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -22,6 +22,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/dropbox/dropboxstorage.h" +#include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "common/config-manager.h" @@ -75,37 +76,20 @@ void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); } -void printJson(void *ptr) { - Common::JSONValue *json = (Common::JSONValue *)ptr; - if (json) { - debug("%s", json->stringify(true).c_str()); - } else { - warning("null, not json"); - } +void DropboxStorage::printFiles(Common::Array files) { + debug("files:"); + for (uint32 i = 0; i < files.size(); ++i) + debug("\t%s", files[i].name().c_str()); } void DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { - //Common::BaseCallback<> *innerCallback = new Common::CallbackBridge >(this, &DropboxStorage::listDirectoryInnerCallback, outerCallback); - Common::BaseCallback<> *innerCallback = 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); + ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); } void DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation - listDirectory("", 0); //"" is root in Dropbox, not "/" + //"" is root in Dropbox, not "/" + listDirectory("", new Common::Callback >(this, &DropboxStorage::printFiles), true); } void DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 3077b98763..c1c2e03497 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -42,6 +42,8 @@ class DropboxStorage: public Cloud::Storage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, void *json); + void printFiles(Common::Array files); + public: virtual ~DropboxStorage(); diff --git a/backends/cloud/iso8601.cpp b/backends/cloud/iso8601.cpp new file mode 100644 index 0000000000..d34c98e7b8 --- /dev/null +++ b/backends/cloud/iso8601.cpp @@ -0,0 +1,117 @@ +/* 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/iso8601.h" +#include "common/str.h" + +namespace { + +uint32 find(const Common::String &haystack, const Common::String &needle, uint32 pos = 0) { + if (pos >= haystack.size()) { + return Common::String::npos; + } + + //TODO: write something smarter + uint32 lastIndex = haystack.size() - needle.size(); + for (uint32 i = pos; i < lastIndex; ++i) { + bool found = true; + for (uint32 j = 0; j < needle.size(); ++j) + if (haystack[i + j] != needle[j]) { + found = false; + break; + } + + if (found) return i; + } + + return Common::String::npos; +} + +Common::String getSubstring(const Common::String &s, uint32 beginning, uint32 ending) { + //beginning inclusive, ending exclusive + if (beginning == -1 || ending == -1) return ""; //bad + Common::String result = s; + result.erase(ending); + result.erase(0, beginning); + return result; +} + +int parseInt(Common::String s) { + //TODO: not sure this is not forbidden at all + return atoi(s.c_str()); +} + +} + +namespace Cloud { +namespace ISO8601 { + +uint32 convertToTimestamp(const Common::String &iso8601Date) { + //2015-05-12T15:50:38Z + uint32 firstHyphen = find(iso8601Date, "-"); + uint32 secondHyphen = find(iso8601Date, "-", firstHyphen + 1); + uint32 tSeparator = find(iso8601Date, "T", secondHyphen + 1); + uint32 firstColon = find(iso8601Date, ":", tSeparator + 1); + uint32 secondColon = find(iso8601Date, ":", firstColon + 1); + uint32 zSeparator = find(iso8601Date, "Z", secondColon + 1); + //now note '+1' which means if there ever was '-1' result of find(), we still did a valid find() from 0th char + + Common::String year = getSubstring(iso8601Date, 0, firstHyphen); + Common::String month = getSubstring(iso8601Date, firstHyphen + 1, secondHyphen); + Common::String day = getSubstring(iso8601Date, secondHyphen + 1, tSeparator); + Common::String hour = getSubstring(iso8601Date, tSeparator + 1, firstColon); + Common::String minute = getSubstring(iso8601Date, firstColon + 1, secondColon); + Common::String second = getSubstring(iso8601Date, secondColon + 1, zSeparator); + //now note only 'ending' argument was not '+1' (which means I could've make that function such that -1 means 'until the end') + + int Y = parseInt(year); + int M = parseInt(month); + int D = parseInt(day); + int h = parseInt(hour); + int m = parseInt(minute); + int s = parseInt(second); + + //ok, now I compose a timestamp based on my basic perception of time/date + //yeah, I know about leap years and leap seconds and all, but still we don't care there + + uint32 days = D - 1; + for (int i = 1970; i < Y; ++i) + if ((i % 4 == 0 && i % 100 != 0) || (i % 400 == 0)) + days += 366; + else + days += 365; + + int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + for (int i = 1; i < M; ++i) { + days += mdays[i - 1]; + if (i == 2) + if ((Y % 4 == 0 && Y % 100 != 0) || (Y % 400 == 0)) + days += 1; + } + + uint32 hours = days * 24 + h; + uint32 minutes = hours * 60 + m; + return minutes * 60 + s; +} + +} //end of namespace ISO8601 +} //end of namespace Cloud diff --git a/backends/cloud/iso8601.h b/backends/cloud/iso8601.h new file mode 100644 index 0000000000..a53b3bb501 --- /dev/null +++ b/backends/cloud/iso8601.h @@ -0,0 +1,37 @@ +/* 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_ISO8601_H +#define BACKENDS_CLOUD_ISO8601_H + +#include "common/str.h" + +namespace Cloud { +namespace ISO8601 { + + /** Returns timestamp corresponding to given ISO 8601 date */ + uint32 convertToTimestamp(const Common::String &iso8601Date); + +} //end of namespace ISO8601 +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp index 0d40698823..02c9cae3cf 100644 --- a/backends/cloud/storagefile.cpp +++ b/backends/cloud/storagefile.cpp @@ -32,7 +32,7 @@ StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { uint32 i = _name.size() - 1; while (true) { if (_name[i] == '/' || _name[i] == '\\') { - _name.erase(0, i); + _name.erase(0, i+1); break; } if (i == 0) break; -- cgit v1.2.3 From 3582f6165ce829e4990c15bf77d1792ee20dca55 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 24 May 2016 00:50:35 +0600 Subject: CLOUD: Change ISO8601 to use strchr I'm not sure it works as it should though. --- backends/cloud/iso8601.cpp | 54 ++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 40 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/iso8601.cpp b/backends/cloud/iso8601.cpp index d34c98e7b8..12cbb742b8 100644 --- a/backends/cloud/iso8601.cpp +++ b/backends/cloud/iso8601.cpp @@ -25,41 +25,14 @@ namespace { -uint32 find(const Common::String &haystack, const Common::String &needle, uint32 pos = 0) { - if (pos >= haystack.size()) { - return Common::String::npos; - } - - //TODO: write something smarter - uint32 lastIndex = haystack.size() - needle.size(); - for (uint32 i = pos; i < lastIndex; ++i) { - bool found = true; - for (uint32 j = 0; j < needle.size(); ++j) - if (haystack[i + j] != needle[j]) { - found = false; - break; - } - - if (found) return i; - } - - return Common::String::npos; -} - Common::String getSubstring(const Common::String &s, uint32 beginning, uint32 ending) { //beginning inclusive, ending exclusive - if (beginning == -1 || ending == -1) return ""; //bad Common::String result = s; result.erase(ending); result.erase(0, beginning); return result; } -int parseInt(Common::String s) { - //TODO: not sure this is not forbidden at all - return atoi(s.c_str()); -} - } namespace Cloud { @@ -67,13 +40,14 @@ namespace ISO8601 { uint32 convertToTimestamp(const Common::String &iso8601Date) { //2015-05-12T15:50:38Z - uint32 firstHyphen = find(iso8601Date, "-"); - uint32 secondHyphen = find(iso8601Date, "-", firstHyphen + 1); - uint32 tSeparator = find(iso8601Date, "T", secondHyphen + 1); - uint32 firstColon = find(iso8601Date, ":", tSeparator + 1); - uint32 secondColon = find(iso8601Date, ":", firstColon + 1); - uint32 zSeparator = find(iso8601Date, "Z", secondColon + 1); - //now note '+1' which means if there ever was '-1' result of find(), we still did a valid find() from 0th char + const char *cstr = iso8601Date.c_str(); + uint32 firstHyphen = strchr(cstr, '-') - cstr; + uint32 secondHyphen = strchr(cstr + firstHyphen + 1, '-') - cstr; + uint32 tSeparator = strchr(cstr + secondHyphen + 1, 'T') - cstr; + uint32 firstColon = strchr(cstr + tSeparator + 1, ':') - cstr; + uint32 secondColon = strchr(cstr + firstColon + 1, ':') - cstr; + uint32 zSeparator = strchr(cstr + secondColon + 1, 'Z') - cstr; + //now note '+1' which means if there ever was '-1' result of find(), we still did a valid find() from 0th char Common::String year = getSubstring(iso8601Date, 0, firstHyphen); Common::String month = getSubstring(iso8601Date, firstHyphen + 1, secondHyphen); @@ -83,12 +57,12 @@ uint32 convertToTimestamp(const Common::String &iso8601Date) { Common::String second = getSubstring(iso8601Date, secondColon + 1, zSeparator); //now note only 'ending' argument was not '+1' (which means I could've make that function such that -1 means 'until the end') - int Y = parseInt(year); - int M = parseInt(month); - int D = parseInt(day); - int h = parseInt(hour); - int m = parseInt(minute); - int s = parseInt(second); + int Y = atoi(year.c_str()); + int M = atoi(month.c_str()); + int D = atoi(day.c_str()); + int h = atoi(hour.c_str()); + int m = atoi(minute.c_str()); + int s = atoi(second.c_str()); //ok, now I compose a timestamp based on my basic perception of time/date //yeah, I know about leap years and leap seconds and all, but still we don't care there -- 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/downloadrequest.cpp | 67 ++++++++++++++++++++++ backends/cloud/downloadrequest.h | 45 +++++++++++++++ .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 1 + .../cloud/dropbox/dropboxlistdirectoryrequest.h | 2 +- backends/cloud/dropbox/dropboxstorage.cpp | 21 ++++++- backends/cloud/dropbox/dropboxstorage.h | 9 ++- backends/cloud/storage.h | 10 +++- 7 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 backends/cloud/downloadrequest.cpp create mode 100644 backends/cloud/downloadrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp new file mode 100644 index 0000000000..ed84d4f0e5 --- /dev/null +++ b/backends/cloud/downloadrequest.cpp @@ -0,0 +1,67 @@ +/* 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/downloadrequest.h" +#include "common/debug.h" +#include "common/textconsole.h" + +namespace Cloud { + +DownloadRequest::DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream): + Request(0), _boolCallback(callback), _stream(stream) {} + +bool DownloadRequest::handle() { + if (!_stream) { + warning("DownloadRequest: no stream to read"); + return true; + } + + const int kBufSize = 16 * 1024; + char buf[kBufSize]; + uint32 readBytes = _stream->read(buf, kBufSize); + + //TODO: save into file + /* + if (readBytes != 0) + if (_outputStream.write(buf, readBytes) != readBytes) + warning("DropboxDownloadRequest: unable to write all received bytes into output stream"); + */ + + buf[readBytes] = 0; + debug("%s", buf); //TODO: remove + + if (_stream->eos()) { + if (_stream->httpResponseCode() != 200) { + warning("HTTP response code is not 200 OK (it's %ld)", _stream->httpResponseCode()); + //TODO: do something about it actually + } + + if (_boolCallback) (*_boolCallback)(_stream->httpResponseCode() == 200); + + //TODO: close file stream + return true; + } + + return false; +} + +} //end of namespace Cloud diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h new file mode 100644 index 0000000000..a819910b1b --- /dev/null +++ b/backends/cloud/downloadrequest.h @@ -0,0 +1,45 @@ +/* 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_DOWNLOADREQUEST_H +#define BACKENDS_CLOUD_DOWNLOADREQUEST_H + +#include "backends/networking/curl/request.h" +#include "backends/networking/curl/networkreadstream.h" +#include "backends/cloud/storage.h" + +namespace Cloud { + +class DownloadRequest: public Networking::Request { + Networking::NetworkReadStream *_stream; + Storage::BoolCallback _boolCallback; + +public: + DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream); + virtual ~DownloadRequest() {} + + virtual bool handle(); +}; + +} //end of namespace Cloud + +#endif 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 { diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 03b4fc121a..0c10512782 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -24,8 +24,8 @@ #define BACKENDS_CLOUD_DROPBOX_DROPBOXLISTDIRECTORYREQUEST_H #include "backends/cloud/storage.h" -#include "common/callback.h" #include "backends/networking/curl/request.h" +#include "common/callback.h" namespace Cloud { namespace Dropbox { diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 6de9424efc..1b6dc1b92f 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -23,6 +23,7 @@ #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h" +#include "backends/cloud/downloadrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "common/config-manager.h" @@ -86,10 +87,28 @@ void DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerC ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); } +Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("path", new Common::JSONValue(path)); + Common::JSONValue value(jsonRequestParameters); + + Networking::CurlRequest *request = new Networking::CurlRequest(0, "https://content.dropboxapi.com/2/files/download"); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); + request->addHeader("Content-Type: "); //required to be empty (as we do POST, it's usually app/form-url-encoded) + + return request->execute(); +} + +void DropboxStorage::download(Common::String path, BoolCallback callback) { + ConnMan.addRequest(new DownloadRequest(callback, streamFile(path))); +} + void DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation //"" is root in Dropbox, not "/" - listDirectory("", new Common::Callback >(this, &DropboxStorage::printFiles), true); + //listDirectory("", new Common::Callback >(this, &DropboxStorage::printFiles), true); + download("/notempty.txt", 0); } void DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index c1c2e03497..92c3746da5 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -67,10 +67,13 @@ public: virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream* contents, BoolCallback callback) {} //TODO + virtual void upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) {} //TODO - /** Returns pointer to Common::ReadStream. */ - virtual void download(Common::String path, ReadStreamCallback callback) {} //TODO + /** Returns pointer to Networking::NetworkReadStream. */ + virtual Networking::NetworkReadStream *streamFile(Common::String path); + + /** Calls the callback when finished. */ + virtual void download(Common::String path, BoolCallback callback); /** Calls the callback when finished. */ virtual void remove(Common::String path, BoolCallback callback) {} //TODO diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 1435be8329..92f3bb96b2 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -29,6 +29,7 @@ #include "common/callback.h" #include "backends/cloud/storagefile.h" #include "backends/cloud/storageinfo.h" +#include "backends/networking/curl/networkreadstream.h" namespace Cloud { @@ -62,10 +63,13 @@ public: virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream* contents, BoolCallback callback) = 0; + virtual void upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) = 0; - /** Returns pointer to Common::ReadStream. */ - virtual void download(Common::String path, ReadStreamCallback callback) = 0; + /** Returns pointer to Networking::NetworkReadStream. */ + virtual Networking::NetworkReadStream *streamFile(Common::String path) = 0; + + /** Calls the callback when finished. */ + virtual void download(Common::String path, BoolCallback callback) = 0; /** Calls the callback when finished. */ virtual void remove(Common::String path, BoolCallback callback) = 0; -- cgit v1.2.3 From caaa4c5a5d0bce7582cc6611d8bde53fbdb1f2d1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 24 May 2016 12:31:27 +0600 Subject: CLOUD: Make DownloadRequest write to local file Tested with .jpg file. Transfer complete, CRC-32 is the same. --- backends/cloud/downloadrequest.cpp | 41 ++++++++++++++++++------------- backends/cloud/downloadrequest.h | 8 +++--- backends/cloud/dropbox/dropboxstorage.cpp | 15 ++++++++--- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/storage.h | 2 +- 5 files changed, 43 insertions(+), 25 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index ed84d4f0e5..8124fd67d7 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -26,38 +26,45 @@ namespace Cloud { -DownloadRequest::DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream): - Request(0), _boolCallback(callback), _stream(stream) {} +DownloadRequest::DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream, Common::DumpFile *dumpFile): + Request(0), _boolCallback(callback), _remoteFileStream(stream), _localFile(dumpFile) {} bool DownloadRequest::handle() { - if (!_stream) { + if (!_remoteFileStream) { warning("DownloadRequest: no stream to read"); return true; } + if (!_localFile) { + warning("DownloadRequest: no file to write"); + return true; + } + + if (!_localFile->isOpen()) { + warning("DownloadRequest: failed to open file to write"); + return true; + } + const int kBufSize = 16 * 1024; char buf[kBufSize]; - uint32 readBytes = _stream->read(buf, kBufSize); + uint32 readBytes = _remoteFileStream->read(buf, kBufSize); - //TODO: save into file - /* if (readBytes != 0) - if (_outputStream.write(buf, readBytes) != readBytes) - warning("DropboxDownloadRequest: unable to write all received bytes into output stream"); - */ - - buf[readBytes] = 0; - debug("%s", buf); //TODO: remove + if (_localFile->write(buf, readBytes) != readBytes) { + warning("DownloadRequest: unable to write all received bytes into output file"); + if (_boolCallback) (*_boolCallback)(false); + return true; + } - if (_stream->eos()) { - if (_stream->httpResponseCode() != 200) { - warning("HTTP response code is not 200 OK (it's %ld)", _stream->httpResponseCode()); + if (_remoteFileStream->eos()) { + if (_remoteFileStream->httpResponseCode() != 200) { + warning("HTTP response code is not 200 OK (it's %ld)", _remoteFileStream->httpResponseCode()); //TODO: do something about it actually } - if (_boolCallback) (*_boolCallback)(_stream->httpResponseCode() == 200); + if (_boolCallback) (*_boolCallback)(_remoteFileStream->httpResponseCode() == 200); - //TODO: close file stream + _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() return true; } diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index a819910b1b..b135b15f23 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -26,16 +26,18 @@ #include "backends/networking/curl/request.h" #include "backends/networking/curl/networkreadstream.h" #include "backends/cloud/storage.h" +#include namespace Cloud { class DownloadRequest: public Networking::Request { - Networking::NetworkReadStream *_stream; Storage::BoolCallback _boolCallback; + Networking::NetworkReadStream *_remoteFileStream; + Common::DumpFile *_localFile; public: - DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream); - virtual ~DownloadRequest() {} + DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream, Common::DumpFile *dumpFile); + virtual ~DownloadRequest() { delete _localFile; } virtual bool handle(); }; diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 1b6dc1b92f..38ad12d94b 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -30,6 +30,7 @@ #include "common/debug.h" #include "common/json.h" #include +#include namespace Cloud { namespace Dropbox { @@ -100,15 +101,23 @@ Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { return request->execute(); } -void DropboxStorage::download(Common::String path, BoolCallback callback) { - ConnMan.addRequest(new DownloadRequest(callback, streamFile(path))); +void DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { + Common::DumpFile *f = new Common::DumpFile(); + if (!f->open(localPath)) { + warning("DropboxStorage: unable to open file to download into"); + if (callback) (*callback)(false); + delete f; + return; + } + + ConnMan.addRequest(new DownloadRequest(callback, streamFile(remotePath), f)); } void DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation //"" is root in Dropbox, not "/" //listDirectory("", new Common::Callback >(this, &DropboxStorage::printFiles), true); - download("/notempty.txt", 0); + download("/remote/test.jpg", "local/test.jpg", 0); } void DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 92c3746da5..415a3fe5fb 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -73,7 +73,7 @@ public: virtual Networking::NetworkReadStream *streamFile(Common::String path); /** Calls the callback when finished. */ - virtual void download(Common::String path, BoolCallback callback); + virtual void download(Common::String remotePath, Common::String localPath, BoolCallback callback); /** Calls the callback when finished. */ virtual void remove(Common::String path, BoolCallback callback) {} //TODO diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 92f3bb96b2..e38c6bedd9 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -69,7 +69,7 @@ public: virtual Networking::NetworkReadStream *streamFile(Common::String path) = 0; /** Calls the callback when finished. */ - virtual void download(Common::String path, BoolCallback callback) = 0; + virtual void download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; /** Calls the callback when finished. */ virtual void remove(Common::String path, BoolCallback callback) = 0; -- cgit v1.2.3 From 5f4bbe6e9e08f5f76eada84497a7530ffb08fbf1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 24 May 2016 16:19:22 +0600 Subject: CLOUD: Add OneDrive Storage stub Knows how to OAuth already. This commit also adds CloudManager::addStorage(), so OneDriveStorage can add newly created Storage and CloudManager can save it in the configuration file. --- backends/cloud/downloadrequest.cpp | 2 +- backends/cloud/manager.cpp | 19 +++- backends/cloud/manager.h | 1 + backends/cloud/onedrive/onedrivestorage.cpp | 151 ++++++++++++++++++++++++++++ backends/cloud/onedrive/onedrivestorage.h | 119 ++++++++++++++++++++++ 5 files changed, 289 insertions(+), 3 deletions(-) create mode 100644 backends/cloud/onedrive/onedrivestorage.cpp create mode 100644 backends/cloud/onedrive/onedrivestorage.h (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 8124fd67d7..e86b6552e9 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -45,7 +45,7 @@ bool DownloadRequest::handle() { return true; } - const int kBufSize = 16 * 1024; + const int kBufSize = 640 * 1024; //640 KB is enough to everyone?.. char buf[kBufSize]; uint32 readBytes = _remoteFileStream->read(buf, kBufSize); diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 1c11efbcef..a7e92dfe03 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -23,6 +23,7 @@ #include "backends/cloud/manager.h" #include "backends/cloud/dropbox/dropboxstorage.h" #include "common/config-manager.h" +#include "onedrive/onedrivestorage.h" namespace Cloud { @@ -37,6 +38,7 @@ Manager::~Manager() { void Manager::init() { bool offerDropbox = false; + bool offerOneDrive = true; if (ConfMan.hasKey("storages_number", "cloud")) { int storages = ConfMan.getInt("storages_number", "cloud"); @@ -46,7 +48,10 @@ void Manager::init() { if (ConfMan.hasKey(keyPrefix + "type", "cloud")) { Common::String storageType = ConfMan.get(keyPrefix + "type", "cloud"); if (storageType == "Dropbox") loaded = Dropbox::DropboxStorage::loadFromConfig(keyPrefix); - else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); + else if (storageType == "OneDrive") { + loaded = OneDrive::OneDriveStorage::loadFromConfig(keyPrefix); + offerOneDrive = false; + } else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); } else { warning("Cloud storage #%d (out of %d) is missing.", i, storages); } @@ -66,8 +71,11 @@ void Manager::init() { } if (offerDropbox) { - //this is temporary console offer to auth with Dropbox (because there is no other storage type yet anyway) + //this is temporary console offer to auth with Dropbox Dropbox::DropboxStorage::authThroughConsole(); + } else if(offerOneDrive) { + //OneDrive time + OneDrive::OneDriveStorage::authThroughConsole(); } } @@ -79,6 +87,13 @@ void Manager::save() { ConfMan.flushToDisk(); } +void Manager::addStorage(Cloud::Storage *storage, bool makeCurrent, bool saveConfig) { + if (!storage) error("Cloud::Manager: NULL storage passed"); + _storages.push_back(storage); + if (makeCurrent) _currentStorageIndex = _storages.size() - 1; + if (saveConfig) save(); +} + Storage *Manager::getCurrentStorage() { if (_currentStorageIndex < _storages.size()) return _storages[_currentStorageIndex]; diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index e531854ba9..08106e0513 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -38,6 +38,7 @@ public: virtual void init(); virtual void save(); + virtual void addStorage(Cloud::Storage *storage, bool makeCurrent = true, bool saveConfig = true); virtual Storage *getCurrentStorage(); virtual void syncSaves(Storage::BoolCallback callback); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp new file mode 100644 index 0000000000..b632c74580 --- /dev/null +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -0,0 +1,151 @@ +/* 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. +* +*/ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/curljsonrequest.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/json.h" +#include +#include +#include "common/system.h" +#include "common/cloudmanager.h" + +namespace Cloud { +namespace OneDrive { + +Common::String OneDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth +Common::String OneDriveStorage::SECRET; //TODO: hide these secrets somehow + +static void saveAccessTokenCallback(void *ptr) { + Common::JSONValue *json = (Common::JSONValue *)ptr; + if (json) { + debug("saveAccessTokenCallback:"); + debug("%s", json->stringify(true).c_str()); + + //TODO: do something about refresh token + Common::JSONObject result = json->asObject(); + if (!result.contains("access_token") || !result.contains("user_id")) { + warning("Bad response, no token/user_id passed"); + } else { + OneDriveStorage::addStorage(result.getVal("access_token")->asString(), result.getVal("user_id")->asString()); + ConfMan.removeKey("onedrive_code", "cloud"); + debug("Done! You can use OneDrive now! Look:"); + g_system->getCloudManager()->syncSaves(); + } + + delete json; + } else { + debug("saveAccessTokenCallback: got NULL instead of JSON!"); + } +} + +OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) { + curl_global_init(CURL_GLOBAL_ALL); +} + +OneDriveStorage::~OneDriveStorage() { + curl_global_cleanup(); +} + +void OneDriveStorage::saveConfig(Common::String keyPrefix) { + ConfMan.set(keyPrefix + "type", "OneDrive", "cloud"); + ConfMan.set(keyPrefix + "access_token", _token, "cloud"); + ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); +} + +void OneDriveStorage::syncSaves(BoolCallback callback) { + //this is not the real syncSaves() implementation +} + +void OneDriveStorage::addStorage(Common::String token, Common::String uid) { + Storage *storage = new OneDriveStorage(token, uid); + g_system->getCloudManager()->addStorage(storage); +} + +OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { + KEY = ConfMan.get("ONEDRIVE_KEY", "cloud"); + SECRET = ConfMan.get("ONEDRIVE_SECRET", "cloud"); + + if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { + warning("No access_token found"); + return 0; + } + + if (!ConfMan.hasKey(keyPrefix + "user_id", "cloud")) { + warning("No user_id found"); + return 0; + } + + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud"); + Common::String userId = ConfMan.get(keyPrefix + "user_id", "cloud"); + return new OneDriveStorage(accessToken, userId); +} + +Common::String OneDriveStorage::getAuthLink() { + Common::String url = "https://login.live.com/oauth20_authorize.srf"; + url += "?response_type=code"; + url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting + //url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening + url += "&client_id=" + KEY; + url += "&scope=onedrive.appfolder"; //TODO + return url; +} + +void OneDriveStorage::authThroughConsole() { + if (!ConfMan.hasKey("ONEDRIVE_KEY", "cloud") || !ConfMan.hasKey("ONEDRIVE_SECRET", "cloud")) { + warning("No OneDrive keys available, cannot do auth"); + return; + } + + KEY = ConfMan.get("ONEDRIVE_KEY", "cloud"); + SECRET = ConfMan.get("ONEDRIVE_SECRET", "cloud"); + + if (ConfMan.hasKey("onedrive_code", "cloud")) { + //phase 2: get access_token using specified code + getAccessToken(ConfMan.get("onedrive_code", "cloud")); + return; + } + + debug("Navigate to this URL and press \"Allow\":"); + debug("%s\n", getAuthLink().c_str()); + debug("Then, add onedrive_code key in [cloud] section of configuration file. You should copy the value from URL and put it as value for that key.\n"); + debug("Navigate to this URL to get more information on ScummVM's configuration files:"); + debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); +} + +void OneDriveStorage::getAccessToken(Common::String code) { + Common::BaseCallback<> *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://login.live.com/oauth20_token.srf"); + //Content-Type: application/x-www-form-urlencoded + request->addPostField("code=" + code); + request->addPostField("grant_type=authorization_code"); + request->addPostField("client_id=" + KEY); + request->addPostField("client_secret=" + SECRET); + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); + ConnMan.addRequest(request); +} + +} //end of namespace OneDrive +} //end of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h new file mode 100644 index 0000000000..99f8476bc1 --- /dev/null +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -0,0 +1,119 @@ +/* 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_ONEDRIVESTORAGE_H +#define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVESTORAGE_H + +#include "backends/cloud/storage.h" +#include "common/callback.h" + +namespace Cloud { +namespace OneDrive { + +class OneDriveStorage: public Cloud::Storage { + static Common::String KEY, SECRET; + + Common::String _token, _uid; + + /** This private constructor is called from loadFromConfig(). */ + OneDriveStorage(Common::String token, Common::String uid); + + static void getAccessToken(Common::String code); + +public: + virtual ~OneDriveStorage(); + + /** + * Storage methods, which are used by CloudManager to save + * storage in configuration file. + */ + + /** + * Save storage data using ConfMan. + * @param keyPrefix all saved keys must start with this prefix. + * @note every Storage must write keyPrefix + "type" key + * with common value (e.g. "Dropbox"). + */ + + virtual void saveConfig(Common::String keyPrefix); + + /** Public Cloud API comes down there. */ + + /** Returns Common::Array. */ + virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) {} //TODO + + /** Calls the callback when finished. */ + virtual void upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) {} //TODO + + /** Returns pointer to Networking::NetworkReadStream. */ + virtual Networking::NetworkReadStream *streamFile(Common::String path) { return 0; } //TODO + + /** Calls the callback when finished. */ + virtual void download(Common::String remotePath, Common::String localPath, BoolCallback callback) {} //TODO + + /** Calls the callback when finished. */ + virtual void remove(Common::String path, BoolCallback callback) {} //TODO + + /** Calls the callback when finished. */ + virtual void syncSaves(BoolCallback callback); + + /** Calls the callback when finished. */ + virtual void createDirectory(Common::String path, BoolCallback callback) {} //TODO + + /** Calls the callback when finished. */ + virtual void touch(Common::String path, BoolCallback callback) {} //TODO + + /** Returns the StorageInfo struct. */ + virtual void info(StorageInfoCallback callback) {} //TODO + + /** Returns whether saves sync process is running. */ + virtual bool isSyncing() { return false; } //TODO + + /** Returns whether there are any requests running. */ + virtual bool isWorking() { return false; } //TODO + + /** + * Add OneDriveStorage with given token and uid into Cloud::Manager. + */ + static void addStorage(Common::String token, Common::String uid); + + /** + * Load token and user id from configs and return OneDriveStorage for those. + * @return pointer to the newly created OneDriveStorage or 0 if some problem occured. + */ + static OneDriveStorage *loadFromConfig(Common::String keyPrefix); + + /** + * Returns OneDrive auth link. + */ + static Common::String getAuthLink(); + + /** + * Show message with OneDrive auth instructions. (Temporary) + */ + static void authThroughConsole(); +}; + +} //end of namespace OneDrive +} //end of namespace Cloud + +#endif -- cgit v1.2.3 From 5e346ea6fbcd4a028bc7dd63efd09ff42770f8ef Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 24 May 2016 23:08:48 +0600 Subject: CLOUD: Add OneDrive refresh_token support It might be not that easy to restart the request after new token received, though. --- backends/cloud/onedrive/onedrivestorage.cpp | 139 +++++++++++++++++++--------- backends/cloud/onedrive/onedrivestorage.h | 26 ++++-- 2 files changed, 115 insertions(+), 50 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index b632c74580..2f10841cc9 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -38,50 +38,111 @@ namespace OneDrive { Common::String OneDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth Common::String OneDriveStorage::SECRET; //TODO: hide these secrets somehow -static void saveAccessTokenCallback(void *ptr) { - Common::JSONValue *json = (Common::JSONValue *)ptr; - if (json) { - debug("saveAccessTokenCallback:"); - debug("%s", json->stringify(true).c_str()); - - //TODO: do something about refresh token - Common::JSONObject result = json->asObject(); - if (!result.contains("access_token") || !result.contains("user_id")) { - warning("Bad response, no token/user_id passed"); - } else { - OneDriveStorage::addStorage(result.getVal("access_token")->asString(), result.getVal("user_id")->asString()); - ConfMan.removeKey("onedrive_code", "cloud"); - debug("Done! You can use OneDrive now! Look:"); - g_system->getCloudManager()->syncSaves(); - } +OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId, Common::String refreshToken): + _token(accessToken), _uid(userId), _refreshToken(refreshToken) {} - delete json; +OneDriveStorage::OneDriveStorage(Common::String code) { + getAccessToken(new Common::Callback(this, &OneDriveStorage::codeFlowComplete), code); +} + +OneDriveStorage::~OneDriveStorage() {} + +void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) { + bool codeFlow = (code != ""); + + if (!codeFlow && _refreshToken == "") { + warning("OneDriveStorage: no refresh token available to get new access token."); + if (callback) (*callback)(false); + return; + } + + Common::BaseCallback<> *innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://login.live.com/oauth20_token.srf"); + if (codeFlow) { + request->addPostField("code=" + code); + request->addPostField("grant_type=authorization_code"); } else { - debug("saveAccessTokenCallback: got NULL instead of JSON!"); + request->addPostField("refresh_token=" + _refreshToken); + request->addPostField("grant_type=refresh_token"); } + request->addPostField("client_id=" + KEY); + request->addPostField("client_secret=" + SECRET); + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); + ConnMan.addRequest(request); } -OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) { - curl_global_init(CURL_GLOBAL_ALL); +void OneDriveStorage::tokenRefreshed(BoolCallback callback, void *jsonPointer) { + Common::JSONValue *json = (Common::JSONValue *)jsonPointer; + if (!json) { + warning("OneDriveStorage: got NULL instead of JSON"); + if (callback) (*callback)(false); + return; + } + + Common::JSONObject result = json->asObject(); + if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) { + warning("Bad response, no token or user_id passed"); + debug("%s", json->stringify().c_str()); + if (callback) (*callback)(false); + } else { + _token = result.getVal("access_token")->asString(); + _uid = result.getVal("user_id")->asString(); + _refreshToken = result.getVal("refresh_token")->asString(); + g_system->getCloudManager()->save(); //ask CloudManager to save our new refreshToken + if (callback) (*callback)(true); + } + delete json; } -OneDriveStorage::~OneDriveStorage() { - curl_global_cleanup(); +void OneDriveStorage::codeFlowComplete(bool success) { + if (!success) { + warning("OneDriveStorage: failed to get access token through code flow"); + return; + } + + g_system->getCloudManager()->addStorage(this); + ConfMan.removeKey("onedrive_code", "cloud"); + debug("Done! You can use OneDrive now! Look:"); + g_system->getCloudManager()->syncSaves(); } void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "type", "OneDrive", "cloud"); ConfMan.set(keyPrefix + "access_token", _token, "cloud"); ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); + ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } -void OneDriveStorage::syncSaves(BoolCallback callback) { - //this is not the real syncSaves() implementation +void OneDriveStorage::printJsonTokenReceived(bool success) { + if (success) syncSaves(0); //try again +} + +void OneDriveStorage::printJson(void *jsonPointer) { + Common::JSONValue *json = (Common::JSONValue *)jsonPointer; + if (!json) { + warning("printJson: NULL"); + return; + } + + Common::JSONObject result = json->asObject(); + if (result.contains("error")) { + //Common::JSONObject error = result.getVal("error")->asObject(); + debug("bad token, trying again..."); + getAccessToken(new Common::Callback(this, &OneDriveStorage::printJsonTokenReceived)); + delete json; + return; + } + + debug("%s", json->stringify().c_str()); + delete json; } -void OneDriveStorage::addStorage(Common::String token, Common::String uid) { - Storage *storage = new OneDriveStorage(token, uid); - g_system->getCloudManager()->addStorage(storage); +void OneDriveStorage::syncSaves(BoolCallback callback) { + //this is not the real syncSaves() implementation + Common::BaseCallback<> *innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/"); + request->addHeader("Authorization: bearer " + _token); + ConnMan.addRequest(request); } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { @@ -98,9 +159,15 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { return 0; } + if (!ConfMan.hasKey(keyPrefix + "refresh_token", "cloud")) { + warning("No refresh_token found"); + return 0; + } + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud"); Common::String userId = ConfMan.get(keyPrefix + "user_id", "cloud"); - return new OneDriveStorage(accessToken, userId); + Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", "cloud"); + return new OneDriveStorage(accessToken, userId, refreshToken); } Common::String OneDriveStorage::getAuthLink() { @@ -109,7 +176,7 @@ Common::String OneDriveStorage::getAuthLink() { url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting //url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening url += "&client_id=" + KEY; - url += "&scope=onedrive.appfolder"; //TODO + url += "&scope=onedrive.appfolder%20offline_access"; //TODO return url; } @@ -124,7 +191,7 @@ void OneDriveStorage::authThroughConsole() { if (ConfMan.hasKey("onedrive_code", "cloud")) { //phase 2: get access_token using specified code - getAccessToken(ConfMan.get("onedrive_code", "cloud")); + new OneDriveStorage(ConfMan.get("onedrive_code", "cloud")); return; } @@ -135,17 +202,5 @@ void OneDriveStorage::authThroughConsole() { debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); } -void OneDriveStorage::getAccessToken(Common::String code) { - Common::BaseCallback<> *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://login.live.com/oauth20_token.srf"); - //Content-Type: application/x-www-form-urlencoded - request->addPostField("code=" + code); - request->addPostField("grant_type=authorization_code"); - request->addPostField("client_id=" + KEY); - request->addPostField("client_secret=" + SECRET); - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); - ConnMan.addRequest(request); -} - } //end of namespace OneDrive } //end of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 99f8476bc1..28f37aee2c 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -32,13 +32,28 @@ namespace OneDrive { class OneDriveStorage: public Cloud::Storage { static Common::String KEY, SECRET; - Common::String _token, _uid; + Common::String _token, _uid, _refreshToken; /** This private constructor is called from loadFromConfig(). */ - OneDriveStorage(Common::String token, Common::String uid); + OneDriveStorage(Common::String token, Common::String uid, Common::String refreshToken); - static void getAccessToken(Common::String code); + /** + * This private constructor is called from authThroughConsole() (phase 2). + * It uses OAuth code flow to get tokens. + */ + OneDriveStorage(Common::String code); + + /** + * Gets new access_token. If passed is "", refresh_token is used. + * Use "" in order to refresh token and pass a callback, so you could + * continue your work when new token is available. + */ + void getAccessToken(BoolCallback callback, Common::String code = ""); + void tokenRefreshed(BoolCallback callback, void *jsonPointer); + void codeFlowComplete(bool success); + void printJson(void *jsonPointer); + void printJsonTokenReceived(bool success); public: virtual ~OneDriveStorage(); @@ -91,11 +106,6 @@ public: /** Returns whether there are any requests running. */ virtual bool isWorking() { return false; } //TODO - /** - * Add OneDriveStorage with given token and uid into Cloud::Manager. - */ - static void addStorage(Common::String token, Common::String uid); - /** * Load token and user id from configs and return OneDriveStorage for those. * @return pointer to the newly created OneDriveStorage or 0 if some problem occured. -- cgit v1.2.3 From ae8e7f39f5b3e4f647a29d39d19cce7626528bb1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 25 May 2016 16:32:22 +0600 Subject: CLOUD: Make download() create necessary directories DumpFile::open() with createPath=true create would create the missing directories from the path before opening a file. Thus, one can easily create a file and avoid "can't open a file" error. --- backends/cloud/dropbox/dropboxstorage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 38ad12d94b..e5041466e9 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -103,7 +103,7 @@ Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { void DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { Common::DumpFile *f = new Common::DumpFile(); - if (!f->open(localPath)) { + if (!f->open(localPath, true)) { warning("DropboxStorage: unable to open file to download into"); if (callback) (*callback)(false); delete f; @@ -116,8 +116,8 @@ void DropboxStorage::download(Common::String remotePath, Common::String localPat void DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation //"" is root in Dropbox, not "/" - //listDirectory("", new Common::Callback >(this, &DropboxStorage::printFiles), true); - download("/remote/test.jpg", "local/test.jpg", 0); + //this must create all these directories: + download("/remote/test.jpg", "local/a/b/c/d/test.jpg", 0); } void DropboxStorage::info(StorageInfoCallback outerCallback) { -- cgit v1.2.3 From eda575a660543884b1a4addd21b676a67d2c2a31 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 26 May 2016 17:12:40 +0600 Subject: CLOUD: Add Requests id (Upgrading ConnectionManager step by step.) --- backends/cloud/dropbox/dropboxstorage.cpp | 18 +++++++++--------- backends/cloud/dropbox/dropboxstorage.h | 16 ++++++++-------- backends/cloud/onedrive/onedrivestorage.cpp | 4 ++-- backends/cloud/onedrive/onedrivestorage.h | 16 ++++++++-------- backends/cloud/storage.h | 26 ++++++++++++++++---------- 5 files changed, 43 insertions(+), 37 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index e5041466e9..9acbfc0428 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -84,8 +84,8 @@ void DropboxStorage::printFiles(Common::Array files) { debug("\t%s", files[i].name().c_str()); } -void DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { - ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); +int32 DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { + return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); } Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { @@ -101,30 +101,30 @@ Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { return request->execute(); } -void DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { +int32 DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { Common::DumpFile *f = new Common::DumpFile(); if (!f->open(localPath, true)) { warning("DropboxStorage: unable to open file to download into"); if (callback) (*callback)(false); delete f; - return; + return -1; } - ConnMan.addRequest(new DownloadRequest(callback, streamFile(remotePath), f)); + return ConnMan.addRequest(new DownloadRequest(callback, streamFile(remotePath), f)); } -void DropboxStorage::syncSaves(BoolCallback callback) { +int32 DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation //"" is root in Dropbox, not "/" //this must create all these directories: - download("/remote/test.jpg", "local/a/b/c/d/test.jpg", 0); + return download("/remote/test.jpg", "local/a/b/c/d/test.jpg", 0); } -void DropboxStorage::info(StorageInfoCallback outerCallback) { +int32 DropboxStorage::info(StorageInfoCallback outerCallback) { Common::BaseCallback<> *innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); - ConnMan.addRequest(request); + return ConnMan.addRequest(request); //that callback bridge wraps the outerCallback (passed in arguments from user) into innerCallback //so, when CurlJsonRequest is finished, it calls the innerCallback //innerCallback (which is DropboxStorage::infoInnerCallback in this case) processes the void *ptr diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 415a3fe5fb..6abd3d1d94 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -64,31 +64,31 @@ public: /** Public Cloud API comes down there. */ /** Returns Common::Array. */ - virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); + virtual int32 listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) {} //TODO + virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return -1; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::NetworkReadStream *streamFile(Common::String path); /** Calls the callback when finished. */ - virtual void download(Common::String remotePath, Common::String localPath, BoolCallback callback); + virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback); /** Calls the callback when finished. */ - virtual void remove(Common::String path, BoolCallback callback) {} //TODO + virtual int32 remove(Common::String path, BoolCallback callback) { return -1; } //TODO /** Calls the callback when finished. */ - virtual void syncSaves(BoolCallback callback); + virtual int32 syncSaves(BoolCallback callback); /** Calls the callback when finished. */ - virtual void createDirectory(Common::String path, BoolCallback callback) {} //TODO + virtual int32 createDirectory(Common::String path, BoolCallback callback) { return -1; } //TODO /** Calls the callback when finished. */ - virtual void touch(Common::String path, BoolCallback callback) {} //TODO + virtual int32 touch(Common::String path, BoolCallback callback) { return -1; } //TODO /** Returns the StorageInfo struct. */ - virtual void info(StorageInfoCallback callback); + virtual int32 info(StorageInfoCallback callback); /** This method is passed into info(). (Temporary) */ void infoMethodCallback(StorageInfo storageInfo); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 2f10841cc9..b0690be5b0 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -137,12 +137,12 @@ void OneDriveStorage::printJson(void *jsonPointer) { delete json; } -void OneDriveStorage::syncSaves(BoolCallback callback) { +int32 OneDriveStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation Common::BaseCallback<> *innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/"); request->addHeader("Authorization: bearer " + _token); - ConnMan.addRequest(request); + return ConnMan.addRequest(request); } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 28f37aee2c..4141771f65 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -74,31 +74,31 @@ public: /** Public Cloud API comes down there. */ /** Returns Common::Array. */ - virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) {} //TODO + virtual int32 listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) { return -1; } //TODO /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) {} //TODO + virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return -1; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::NetworkReadStream *streamFile(Common::String path) { return 0; } //TODO /** Calls the callback when finished. */ - virtual void download(Common::String remotePath, Common::String localPath, BoolCallback callback) {} //TODO + virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback) { return -1; } //TODO /** Calls the callback when finished. */ - virtual void remove(Common::String path, BoolCallback callback) {} //TODO + virtual int32 remove(Common::String path, BoolCallback callback) { return -1; } //TODO /** Calls the callback when finished. */ - virtual void syncSaves(BoolCallback callback); + virtual int32 syncSaves(BoolCallback callback); /** Calls the callback when finished. */ - virtual void createDirectory(Common::String path, BoolCallback callback) {} //TODO + virtual int32 createDirectory(Common::String path, BoolCallback callback) { return -1; } //TODO /** Calls the callback when finished. */ - virtual void touch(Common::String path, BoolCallback callback) {} //TODO + virtual int32 touch(Common::String path, BoolCallback callback) { return -1; } //TODO /** Returns the StorageInfo struct. */ - virtual void info(StorageInfoCallback callback) {} //TODO + virtual int32 info(StorageInfoCallback callback) { return -1; } //TODO /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index e38c6bedd9..394fc2c22d 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -57,34 +57,40 @@ public: virtual void saveConfig(Common::String keyPrefix) = 0; - /** Public Cloud API comes down there. */ + /** + * Public Cloud API comes down there. + * + * All Cloud API methods return int32 request id, which might be used to access + * request through ConnectionManager. All methods also accept a callback, which + * would be called, when request is complete. + */ /** Returns Common::Array. */ - virtual void listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; + virtual int32 listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; /** Calls the callback when finished. */ - virtual void upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) = 0; + virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) = 0; /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::NetworkReadStream *streamFile(Common::String path) = 0; + virtual Networking::NetworkReadStream *streamFile(Common::String path) = 0; //TODO: return int32 somehow /** Calls the callback when finished. */ - virtual void download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; + virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual void remove(Common::String path, BoolCallback callback) = 0; + virtual int32 remove(Common::String path, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual void syncSaves(BoolCallback callback) = 0; + virtual int32 syncSaves(BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual void createDirectory(Common::String path, BoolCallback callback) = 0; + virtual int32 createDirectory(Common::String path, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual void touch(Common::String path, BoolCallback callback) = 0; + virtual int32 touch(Common::String path, BoolCallback callback) = 0; /** Returns the StorageInfo struct. */ - virtual void info(StorageInfoCallback callback) = 0; + virtual int32 info(StorageInfoCallback callback) = 0; /** Returns whether saves sync process is running. */ virtual bool isSyncing() = 0; -- 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. --- backends/cloud/downloadrequest.cpp | 17 ++++++++++- backends/cloud/downloadrequest.h | 1 + .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 34 +++++++++++++++++----- .../cloud/dropbox/dropboxlistdirectoryrequest.h | 6 ++++ 4 files changed, 50 insertions(+), 8 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index e86b6552e9..a96c298fe8 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -21,6 +21,7 @@ */ #include "backends/cloud/downloadrequest.h" +#include "backends/networking/curl/connectionmanager.h" #include "common/debug.h" #include "common/textconsole.h" @@ -32,16 +33,19 @@ DownloadRequest::DownloadRequest(Storage::BoolCallback callback, Networking::Net bool DownloadRequest::handle() { if (!_remoteFileStream) { warning("DownloadRequest: no stream to read"); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; return true; } if (!_localFile) { warning("DownloadRequest: no file to write"); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; return true; } if (!_localFile->isOpen()) { warning("DownloadRequest: failed to open file to write"); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; return true; } @@ -52,7 +56,8 @@ bool DownloadRequest::handle() { if (readBytes != 0) if (_localFile->write(buf, readBytes) != readBytes) { warning("DownloadRequest: unable to write all received bytes into output file"); - if (_boolCallback) (*_boolCallback)(false); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_boolCallback) (*_boolCallback)(false); return true; } @@ -62,6 +67,7 @@ bool DownloadRequest::handle() { //TODO: do something about it actually } + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; if (_boolCallback) (*_boolCallback)(_remoteFileStream->httpResponseCode() == 200); _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() @@ -71,4 +77,13 @@ bool DownloadRequest::handle() { return false; } +void DownloadRequest::restart() { + //this request doesn't know anything about the _remoteFileStream it's reading + //thus, it can't restart it + warning("DownloadRequest: cannot be restarted"); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_boolCallback) (*_boolCallback)(false); + //TODO: fix that +} + } //end of namespace Cloud diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index b135b15f23..c1564100c2 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -40,6 +40,7 @@ public: virtual ~DownloadRequest() { delete _localFile; } virtual bool handle(); + virtual void restart(); }; } //end of namespace Cloud 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 diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 0c10512782..36070a2a32 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -31,18 +31,24 @@ namespace Cloud { namespace Dropbox { class DropboxListDirectoryRequest: public Networking::Request { + Common::String _requestedPath; + bool _requestedRecursive; + Storage::FileArrayCallback _filesCallback; Common::String _token; bool _complete; Common::Array _files; + int32 _requestId; void responseCallback(void *jsonPtr); + void startupWork(); public: DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); virtual ~DropboxListDirectoryRequest() { delete _filesCallback; } virtual bool handle(); + virtual void restart(); }; } //end of namespace Dropbox -- 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/downloadrequest.cpp | 6 ++-- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 11 ++++---- .../cloud/dropbox/dropboxlistdirectoryrequest.h | 2 +- backends/cloud/dropbox/dropboxstorage.cpp | 26 +++++++++--------- backends/cloud/dropbox/dropboxstorage.h | 4 +-- backends/cloud/onedrive/onedrivestorage.cpp | 32 +++++++++++----------- backends/cloud/onedrive/onedrivestorage.h | 8 +++--- backends/cloud/storage.h | 14 +++++++--- 8 files changed, 55 insertions(+), 48 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index a96c298fe8..6f777b7cb1 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -57,7 +57,7 @@ bool DownloadRequest::handle() { if (_localFile->write(buf, readBytes) != readBytes) { warning("DownloadRequest: unable to write all received bytes into output file"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(false); + if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); return true; } @@ -68,7 +68,7 @@ bool DownloadRequest::handle() { } ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(_remoteFileStream->httpResponseCode() == 200); + if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, _remoteFileStream->httpResponseCode() == 200)); _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() return true; @@ -82,7 +82,7 @@ void DownloadRequest::restart() { //thus, it can't restart it warning("DownloadRequest: cannot be restarted"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(false); + if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); //TODO: fix that } 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; diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 36070a2a32..58f3dc6113 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -40,7 +40,7 @@ class DropboxListDirectoryRequest: public Networking::Request { Common::Array _files; int32 _requestId; - void responseCallback(void *jsonPtr); + void responseCallback(Networking::RequestDataPair pair); void startupWork(); public: diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 9acbfc0428..02b033fced 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -38,8 +38,8 @@ namespace Dropbox { Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow -static void saveAccessTokenCallback(void *ptr) { - Common::JSONValue *json = (Common::JSONValue *)ptr; +static void saveAccessTokenCallback(Networking::RequestDataPair pair) { + Common::JSONValue *json = (Common::JSONValue *)pair.value; if (json) { debug("saveAccessTokenCallback:"); debug("%s", json->stringify(true).c_str()); @@ -105,7 +105,7 @@ int32 DropboxStorage::download(Common::String remotePath, Common::String localPa Common::DumpFile *f = new Common::DumpFile(); if (!f->open(localPath, true)) { warning("DropboxStorage: unable to open file to download into"); - if (callback) (*callback)(false); + if (callback) (*callback)(RequestBoolPair(-1, false)); delete f; return -1; } @@ -121,7 +121,7 @@ int32 DropboxStorage::syncSaves(BoolCallback callback) { } int32 DropboxStorage::info(StorageInfoCallback outerCallback) { - Common::BaseCallback<> *innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); + Networking::DataCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); return ConnMan.addRequest(request); @@ -131,8 +131,8 @@ int32 DropboxStorage::info(StorageInfoCallback outerCallback) { //and then calls the outerCallback (which wants to receive StorageInfo, not void *) } -void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, void *jsonPointer) { - Common::JSONValue *json = (Common::JSONValue *)jsonPointer; +void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestDataPair pair) { + Common::JSONValue *json = (Common::JSONValue *)pair.value; if (!json) { warning("NULL passed instead of JSON"); delete outerCallback; @@ -148,19 +148,19 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, void * Common::JSONObject quota = info.getVal("quota_info")->asObject(); uint32 quotaNormal = quota.getVal("normal")->asNumber(); uint32 quotaShared = quota.getVal("shared")->asNumber(); - uint32 quotaAllocated = quota.getVal("quota")->asNumber(); - (*outerCallback)(StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated)); + uint32 quotaAllocated = quota.getVal("quota")->asNumber(); + (*outerCallback)(RequestStorageInfoPair(-1, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); delete outerCallback; } delete json; } -void DropboxStorage::infoMethodCallback(StorageInfo storageInfo) { +void DropboxStorage::infoMethodCallback(RequestStorageInfoPair pair) { debug("\nStorage info:"); - debug("User name: %s", storageInfo.name().c_str()); - debug("Email: %s", storageInfo.email().c_str()); - debug("Disk usage: %u/%u", storageInfo.used(), storageInfo.available()); + debug("User name: %s", pair.value.name().c_str()); + debug("Email: %s", pair.value.email().c_str()); + debug("Disk usage: %u/%u", pair.value.used(), pair.value.available()); } DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { @@ -214,7 +214,7 @@ void DropboxStorage::authThroughConsole() { } void DropboxStorage::getAccessToken(Common::String code) { - Common::BaseCallback<> *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); + Networking::DataCallback callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 6abd3d1d94..4fe6109c17 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -40,7 +40,7 @@ class DropboxStorage: public Cloud::Storage { static void getAccessToken(Common::String code); /** Constructs StorageInfo based on JSON response from cloud. */ - void infoInnerCallback(StorageInfoCallback outerCallback, void *json); + void infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestDataPair json); void printFiles(Common::Array files); @@ -91,7 +91,7 @@ public: virtual int32 info(StorageInfoCallback callback); /** This method is passed into info(). (Temporary) */ - void infoMethodCallback(StorageInfo storageInfo); + void infoMethodCallback(RequestStorageInfoPair pair); /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index b0690be5b0..36b3e26f1b 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -42,7 +42,7 @@ OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String user _token(accessToken), _uid(userId), _refreshToken(refreshToken) {} OneDriveStorage::OneDriveStorage(Common::String code) { - getAccessToken(new Common::Callback(this, &OneDriveStorage::codeFlowComplete), code); + getAccessToken(new Common::Callback(this, &OneDriveStorage::codeFlowComplete), code); } OneDriveStorage::~OneDriveStorage() {} @@ -52,11 +52,11 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) if (!codeFlow && _refreshToken == "") { warning("OneDriveStorage: no refresh token available to get new access token."); - if (callback) (*callback)(false); + if (callback) (*callback)(RequestBoolPair(-1, false)); return; } - Common::BaseCallback<> *innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); + Networking::DataCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://login.live.com/oauth20_token.srf"); if (codeFlow) { request->addPostField("code=" + code); @@ -71,11 +71,11 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) ConnMan.addRequest(request); } -void OneDriveStorage::tokenRefreshed(BoolCallback callback, void *jsonPointer) { - Common::JSONValue *json = (Common::JSONValue *)jsonPointer; +void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::RequestDataPair pair) { + Common::JSONValue *json = (Common::JSONValue *)pair.value; if (!json) { warning("OneDriveStorage: got NULL instead of JSON"); - if (callback) (*callback)(false); + if (callback) (*callback)(RequestBoolPair(-1, false)); return; } @@ -83,19 +83,19 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, void *jsonPointer) { if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) { warning("Bad response, no token or user_id passed"); debug("%s", json->stringify().c_str()); - if (callback) (*callback)(false); + if (callback) (*callback)(RequestBoolPair(-1, false)); } else { _token = result.getVal("access_token")->asString(); _uid = result.getVal("user_id")->asString(); _refreshToken = result.getVal("refresh_token")->asString(); g_system->getCloudManager()->save(); //ask CloudManager to save our new refreshToken - if (callback) (*callback)(true); + if (callback) (*callback)(RequestBoolPair(-1, true)); } delete json; } -void OneDriveStorage::codeFlowComplete(bool success) { - if (!success) { +void OneDriveStorage::codeFlowComplete(RequestBoolPair pair) { + if (!pair.value) { warning("OneDriveStorage: failed to get access token through code flow"); return; } @@ -113,12 +113,12 @@ void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } -void OneDriveStorage::printJsonTokenReceived(bool success) { - if (success) syncSaves(0); //try again +void OneDriveStorage::printJsonTokenReceived(RequestBoolPair pair) { + if (pair.value) syncSaves(0); //try again } -void OneDriveStorage::printJson(void *jsonPointer) { - Common::JSONValue *json = (Common::JSONValue *)jsonPointer; +void OneDriveStorage::printJson(Networking::RequestDataPair pair) { + Common::JSONValue *json = (Common::JSONValue *)pair.value; if (!json) { warning("printJson: NULL"); return; @@ -128,7 +128,7 @@ void OneDriveStorage::printJson(void *jsonPointer) { if (result.contains("error")) { //Common::JSONObject error = result.getVal("error")->asObject(); debug("bad token, trying again..."); - getAccessToken(new Common::Callback(this, &OneDriveStorage::printJsonTokenReceived)); + getAccessToken(new Common::Callback(this, &OneDriveStorage::printJsonTokenReceived)); delete json; return; } @@ -139,7 +139,7 @@ void OneDriveStorage::printJson(void *jsonPointer) { int32 OneDriveStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation - Common::BaseCallback<> *innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); + Networking::DataCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/"); request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 4141771f65..3c92880750 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -49,11 +49,11 @@ class OneDriveStorage: public Cloud::Storage { * continue your work when new token is available. */ void getAccessToken(BoolCallback callback, Common::String code = ""); - void tokenRefreshed(BoolCallback callback, void *jsonPointer); - void codeFlowComplete(bool success); + void tokenRefreshed(BoolCallback callback, Networking::RequestDataPair pair); + void codeFlowComplete(RequestBoolPair pair); - void printJson(void *jsonPointer); - void printJsonTokenReceived(bool success); + void printJson(Networking::RequestDataPair pair); + void printJsonTokenReceived(RequestBoolPair pair); public: virtual ~OneDriveStorage(); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 394fc2c22d..325d57d02c 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -30,15 +30,21 @@ #include "backends/cloud/storagefile.h" #include "backends/cloud/storageinfo.h" #include "backends/networking/curl/networkreadstream.h" +#include namespace Cloud { class Storage { public: - typedef Common::BaseCallback< Common::Array > *FileArrayCallback; - typedef Common::BaseCallback *ReadStreamCallback; - typedef Common::BaseCallback *StorageInfoCallback; - typedef Common::BaseCallback *BoolCallback; + typedef Networking::RequestIdPair&> RequestFileArrayPair; + typedef Networking::RequestIdPair RequestReadStreamPair; + typedef Networking::RequestIdPair RequestStorageInfoPair; + typedef Networking::RequestIdPair RequestBoolPair; + + typedef Common::BaseCallback *FileArrayCallback; + typedef Common::BaseCallback *ReadStreamCallback; + typedef Common::BaseCallback *StorageInfoCallback; + typedef Common::BaseCallback *BoolCallback; Storage() {} virtual ~Storage() {} -- 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/downloadrequest.cpp | 15 ++++++--------- backends/cloud/downloadrequest.h | 2 +- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 6 ++---- backends/cloud/dropbox/dropboxlistdirectoryrequest.h | 2 +- 4 files changed, 10 insertions(+), 15 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 6f777b7cb1..756a904c74 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -30,23 +30,23 @@ namespace Cloud { DownloadRequest::DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream, Common::DumpFile *dumpFile): Request(0), _boolCallback(callback), _remoteFileStream(stream), _localFile(dumpFile) {} -bool DownloadRequest::handle() { +void DownloadRequest::handle() { if (!_remoteFileStream) { warning("DownloadRequest: no stream to read"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - return true; + return; } if (!_localFile) { warning("DownloadRequest: no file to write"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - return true; + return; } if (!_localFile->isOpen()) { warning("DownloadRequest: failed to open file to write"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - return true; + return; } const int kBufSize = 640 * 1024; //640 KB is enough to everyone?.. @@ -58,7 +58,7 @@ bool DownloadRequest::handle() { warning("DownloadRequest: unable to write all received bytes into output file"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); - return true; + return; } if (_remoteFileStream->eos()) { @@ -70,11 +70,8 @@ bool DownloadRequest::handle() { ConnMan.getRequestInfo(_id).state = Networking::FINISHED; if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, _remoteFileStream->httpResponseCode() == 200)); - _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() - return true; + _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() } - - return false; } void DownloadRequest::restart() { diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index c1564100c2..724cf19d89 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -39,7 +39,7 @@ public: DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream, Common::DumpFile *dumpFile); virtual ~DownloadRequest() { delete _localFile; } - virtual bool handle(); + virtual void handle(); virtual void restart(); }; 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() { diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 58f3dc6113..afa544de69 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -47,7 +47,7 @@ public: DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); virtual ~DropboxListDirectoryRequest() { delete _filesCallback; } - virtual bool handle(); + virtual void handle(); virtual void 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 ++++---- backends/cloud/dropbox/dropboxlistdirectoryrequest.h | 3 ++- backends/cloud/dropbox/dropboxstorage.cpp | 10 +++++----- backends/cloud/dropbox/dropboxstorage.h | 3 ++- backends/cloud/onedrive/onedrivestorage.cpp | 12 ++++++------ backends/cloud/onedrive/onedrivestorage.h | 5 +++-- 6 files changed, 22 insertions(+), 19 deletions(-) (limited to 'backends/cloud') 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"); diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index afa544de69..9a82ef7091 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -26,6 +26,7 @@ #include "backends/cloud/storage.h" #include "backends/networking/curl/request.h" #include "common/callback.h" +#include "backends/networking/curl/curljsonrequest.h" namespace Cloud { namespace Dropbox { @@ -40,7 +41,7 @@ class DropboxListDirectoryRequest: public Networking::Request { Common::Array _files; int32 _requestId; - void responseCallback(Networking::RequestDataPair pair); + void responseCallback(Networking::RequestJsonPair pair); void startupWork(); public: diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 02b033fced..47576d7cda 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -38,7 +38,7 @@ namespace Dropbox { Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow -static void saveAccessTokenCallback(Networking::RequestDataPair pair) { +static void saveAccessTokenCallback(Networking::RequestJsonPair pair) { Common::JSONValue *json = (Common::JSONValue *)pair.value; if (json) { debug("saveAccessTokenCallback:"); @@ -121,7 +121,7 @@ int32 DropboxStorage::syncSaves(BoolCallback callback) { } int32 DropboxStorage::info(StorageInfoCallback outerCallback) { - Networking::DataCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); return ConnMan.addRequest(request); @@ -131,8 +131,8 @@ int32 DropboxStorage::info(StorageInfoCallback outerCallback) { //and then calls the outerCallback (which wants to receive StorageInfo, not void *) } -void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestDataPair pair) { - Common::JSONValue *json = (Common::JSONValue *)pair.value; +void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestJsonPair pair) { + Common::JSONValue *json = pair.value; if (!json) { warning("NULL passed instead of JSON"); delete outerCallback; @@ -214,7 +214,7 @@ void DropboxStorage::authThroughConsole() { } void DropboxStorage::getAccessToken(Common::String code) { - Networking::DataCallback callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); + Networking::JsonCallback callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 4fe6109c17..4f1e6cd48a 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -25,6 +25,7 @@ #include "backends/cloud/storage.h" #include "common/callback.h" +#include "backends/networking/curl/curljsonrequest.h" namespace Cloud { namespace Dropbox { @@ -40,7 +41,7 @@ class DropboxStorage: public Cloud::Storage { static void getAccessToken(Common::String code); /** Constructs StorageInfo based on JSON response from cloud. */ - void infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestDataPair json); + void infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestJsonPair json); void printFiles(Common::Array files); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 36b3e26f1b..833ba8e558 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -56,7 +56,7 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) return; } - Networking::DataCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://login.live.com/oauth20_token.srf"); if (codeFlow) { request->addPostField("code=" + code); @@ -71,8 +71,8 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) ConnMan.addRequest(request); } -void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::RequestDataPair pair) { - Common::JSONValue *json = (Common::JSONValue *)pair.value; +void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::RequestJsonPair pair) { + Common::JSONValue *json = pair.value; if (!json) { warning("OneDriveStorage: got NULL instead of JSON"); if (callback) (*callback)(RequestBoolPair(-1, false)); @@ -117,8 +117,8 @@ void OneDriveStorage::printJsonTokenReceived(RequestBoolPair pair) { if (pair.value) syncSaves(0); //try again } -void OneDriveStorage::printJson(Networking::RequestDataPair pair) { - Common::JSONValue *json = (Common::JSONValue *)pair.value; +void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { + Common::JSONValue *json = pair.value; if (!json) { warning("printJson: NULL"); return; @@ -139,7 +139,7 @@ void OneDriveStorage::printJson(Networking::RequestDataPair pair) { int32 OneDriveStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation - Networking::DataCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); + Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/"); request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 3c92880750..1cb7017d64 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -25,6 +25,7 @@ #include "backends/cloud/storage.h" #include "common/callback.h" +#include "backends/networking/curl/curljsonrequest.h" namespace Cloud { namespace OneDrive { @@ -49,10 +50,10 @@ class OneDriveStorage: public Cloud::Storage { * continue your work when new token is available. */ void getAccessToken(BoolCallback callback, Common::String code = ""); - void tokenRefreshed(BoolCallback callback, Networking::RequestDataPair pair); + void tokenRefreshed(BoolCallback callback, Networking::RequestJsonPair pair); void codeFlowComplete(RequestBoolPair pair); - void printJson(Networking::RequestDataPair pair); + void printJson(Networking::RequestJsonPair pair); void printJsonTokenReceived(RequestBoolPair pair); public: virtual ~OneDriveStorage(); -- cgit v1.2.3 From 8f6bcdf55da97db98384c2a8cb9dcdf34232ac35 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 26 May 2016 21:40:01 +0600 Subject: CLOUD: Add OneDriveTokenRefresher OneDriveTokenRefresher is a CurlJsonRequest replacement for OneDriveStorage methods. It behaves very similarly, but checks received JSON before passing it to user. If it contains "error" key, it attempts to refresh the token through OneDriveStorage, and then restarts the original request, so user won't notice that there ever was an error. --- backends/cloud/onedrive/onedrivestorage.cpp | 16 +-- backends/cloud/onedrive/onedrivestorage.h | 15 ++- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 124 +++++++++++++++++++++ backends/cloud/onedrive/onedrivetokenrefresher.h | 61 ++++++++++ 4 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 backends/cloud/onedrive/onedrivetokenrefresher.cpp create mode 100644 backends/cloud/onedrive/onedrivetokenrefresher.h (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 833ba8e558..6f91cadd37 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -31,6 +31,7 @@ #include #include "common/system.h" #include "common/cloudmanager.h" +#include "onedrivetokenrefresher.h" namespace Cloud { namespace OneDrive { @@ -113,10 +114,6 @@ void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } -void OneDriveStorage::printJsonTokenReceived(RequestBoolPair pair) { - if (pair.value) syncSaves(0); //try again -} - void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { Common::JSONValue *json = pair.value; if (!json) { @@ -124,15 +121,6 @@ void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { return; } - Common::JSONObject result = json->asObject(); - if (result.contains("error")) { - //Common::JSONObject error = result.getVal("error")->asObject(); - debug("bad token, trying again..."); - getAccessToken(new Common::Callback(this, &OneDriveStorage::printJsonTokenReceived)); - delete json; - return; - } - debug("%s", json->stringify().c_str()); delete json; } @@ -140,7 +128,7 @@ void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { int32 OneDriveStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/"); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, "https://api.onedrive.com/v1.0/drives/"); request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); } diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 1cb7017d64..e120691a08 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -44,12 +44,6 @@ class OneDriveStorage: public Cloud::Storage { */ OneDriveStorage(Common::String code); - /** - * Gets new access_token. If passed is "", refresh_token is used. - * Use "" in order to refresh token and pass a callback, so you could - * continue your work when new token is available. - */ - void getAccessToken(BoolCallback callback, Common::String code = ""); void tokenRefreshed(BoolCallback callback, Networking::RequestJsonPair pair); void codeFlowComplete(RequestBoolPair pair); @@ -122,6 +116,15 @@ public: * Show message with OneDrive auth instructions. (Temporary) */ static void authThroughConsole(); + + /** + * Gets new access_token. If passed is "", refresh_token is used. + * Use "" in order to refresh token and pass a callback, so you could + * continue your work when new token is available. + */ + void getAccessToken(BoolCallback callback, Common::String code = ""); + + Common::String accessToken() { return _token; } }; } //end of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp new file mode 100644 index 0000000000..5e72717740 --- /dev/null +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -0,0 +1,124 @@ +/* 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. +* +*/ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/onedrive/onedrivetokenrefresher.h" +#include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/curljsonrequest.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/json.h" +#include + +namespace Cloud { +namespace OneDrive { + +OneDriveTokenRefresher::OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url): + CurlJsonRequest(0, url), + _parentStorage(parent), + _innerRequest( + new CurlJsonRequest( + new Common::Callback(this, &OneDriveTokenRefresher::innerRequestCallback), + url + ) + ), _jsonCallback(callback), _retryId(-1), _started(false) {} + +OneDriveTokenRefresher::~OneDriveTokenRefresher() {} + +void OneDriveTokenRefresher::innerRequestCallback(Networking::RequestJsonPair pair) { + if (!pair.value) { + //notify user of failure + warning("OneDriveTokenRefresher: got NULL instead of JSON"); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0)); + return; + } + + Common::JSONObject result = pair.value->asObject(); + if (result.contains("error")) { + //new token needed => request token & then retry original request + ConnMan.getRequestInfo(pair.id).state = Networking::PAUSED; + _retryId = pair.id; + delete pair.value; + _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); + return; + } + + //notify user of success + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, pair.value)); +} + +void OneDriveTokenRefresher::tokenRefreshed(Storage::RequestBoolPair pair) { + if (!pair.value) { + //failed to refresh token, notify user with NULL in original callback + warning("OneDriveTokenRefresher: failed to refresh token"); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0)); + return; + } + + //successfully received refreshed token, can restart the original request now + Networking::RequestInfo &info = ConnMan.getRequestInfo(_retryId); + info.state = Networking::RETRY; + info.retryInSeconds = 1; + + //update headers: first change header with token, then pass those to request + for (uint32 i = 0; i < _headers.size(); ++i) { + if (_headers[i].contains("Authorization: bearer ")) { + _headers[i] = "Authorization: bearer " + _parentStorage->accessToken(); + } + } + CurlJsonRequest *retryRequest = (CurlJsonRequest *)info.request; + if (retryRequest) retryRequest->setHeaders(_headers); +} + +void OneDriveTokenRefresher::handle() { + if (!_started) { + for (uint32 i = 0; i < _headers.size(); ++i) + _innerRequest->addHeader(_headers[i]); + _started = true; + ConnMan.addRequest(_innerRequest); + } +} + +void OneDriveTokenRefresher::restart() { + //can't restart as all headers were passed to _innerRequest which is probably dead now + warning("OneDriveTokenRefresher: cannot be restarted"); + ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0)); +} + +Networking::NetworkReadStream *OneDriveTokenRefresher::execute() { + if (!_started) { + for (uint32 i = 0; i < _headers.size(); ++i) + _innerRequest->addHeader(_headers[i]); + _started = true; + } else { + warning("OneDriveTokenRefresher: inner Request is already started"); + } + return _innerRequest->execute(); +} + +} //end of namespace OneDrive +} //end of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h new file mode 100644 index 0000000000..976851282e --- /dev/null +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -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_ONEDRIVETOKENREFRESHER_H +#define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVETOKENREFRESHER_H + +#include "backends/cloud/storage.h" +#include "common/callback.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace OneDrive { + +class OneDriveStorage; + +class OneDriveTokenRefresher: public Networking::CurlJsonRequest { + OneDriveStorage *_parentStorage; + Common::Array _headers; + Networking::CurlJsonRequest *_innerRequest; + Networking::JsonCallback _jsonCallback; + int32 _retryId; + bool _started; + + void innerRequestCallback(Networking::RequestJsonPair pair); + void tokenRefreshed(Storage::RequestBoolPair pair); +public: + OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url); + virtual ~OneDriveTokenRefresher(); + + virtual void handle(); + virtual void restart(); + + virtual void setHeaders(Common::Array &headers) { _headers = headers; } + virtual void addHeader(Common::String header) { _headers.push_back(header); } + virtual void addPostField(Common::String field) { _innerRequest->addPostField(field); } + virtual Networking::NetworkReadStream *execute(); +}; + +} //end of namespace OneDrive +} //end of namespace Cloud + +#endif -- cgit v1.2.3 From 24007c029b53a5f4502ee1c48c5244b8cf8099ce Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 26 May 2016 23:56:29 +0600 Subject: CLOUD: Add OneDriveStorage::download() Doesn't work when token is invalid, though. --- backends/cloud/onedrive/onedrivestorage.cpp | 43 +++++++++++++++++++++++++---- backends/cloud/onedrive/onedrivestorage.h | 6 ++-- 2 files changed, 40 insertions(+), 9 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 6f91cadd37..877a1d27d1 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -22,16 +22,17 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/cloud/onedrive/onedrivetokenrefresher.h" +#include "backends/cloud/downloadrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" +#include "common/cloudmanager.h" #include "common/config-manager.h" #include "common/debug.h" +#include "common/file.h" #include "common/json.h" -#include -#include #include "common/system.h" -#include "common/cloudmanager.h" -#include "onedrivetokenrefresher.h" +#include namespace Cloud { namespace OneDrive { @@ -125,12 +126,42 @@ void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { delete json; } +Networking::NetworkReadStream *OneDriveStorage::streamFile(Common::String path) { + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path + ":/content"; + //NOT USING OneDriveTokenRefresher, because it's CurlJsonRequest, which saves all contents in memory to parse as JSON + //we actually don't even need a token if the download is "pre-authenticated" (whatever it means) + //still, we'd have to know direct URL (might be found in Item's "@content.downloadUrl", received from the server) + Networking::CurlRequest *request = new Networking::CurlRequest(0, url.c_str()); + request->addHeader("Authorization: Bearer " + _token); + return request->execute(); +} + +int32 OneDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { + Common::DumpFile *f = new Common::DumpFile(); + if (!f->open(localPath, true)) { + warning("OneDriveStorage: unable to open file to download into"); + if (callback) (*callback)(RequestBoolPair(-1, false)); + delete f; + return -1; + } + + return ConnMan.addRequest(new DownloadRequest(callback, streamFile(remotePath), f)); +} + +void OneDriveStorage::fileDownloaded(RequestBoolPair pair) { + if (pair.value) debug("file downloaded!"); + else debug("download failed!"); +} + int32 OneDriveStorage::syncSaves(BoolCallback callback) { - //this is not the real syncSaves() implementation + //this is not the real syncSaves() implementation + /* Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); - Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, "https://api.onedrive.com/v1.0/drives/"); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, "https://api.onedrive.com/v1.0/drive/special/approot"); request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); + */ + return download("pic.jpg", "local/onedrive/2/doom.jpg", new Common::Callback(this, &OneDriveStorage::fileDownloaded)); } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index e120691a08..391cabe02a 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -48,7 +48,7 @@ class OneDriveStorage: public Cloud::Storage { void codeFlowComplete(RequestBoolPair pair); void printJson(Networking::RequestJsonPair pair); - void printJsonTokenReceived(RequestBoolPair pair); + void fileDownloaded(RequestBoolPair pair); public: virtual ~OneDriveStorage(); @@ -75,10 +75,10 @@ public: virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return -1; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::NetworkReadStream *streamFile(Common::String path) { return 0; } //TODO + virtual int32 streamFile(Common::String path); /** Calls the callback when finished. */ - virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback) { return -1; } //TODO + virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback); /** Calls the callback when finished. */ virtual int32 remove(Common::String path, BoolCallback callback) { return -1; } //TODO -- cgit v1.2.3 From 83b349a033d71e92e292d1f1da0578d557ec6411 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 01:09:10 +0600 Subject: CLOUD: Make OneDriveStorage::download() work fine Well, it takes two API calls instead of one now, but there are no problems with expired token because of it. This commit changes Storage::streamFile() to pass NetworkReadStream * through callback. --- backends/cloud/downloadrequest.cpp | 24 +++++++++++--- backends/cloud/downloadrequest.h | 3 +- backends/cloud/dropbox/dropboxstorage.cpp | 8 +++-- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/onedrive/onedrivestorage.cpp | 37 +++++++++++++++++----- backends/cloud/onedrive/onedrivestorage.h | 4 ++- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 2 +- backends/cloud/onedrive/onedrivetokenrefresher.h | 2 +- backends/cloud/storage.h | 4 +-- 9 files changed, 63 insertions(+), 23 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 756a904c74..661d6fd56b 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -27,25 +27,39 @@ namespace Cloud { -DownloadRequest::DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream, Common::DumpFile *dumpFile): - Request(0), _boolCallback(callback), _remoteFileStream(stream), _localFile(dumpFile) {} +DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callback, Common::String remoteFile, Common::DumpFile *dumpFile): + Request(0), _boolCallback(callback), _remoteFileStream(0), _localFile(dumpFile) { + storage->streamFile(remoteFile, new Common::Callback(this, &DownloadRequest::streamCallback)); +} -void DownloadRequest::handle() { - if (!_remoteFileStream) { - warning("DownloadRequest: no stream to read"); +void DownloadRequest::streamCallback(Storage::RequestReadStreamPair pair) { + if (!pair.value) { + warning("DownloadRequest: no ReadStream passed"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); return; } + _remoteFileStream = (Networking::NetworkReadStream *)pair.value; +} + +void DownloadRequest::handle() { if (!_localFile) { warning("DownloadRequest: no file to write"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); return; } if (!_localFile->isOpen()) { warning("DownloadRequest: failed to open file to write"); ConnMan.getRequestInfo(_id).state = Networking::FINISHED; + if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); + return; + } + + if (!_remoteFileStream) { + //waiting for callback return; } diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index 724cf19d89..181536beba 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -35,8 +35,9 @@ class DownloadRequest: public Networking::Request { Networking::NetworkReadStream *_remoteFileStream; Common::DumpFile *_localFile; + void streamCallback(Storage::RequestReadStreamPair pair); public: - DownloadRequest(Storage::BoolCallback callback, Networking::NetworkReadStream *stream, Common::DumpFile *dumpFile); + DownloadRequest(Storage *storage, Storage::BoolCallback callback, Common::String remoteFile, Common::DumpFile *dumpFile); virtual ~DownloadRequest() { delete _localFile; } virtual void handle(); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 47576d7cda..b5292c83c7 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -88,7 +88,7 @@ int32 DropboxStorage::listDirectory(Common::String path, FileArrayCallback outer return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); } -Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { +int32 DropboxStorage::streamFile(Common::String path, ReadStreamCallback callback) { Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("path", new Common::JSONValue(path)); Common::JSONValue value(jsonRequestParameters); @@ -98,7 +98,9 @@ Networking::NetworkReadStream *DropboxStorage::streamFile(Common::String path) { request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); request->addHeader("Content-Type: "); //required to be empty (as we do POST, it's usually app/form-url-encoded) - return request->execute(); + RequestReadStreamPair pair = request->execute(); + if (callback) (*callback)(pair); + return pair.id; } int32 DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { @@ -110,7 +112,7 @@ int32 DropboxStorage::download(Common::String remotePath, Common::String localPa return -1; } - return ConnMan.addRequest(new DownloadRequest(callback, streamFile(remotePath), f)); + return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); } int32 DropboxStorage::syncSaves(BoolCallback callback) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 4f1e6cd48a..dd082b25f1 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -71,7 +71,7 @@ public: virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return -1; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::NetworkReadStream *streamFile(Common::String path); + virtual int32 streamFile(Common::String path, ReadStreamCallback callback); /** Calls the callback when finished. */ virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 877a1d27d1..237557df59 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -126,14 +126,35 @@ void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { delete json; } -Networking::NetworkReadStream *OneDriveStorage::streamFile(Common::String path) { - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path + ":/content"; - //NOT USING OneDriveTokenRefresher, because it's CurlJsonRequest, which saves all contents in memory to parse as JSON - //we actually don't even need a token if the download is "pre-authenticated" (whatever it means) - //still, we'd have to know direct URL (might be found in Item's "@content.downloadUrl", received from the server) - Networking::CurlRequest *request = new Networking::CurlRequest(0, url.c_str()); +void OneDriveStorage::fileInfoCallback(ReadStreamCallback outerCallback, Networking::RequestJsonPair pair) { + if (!pair.value) { + warning("fileInfoCallback: NULL"); + if (outerCallback) (*outerCallback)(RequestReadStreamPair(pair.id, 0)); + return; + } + + Common::JSONObject result = pair.value->asObject(); + if (result.contains("@content.downloadUrl")) { + const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); + if (outerCallback) + (*outerCallback)(RequestReadStreamPair( + pair.id, + new Networking::NetworkReadStream(url, 0, "") + )); + } else { + warning("downloadUrl not found in passed JSON"); + debug("%s", pair.value->stringify().c_str()); + if (outerCallback) (*outerCallback)(RequestReadStreamPair(pair.id, 0)); + } + delete pair.value; +} + +int32 OneDriveStorage::streamFile(Common::String path, ReadStreamCallback outerCallback) { + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path + ":/"; + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _token); - return request->execute(); + return ConnMan.addRequest(request); } int32 OneDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { @@ -145,7 +166,7 @@ int32 OneDriveStorage::download(Common::String remotePath, Common::String localP return -1; } - return ConnMan.addRequest(new DownloadRequest(callback, streamFile(remotePath), f)); + return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); } void OneDriveStorage::fileDownloaded(RequestBoolPair pair) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 391cabe02a..be2bcdf04c 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -49,6 +49,8 @@ class OneDriveStorage: public Cloud::Storage { void printJson(Networking::RequestJsonPair pair); void fileDownloaded(RequestBoolPair pair); + + void fileInfoCallback(ReadStreamCallback outerCallback, Networking::RequestJsonPair pair); public: virtual ~OneDriveStorage(); @@ -75,7 +77,7 @@ public: virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return -1; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ - virtual int32 streamFile(Common::String path); + virtual int32 streamFile(Common::String path, ReadStreamCallback callback); /** Calls the callback when finished. */ virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback); diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 5e72717740..d3ec0cc668 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -109,7 +109,7 @@ void OneDriveTokenRefresher::restart() { if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0)); } -Networking::NetworkReadStream *OneDriveTokenRefresher::execute() { +Cloud::Storage::RequestReadStreamPair OneDriveTokenRefresher::execute() { if (!_started) { for (uint32 i = 0; i < _headers.size(); ++i) _innerRequest->addHeader(_headers[i]); diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h index 976851282e..58b7dcedb4 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.h +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -52,7 +52,7 @@ public: virtual void setHeaders(Common::Array &headers) { _headers = headers; } virtual void addHeader(Common::String header) { _headers.push_back(header); } virtual void addPostField(Common::String field) { _innerRequest->addPostField(field); } - virtual Networking::NetworkReadStream *execute(); + virtual Cloud::Storage::RequestReadStreamPair execute(); }; } //end of namespace OneDrive diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 325d57d02c..0114b46dee 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -37,7 +37,7 @@ namespace Cloud { class Storage { public: typedef Networking::RequestIdPair&> RequestFileArrayPair; - typedef Networking::RequestIdPair RequestReadStreamPair; + typedef Networking::RequestIdPair RequestReadStreamPair; typedef Networking::RequestIdPair RequestStorageInfoPair; typedef Networking::RequestIdPair RequestBoolPair; @@ -78,7 +78,7 @@ public: virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) = 0; /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::NetworkReadStream *streamFile(Common::String path) = 0; //TODO: return int32 somehow + virtual int32 streamFile(Common::String path, ReadStreamCallback callback) = 0; /** Calls the callback when finished. */ virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; -- 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. --- backends/cloud/downloadrequest.cpp | 31 ++++++++------- backends/cloud/downloadrequest.h | 7 +++- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 32 +++++++++------ .../cloud/dropbox/dropboxlistdirectoryrequest.h | 7 +++- backends/cloud/dropbox/dropboxstorage.cpp | 31 ++++++++------- backends/cloud/dropbox/dropboxstorage.h | 22 +++++------ backends/cloud/onedrive/onedrivestorage.cpp | 46 +++++++++++----------- backends/cloud/onedrive/onedrivestorage.h | 28 ++++++------- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 43 ++++++++++---------- backends/cloud/onedrive/onedrivetokenrefresher.h | 13 +++--- backends/cloud/storage.h | 46 +++++++++++----------- 11 files changed, 163 insertions(+), 143 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 661d6fd56b..c7f6f75346 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -29,14 +29,13 @@ namespace Cloud { DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callback, Common::String remoteFile, Common::DumpFile *dumpFile): Request(0), _boolCallback(callback), _remoteFileStream(0), _localFile(dumpFile) { - storage->streamFile(remoteFile, new Common::Callback(this, &DownloadRequest::streamCallback)); + storage->streamFile(remoteFile, new Common::Callback(this, &DownloadRequest::streamCallback)); } -void DownloadRequest::streamCallback(Storage::RequestReadStreamPair pair) { +void DownloadRequest::streamCallback(Networking::NetworkReadStreamResponse pair) { if (!pair.value) { warning("DownloadRequest: no ReadStream passed"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); + finish(); return; } @@ -46,15 +45,13 @@ void DownloadRequest::streamCallback(Storage::RequestReadStreamPair pair) { void DownloadRequest::handle() { if (!_localFile) { warning("DownloadRequest: no file to write"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); + finish(); return; } if (!_localFile->isOpen()) { warning("DownloadRequest: failed to open file to write"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); + finish(); return; } @@ -70,8 +67,7 @@ void DownloadRequest::handle() { if (readBytes != 0) if (_localFile->write(buf, readBytes) != readBytes) { warning("DownloadRequest: unable to write all received bytes into output file"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); + finish(); return; } @@ -81,8 +77,7 @@ void DownloadRequest::handle() { //TODO: do something about it actually } - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, _remoteFileStream->httpResponseCode() == 200)); + finishBool(_remoteFileStream->httpResponseCode() == 200); _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() } @@ -92,9 +87,17 @@ void DownloadRequest::restart() { //this request doesn't know anything about the _remoteFileStream it's reading //thus, it can't restart it warning("DownloadRequest: cannot be restarted"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_boolCallback) (*_boolCallback)(Storage::RequestBoolPair(_id, false)); + finish(); //TODO: fix that } +void DownloadRequest::finish() { + finishBool(false); +} + +void DownloadRequest::finishBool(bool success) { + Request::finish(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + } //end of namespace Cloud diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index 181536beba..4ea85760ae 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -26,7 +26,7 @@ #include "backends/networking/curl/request.h" #include "backends/networking/curl/networkreadstream.h" #include "backends/cloud/storage.h" -#include +#include "common/file.h" namespace Cloud { @@ -35,13 +35,16 @@ class DownloadRequest: public Networking::Request { Networking::NetworkReadStream *_remoteFileStream; Common::DumpFile *_localFile; - void streamCallback(Storage::RequestReadStreamPair pair); + void streamCallback(Networking::NetworkReadStreamResponse pair); + + void finishBool(bool success); public: DownloadRequest(Storage *storage, Storage::BoolCallback callback, Common::String remoteFile, Common::DumpFile *dumpFile); virtual ~DownloadRequest() { delete _localFile; } virtual void handle(); virtual void restart(); + virtual void finish(); }; } //end of namespace Cloud 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 diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 9a82ef7091..e2a9ebf3a4 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -39,17 +39,20 @@ class DropboxListDirectoryRequest: public Networking::Request { Common::String _token; bool _complete; Common::Array _files; - int32 _requestId; + Request *_innerRequest; - void responseCallback(Networking::RequestJsonPair pair); + void responseCallback(Networking::JsonResponse pair); void startupWork(); + void finishFiles(Common::Array &files); + public: DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); virtual ~DropboxListDirectoryRequest() { delete _filesCallback; } virtual void handle(); virtual void restart(); + virtual void finish(); }; } //end of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index b5292c83c7..a1a97e00dd 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -38,7 +38,7 @@ namespace Dropbox { Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow -static void saveAccessTokenCallback(Networking::RequestJsonPair pair) { +static void saveAccessTokenCallback(Networking::JsonResponse pair) { Common::JSONValue *json = (Common::JSONValue *)pair.value; if (json) { debug("saveAccessTokenCallback:"); @@ -55,6 +55,7 @@ static void saveAccessTokenCallback(Networking::RequestJsonPair pair) { ConfMan.set("storage1_access_token", result.getVal("access_token")->asString(), "cloud"); ConfMan.set("storage1_user_id", result.getVal("uid")->asString(), "cloud"); ConfMan.removeKey("dropbox_code", "cloud"); + ConfMan.flushToDisk(); debug("Now please restart ScummVM to apply the changes."); } @@ -84,11 +85,11 @@ void DropboxStorage::printFiles(Common::Array files) { debug("\t%s", files[i].name().c_str()); } -int32 DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { +Networking::Request *DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); } -int32 DropboxStorage::streamFile(Common::String path, ReadStreamCallback callback) { +Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) { Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("path", new Common::JSONValue(path)); Common::JSONValue value(jsonRequestParameters); @@ -98,32 +99,32 @@ int32 DropboxStorage::streamFile(Common::String path, ReadStreamCallback callbac request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); request->addHeader("Content-Type: "); //required to be empty (as we do POST, it's usually app/form-url-encoded) - RequestReadStreamPair pair = request->execute(); + Networking::NetworkReadStreamResponse pair = request->execute(); if (callback) (*callback)(pair); - return pair.id; + return pair.request; } -int32 DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { +Networking::Request *DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { Common::DumpFile *f = new Common::DumpFile(); if (!f->open(localPath, true)) { warning("DropboxStorage: unable to open file to download into"); - if (callback) (*callback)(RequestBoolPair(-1, false)); + if (callback) (*callback)(BoolResponse(nullptr, false)); delete f; - return -1; + return nullptr; } return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); } -int32 DropboxStorage::syncSaves(BoolCallback callback) { +Networking::Request *DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation //"" is root in Dropbox, not "/" //this must create all these directories: return download("/remote/test.jpg", "local/a/b/c/d/test.jpg", 0); } -int32 DropboxStorage::info(StorageInfoCallback outerCallback) { - Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); +Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) { + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); return ConnMan.addRequest(request); @@ -133,7 +134,7 @@ int32 DropboxStorage::info(StorageInfoCallback outerCallback) { //and then calls the outerCallback (which wants to receive StorageInfo, not void *) } -void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestJsonPair pair) { +void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse pair) { Common::JSONValue *json = pair.value; if (!json) { warning("NULL passed instead of JSON"); @@ -151,14 +152,14 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ uint32 quotaNormal = quota.getVal("normal")->asNumber(); uint32 quotaShared = quota.getVal("shared")->asNumber(); uint32 quotaAllocated = quota.getVal("quota")->asNumber(); - (*outerCallback)(RequestStorageInfoPair(-1, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); + (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); delete outerCallback; } delete json; } -void DropboxStorage::infoMethodCallback(RequestStorageInfoPair pair) { +void DropboxStorage::infoMethodCallback(StorageInfoResponse pair) { debug("\nStorage info:"); debug("User name: %s", pair.value.name().c_str()); debug("Email: %s", pair.value.email().c_str()); @@ -216,7 +217,7 @@ void DropboxStorage::authThroughConsole() { } void DropboxStorage::getAccessToken(Common::String code) { - Networking::JsonCallback callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); + Networking::JsonCallback callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index dd082b25f1..f95d0c9812 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -41,7 +41,7 @@ class DropboxStorage: public Cloud::Storage { static void getAccessToken(Common::String code); /** Constructs StorageInfo based on JSON response from cloud. */ - void infoInnerCallback(StorageInfoCallback outerCallback, Networking::RequestJsonPair json); + void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); void printFiles(Common::Array files); @@ -65,34 +65,34 @@ public: /** Public Cloud API comes down there. */ /** Returns Common::Array. */ - virtual int32 listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); + virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); /** Calls the callback when finished. */ - virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return nullptr; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ - virtual int32 streamFile(Common::String path, ReadStreamCallback callback); + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback); /** Calls the callback when finished. */ - virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback); + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback); /** Calls the callback when finished. */ - virtual int32 remove(Common::String path, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *remove(Common::String path, BoolCallback callback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual int32 syncSaves(BoolCallback callback); + virtual Networking::Request *syncSaves(BoolCallback callback); /** Calls the callback when finished. */ - virtual int32 createDirectory(Common::String path, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual int32 touch(Common::String path, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *touch(Common::String path, BoolCallback callback) { return nullptr; } //TODO /** Returns the StorageInfo struct. */ - virtual int32 info(StorageInfoCallback callback); + virtual Networking::Request *info(StorageInfoCallback callback); /** This method is passed into info(). (Temporary) */ - void infoMethodCallback(RequestStorageInfoPair pair); + void infoMethodCallback(StorageInfoResponse pair); /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 237557df59..e181fecabb 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -44,7 +44,7 @@ OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String user _token(accessToken), _uid(userId), _refreshToken(refreshToken) {} OneDriveStorage::OneDriveStorage(Common::String code) { - getAccessToken(new Common::Callback(this, &OneDriveStorage::codeFlowComplete), code); + getAccessToken(new Common::Callback(this, &OneDriveStorage::codeFlowComplete), code); } OneDriveStorage::~OneDriveStorage() {} @@ -54,11 +54,11 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) if (!codeFlow && _refreshToken == "") { warning("OneDriveStorage: no refresh token available to get new access token."); - if (callback) (*callback)(RequestBoolPair(-1, false)); + if (callback) (*callback)(BoolResponse(nullptr, false)); return; } - Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://login.live.com/oauth20_token.srf"); if (codeFlow) { request->addPostField("code=" + code); @@ -73,11 +73,11 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) ConnMan.addRequest(request); } -void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::RequestJsonPair pair) { +void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse pair) { Common::JSONValue *json = pair.value; if (!json) { warning("OneDriveStorage: got NULL instead of JSON"); - if (callback) (*callback)(RequestBoolPair(-1, false)); + if (callback) (*callback)(BoolResponse(nullptr, false)); return; } @@ -85,18 +85,18 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::RequestJ if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) { warning("Bad response, no token or user_id passed"); debug("%s", json->stringify().c_str()); - if (callback) (*callback)(RequestBoolPair(-1, false)); + if (callback) (*callback)(BoolResponse(nullptr, false)); } else { _token = result.getVal("access_token")->asString(); _uid = result.getVal("user_id")->asString(); _refreshToken = result.getVal("refresh_token")->asString(); g_system->getCloudManager()->save(); //ask CloudManager to save our new refreshToken - if (callback) (*callback)(RequestBoolPair(-1, true)); + if (callback) (*callback)(BoolResponse(nullptr, true)); } delete json; } -void OneDriveStorage::codeFlowComplete(RequestBoolPair pair) { +void OneDriveStorage::codeFlowComplete(BoolResponse pair) { if (!pair.value) { warning("OneDriveStorage: failed to get access token through code flow"); return; @@ -115,7 +115,7 @@ void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } -void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { +void OneDriveStorage::printJson(Networking::JsonResponse pair) { Common::JSONValue *json = pair.value; if (!json) { warning("printJson: NULL"); @@ -126,10 +126,10 @@ void OneDriveStorage::printJson(Networking::RequestJsonPair pair) { delete json; } -void OneDriveStorage::fileInfoCallback(ReadStreamCallback outerCallback, Networking::RequestJsonPair pair) { +void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse pair) { if (!pair.value) { warning("fileInfoCallback: NULL"); - if (outerCallback) (*outerCallback)(RequestReadStreamPair(pair.id, 0)); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(pair.request, 0)); return; } @@ -137,44 +137,44 @@ void OneDriveStorage::fileInfoCallback(ReadStreamCallback outerCallback, Network if (result.contains("@content.downloadUrl")) { const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); if (outerCallback) - (*outerCallback)(RequestReadStreamPair( - pair.id, + (*outerCallback)(Networking::NetworkReadStreamResponse( + pair.request, new Networking::NetworkReadStream(url, 0, "") )); } else { warning("downloadUrl not found in passed JSON"); debug("%s", pair.value->stringify().c_str()); - if (outerCallback) (*outerCallback)(RequestReadStreamPair(pair.id, 0)); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(pair.request, 0)); } delete pair.value; } -int32 OneDriveStorage::streamFile(Common::String path, ReadStreamCallback outerCallback) { - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path + ":/"; - Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); +Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback) { + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path; + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _token); return ConnMan.addRequest(request); } -int32 OneDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { +Networking::Request *OneDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { Common::DumpFile *f = new Common::DumpFile(); if (!f->open(localPath, true)) { warning("OneDriveStorage: unable to open file to download into"); - if (callback) (*callback)(RequestBoolPair(-1, false)); + if (callback) (*callback)(BoolResponse(nullptr, false)); delete f; - return -1; + return nullptr; } return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); } -void OneDriveStorage::fileDownloaded(RequestBoolPair pair) { +void OneDriveStorage::fileDownloaded(BoolResponse pair) { if (pair.value) debug("file downloaded!"); else debug("download failed!"); } -int32 OneDriveStorage::syncSaves(BoolCallback callback) { +Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation /* Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); @@ -182,7 +182,7 @@ int32 OneDriveStorage::syncSaves(BoolCallback callback) { request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); */ - return download("pic.jpg", "local/onedrive/2/doom.jpg", new Common::Callback(this, &OneDriveStorage::fileDownloaded)); + return download("pic.jpg", "local/onedrive/2/doom.jpg", new Common::Callback(this, &OneDriveStorage::fileDownloaded)); } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index be2bcdf04c..858af6c9bf 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -44,13 +44,13 @@ class OneDriveStorage: public Cloud::Storage { */ OneDriveStorage(Common::String code); - void tokenRefreshed(BoolCallback callback, Networking::RequestJsonPair pair); - void codeFlowComplete(RequestBoolPair pair); + void tokenRefreshed(BoolCallback callback, Networking::JsonResponse pair); + void codeFlowComplete(BoolResponse pair); - void printJson(Networking::RequestJsonPair pair); - void fileDownloaded(RequestBoolPair pair); + void printJson(Networking::JsonResponse pair); + void fileDownloaded(BoolResponse pair); - void fileInfoCallback(ReadStreamCallback outerCallback, Networking::RequestJsonPair pair); + void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse pair); public: virtual ~OneDriveStorage(); @@ -71,31 +71,31 @@ public: /** Public Cloud API comes down there. */ /** Returns Common::Array. */ - virtual int32 listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) { return -1; } //TODO + virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) { return nullptr; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ - virtual int32 streamFile(Common::String path, ReadStreamCallback callback); + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback); /** Calls the callback when finished. */ - virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback); + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback); /** Calls the callback when finished. */ - virtual int32 remove(Common::String path, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *remove(Common::String path, BoolCallback callback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual int32 syncSaves(BoolCallback callback); + virtual Networking::Request *syncSaves(BoolCallback callback); /** Calls the callback when finished. */ - virtual int32 createDirectory(Common::String path, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual int32 touch(Common::String path, BoolCallback callback) { return -1; } //TODO + virtual Networking::Request *touch(Common::String path, BoolCallback callback) { return nullptr; } //TODO /** Returns the StorageInfo struct. */ - virtual int32 info(StorageInfoCallback callback) { return -1; } //TODO + virtual Networking::Request *info(StorageInfoCallback callback) { return nullptr; } //TODO /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index d3ec0cc668..6943d89297 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -38,50 +38,45 @@ OneDriveTokenRefresher::OneDriveTokenRefresher(OneDriveStorage *parent, Networki _parentStorage(parent), _innerRequest( new CurlJsonRequest( - new Common::Callback(this, &OneDriveTokenRefresher::innerRequestCallback), + new Common::Callback(this, &OneDriveTokenRefresher::innerRequestCallback), url ) - ), _jsonCallback(callback), _retryId(-1), _started(false) {} + ), _jsonCallback(callback), _retryRequest(nullptr), _started(false) {} OneDriveTokenRefresher::~OneDriveTokenRefresher() {} -void OneDriveTokenRefresher::innerRequestCallback(Networking::RequestJsonPair pair) { +void OneDriveTokenRefresher::innerRequestCallback(Networking::JsonResponse pair) { if (!pair.value) { //notify user of failure warning("OneDriveTokenRefresher: got NULL instead of JSON"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0)); + finish(); return; } Common::JSONObject result = pair.value->asObject(); if (result.contains("error")) { //new token needed => request token & then retry original request - ConnMan.getRequestInfo(pair.id).state = Networking::PAUSED; - _retryId = pair.id; + if (pair.request) pair.request->pause(); + _retryRequest = pair.request; delete pair.value; - _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); + _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); return; } //notify user of success - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, pair.value)); + finishJson(pair.value); } -void OneDriveTokenRefresher::tokenRefreshed(Storage::RequestBoolPair pair) { +void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse pair) { if (!pair.value) { //failed to refresh token, notify user with NULL in original callback warning("OneDriveTokenRefresher: failed to refresh token"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0)); + finish(); return; } //successfully received refreshed token, can restart the original request now - Networking::RequestInfo &info = ConnMan.getRequestInfo(_retryId); - info.state = Networking::RETRY; - info.retryInSeconds = 1; + if (_retryRequest) _retryRequest->retry(1); //update headers: first change header with token, then pass those to request for (uint32 i = 0; i < _headers.size(); ++i) { @@ -89,7 +84,7 @@ void OneDriveTokenRefresher::tokenRefreshed(Storage::RequestBoolPair pair) { _headers[i] = "Authorization: bearer " + _parentStorage->accessToken(); } } - CurlJsonRequest *retryRequest = (CurlJsonRequest *)info.request; + CurlJsonRequest *retryRequest = (CurlJsonRequest *)_retryRequest; if (retryRequest) retryRequest->setHeaders(_headers); } @@ -105,11 +100,19 @@ void OneDriveTokenRefresher::handle() { void OneDriveTokenRefresher::restart() { //can't restart as all headers were passed to _innerRequest which is probably dead now warning("OneDriveTokenRefresher: cannot be restarted"); - ConnMan.getRequestInfo(_id).state = Networking::FINISHED; - if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0)); + finish(); } -Cloud::Storage::RequestReadStreamPair OneDriveTokenRefresher::execute() { +void OneDriveTokenRefresher::finish() { + finishJson(0); +} + +void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { + Request::finish(); + if (_jsonCallback) (*_jsonCallback)(Networking::JsonResponse(this, json)); +} + +Networking::NetworkReadStreamResponse OneDriveTokenRefresher::execute() { if (!_started) { for (uint32 i = 0; i < _headers.size(); ++i) _innerRequest->addHeader(_headers[i]); diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h index 58b7dcedb4..c09879feed 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.h +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -35,24 +35,27 @@ class OneDriveStorage; class OneDriveTokenRefresher: public Networking::CurlJsonRequest { OneDriveStorage *_parentStorage; Common::Array _headers; - Networking::CurlJsonRequest *_innerRequest; + CurlJsonRequest *_innerRequest; Networking::JsonCallback _jsonCallback; - int32 _retryId; + Request *_retryRequest; bool _started; - void innerRequestCallback(Networking::RequestJsonPair pair); - void tokenRefreshed(Storage::RequestBoolPair pair); + void innerRequestCallback(Networking::JsonResponse pair); + void tokenRefreshed(Storage::BoolResponse pair); + + virtual void finishJson(Common::JSONValue *json); public: OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url); virtual ~OneDriveTokenRefresher(); virtual void handle(); virtual void restart(); + virtual void finish(); virtual void setHeaders(Common::Array &headers) { _headers = headers; } virtual void addHeader(Common::String header) { _headers.push_back(header); } virtual void addPostField(Common::String field) { _innerRequest->addPostField(field); } - virtual Cloud::Storage::RequestReadStreamPair execute(); + virtual Networking::NetworkReadStreamResponse execute(); }; } //end of namespace OneDrive diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 0114b46dee..8ae5308a1c 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -23,28 +23,26 @@ #ifndef BACKENDS_CLOUD_STORAGE_H #define BACKENDS_CLOUD_STORAGE_H +#include "backends/cloud/storagefile.h" +#include "backends/cloud/storageinfo.h" +#include "backends/networking/curl/request.h" +#include "backends/networking/curl/curlrequest.h" #include "common/array.h" #include "common/stream.h" #include "common/str.h" #include "common/callback.h" -#include "backends/cloud/storagefile.h" -#include "backends/cloud/storageinfo.h" -#include "backends/networking/curl/networkreadstream.h" -#include namespace Cloud { class Storage { public: - typedef Networking::RequestIdPair&> RequestFileArrayPair; - typedef Networking::RequestIdPair RequestReadStreamPair; - typedef Networking::RequestIdPair RequestStorageInfoPair; - typedef Networking::RequestIdPair RequestBoolPair; + typedef Networking::Response&> FileArrayResponse; + typedef Networking::Response StorageInfoResponse; + typedef Networking::Response BoolResponse; - typedef Common::BaseCallback *FileArrayCallback; - typedef Common::BaseCallback *ReadStreamCallback; - typedef Common::BaseCallback *StorageInfoCallback; - typedef Common::BaseCallback *BoolCallback; + typedef Common::BaseCallback *FileArrayCallback; + typedef Common::BaseCallback *StorageInfoCallback; + typedef Common::BaseCallback *BoolCallback; Storage() {} virtual ~Storage() {} @@ -66,37 +64,37 @@ public: /** * Public Cloud API comes down there. * - * All Cloud API methods return int32 request id, which might be used to access - * request through ConnectionManager. All methods also accept a callback, which - * would be called, when request is complete. + * All Cloud API methods return Networking::Request *, which + * might be used to control request. All methods also accept + * a callback, which is called, when request is complete. */ /** Returns Common::Array. */ - virtual int32 listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; + virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; /** Calls the callback when finished. */ - virtual int32 upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) = 0; + virtual Networking::Request *upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) = 0; /** Returns pointer to Networking::NetworkReadStream. */ - virtual int32 streamFile(Common::String path, ReadStreamCallback callback) = 0; + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) = 0; /** Calls the callback when finished. */ - virtual int32 download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual int32 remove(Common::String path, BoolCallback callback) = 0; + virtual Networking::Request *remove(Common::String path, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual int32 syncSaves(BoolCallback callback) = 0; + virtual Networking::Request *syncSaves(BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual int32 createDirectory(Common::String path, BoolCallback callback) = 0; + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback) = 0; /** Calls the callback when finished. */ - virtual int32 touch(Common::String path, BoolCallback callback) = 0; + virtual Networking::Request *touch(Common::String path, BoolCallback callback) = 0; /** Returns the StorageInfo struct. */ - virtual int32 info(StorageInfoCallback callback) = 0; + virtual Networking::Request *info(StorageInfoCallback callback) = 0; /** Returns whether saves sync process is running. */ virtual bool isSyncing() = 0; -- cgit v1.2.3 From 1348befe297d32de9bf40f89f37bcbae2c91d81f Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 17:50:27 +0600 Subject: CLOUD: Add access to CurlRequest's Stream One can access CurlRequest's NetworkReadStream in order to find out HTTP response code or some other Stream-related data. OneDriveTokenRefresher uses it to print some info on that 404 error I'm trying to troubleshoot. --- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 6943d89297..6620c23dc6 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -25,6 +25,7 @@ #include "backends/cloud/onedrive/onedrivestorage.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" +#include "backends/networking/curl/networkreadstream.h" #include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" @@ -56,6 +57,17 @@ void OneDriveTokenRefresher::innerRequestCallback(Networking::JsonResponse pair) Common::JSONObject result = pair.value->asObject(); if (result.contains("error")) { //new token needed => request token & then retry original request + CurlJsonRequest *streamRequest = (CurlJsonRequest *)pair.request; + if (streamRequest) { + const Networking::NetworkReadStream *stream = streamRequest->getNetworkReadStream(); + if (stream) { + debug("code %ld", stream->httpResponseCode()); + } + } + + Common::JSONObject error = result.getVal("error")->asObject(); + debug("code = %s", error.getVal("code")->asString().c_str()); + debug("message = %s", error.getVal("message")->asString().c_str()); if (pair.request) pair.request->pause(); _retryRequest = pair.request; delete pair.value; -- cgit v1.2.3 From dcbaeb57c4cbe58d17fd46b52fd23ae154458398 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 18:56:02 +0600 Subject: CLOUD: Fix OneDriveTokenRefresher Failed to update token in header when "Bearer" was used instead of "bearer". --- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 6620c23dc6..4be034b363 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -92,7 +92,7 @@ void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse pair) { //update headers: first change header with token, then pass those to request for (uint32 i = 0; i < _headers.size(); ++i) { - if (_headers[i].contains("Authorization: bearer ")) { + if (_headers[i].contains("Authorization")) { _headers[i] = "Authorization: bearer " + _parentStorage->accessToken(); } } -- cgit v1.2.3 From 6c01edc57a221e5c376d23f12bb2f090c73c4ffd Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 19:32:35 +0600 Subject: CLOUD: Simplify OneDriveTokenRefresher It now just extends CurlJsonRequest, not wraps one. --- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 110 +++++++-------------- backends/cloud/onedrive/onedrivetokenrefresher.h | 22 ++--- 2 files changed, 41 insertions(+), 91 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 4be034b363..94214834b0 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -23,10 +23,7 @@ #include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/onedrive/onedrivestorage.h" -#include "backends/networking/curl/connectionmanager.h" -#include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" -#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include @@ -35,50 +32,10 @@ namespace Cloud { namespace OneDrive { OneDriveTokenRefresher::OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url): - CurlJsonRequest(0, url), - _parentStorage(parent), - _innerRequest( - new CurlJsonRequest( - new Common::Callback(this, &OneDriveTokenRefresher::innerRequestCallback), - url - ) - ), _jsonCallback(callback), _retryRequest(nullptr), _started(false) {} + CurlJsonRequest(callback, url), _parentStorage(parent) {} OneDriveTokenRefresher::~OneDriveTokenRefresher() {} -void OneDriveTokenRefresher::innerRequestCallback(Networking::JsonResponse pair) { - if (!pair.value) { - //notify user of failure - warning("OneDriveTokenRefresher: got NULL instead of JSON"); - finish(); - return; - } - - Common::JSONObject result = pair.value->asObject(); - if (result.contains("error")) { - //new token needed => request token & then retry original request - CurlJsonRequest *streamRequest = (CurlJsonRequest *)pair.request; - if (streamRequest) { - const Networking::NetworkReadStream *stream = streamRequest->getNetworkReadStream(); - if (stream) { - debug("code %ld", stream->httpResponseCode()); - } - } - - Common::JSONObject error = result.getVal("error")->asObject(); - debug("code = %s", error.getVal("code")->asString().c_str()); - debug("message = %s", error.getVal("message")->asString().c_str()); - if (pair.request) pair.request->pause(); - _retryRequest = pair.request; - delete pair.value; - _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); - return; - } - - //notify user of success - finishJson(pair.value); -} - void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse pair) { if (!pair.value) { //failed to refresh token, notify user with NULL in original callback @@ -87,53 +44,54 @@ void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse pair) { return; } - //successfully received refreshed token, can restart the original request now - if (_retryRequest) _retryRequest->retry(1); - //update headers: first change header with token, then pass those to request for (uint32 i = 0; i < _headers.size(); ++i) { if (_headers[i].contains("Authorization")) { _headers[i] = "Authorization: bearer " + _parentStorage->accessToken(); } } - CurlJsonRequest *retryRequest = (CurlJsonRequest *)_retryRequest; - if (retryRequest) retryRequest->setHeaders(_headers); + setHeaders(_headers); + + //successfully received refreshed token, can restart the original request now + retry(0); } -void OneDriveTokenRefresher::handle() { - if (!_started) { - for (uint32 i = 0; i < _headers.size(); ++i) - _innerRequest->addHeader(_headers[i]); - _started = true; - ConnMan.addRequest(_innerRequest); +void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { + if (!json) { + //notify user of failure + warning("OneDriveTokenRefresher: got NULL instead of JSON"); + CurlJsonRequest::finish(); + return; } -} -void OneDriveTokenRefresher::restart() { - //can't restart as all headers were passed to _innerRequest which is probably dead now - warning("OneDriveTokenRefresher: cannot be restarted"); - finish(); -} + Common::JSONObject result = json->asObject(); + if (result.contains("error")) { + //new token needed => request token & then retry original request + if (_stream) { + debug("code %ld", _stream->httpResponseCode()); + } -void OneDriveTokenRefresher::finish() { - finishJson(0); -} + Common::JSONObject error = result.getVal("error")->asObject(); + debug("code = %s", error.getVal("code")->asString().c_str()); + debug("message = %s", error.getVal("message")->asString().c_str()); + pause(); + delete json; + _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); + return; + } -void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { - Request::finish(); - if (_jsonCallback) (*_jsonCallback)(Networking::JsonResponse(this, json)); + //notify user of success + CurlJsonRequest::finishJson(json); } -Networking::NetworkReadStreamResponse OneDriveTokenRefresher::execute() { - if (!_started) { - for (uint32 i = 0; i < _headers.size(); ++i) - _innerRequest->addHeader(_headers[i]); - _started = true; - } else { - warning("OneDriveTokenRefresher: inner Request is already started"); - } - return _innerRequest->execute(); +void OneDriveTokenRefresher::setHeaders(Common::Array &headers) { + _headers = headers; + curl_slist_free_all(_headersList); + _headersList = 0; + for (uint32 i = 0; i < headers.size(); ++i) + CurlJsonRequest::addHeader(headers[i]); } + } //end of namespace OneDrive } //end of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h index c09879feed..08212bf6f5 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.h +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -24,7 +24,6 @@ #define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVETOKENREFRESHER_H #include "backends/cloud/storage.h" -#include "common/callback.h" #include "backends/networking/curl/curljsonrequest.h" namespace Cloud { @@ -34,13 +33,8 @@ class OneDriveStorage; class OneDriveTokenRefresher: public Networking::CurlJsonRequest { OneDriveStorage *_parentStorage; - Common::Array _headers; - CurlJsonRequest *_innerRequest; - Networking::JsonCallback _jsonCallback; - Request *_retryRequest; - bool _started; - - void innerRequestCallback(Networking::JsonResponse pair); + Common::Array _headers; + void tokenRefreshed(Storage::BoolResponse pair); virtual void finishJson(Common::JSONValue *json); @@ -48,14 +42,12 @@ public: OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url); virtual ~OneDriveTokenRefresher(); - virtual void handle(); - virtual void restart(); - virtual void finish(); + virtual void setHeaders(Common::Array &headers); - virtual void setHeaders(Common::Array &headers) { _headers = headers; } - virtual void addHeader(Common::String header) { _headers.push_back(header); } - virtual void addPostField(Common::String field) { _innerRequest->addPostField(field); } - virtual Networking::NetworkReadStreamResponse execute(); + virtual void addHeader(Common::String header) { + _headers.push_back(header); + CurlJsonRequest::addHeader(header); + } }; } //end of namespace OneDrive -- cgit v1.2.3 From 0ef1cda1724e973c36c76e07763f681cb14bd597 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 20:59:40 +0600 Subject: CLOUD: Add FolderDownloadRequest Uses Storage's listDirectory() and download() methods to download contents. --- backends/cloud/dropbox/dropboxstorage.cpp | 15 +++- backends/cloud/dropbox/dropboxstorage.h | 5 +- backends/cloud/folderdownloadrequest.cpp | 111 ++++++++++++++++++++++++++++++ backends/cloud/folderdownloadrequest.h | 59 ++++++++++++++++ backends/cloud/storagefile.cpp | 8 +++ backends/cloud/storagefile.h | 1 + 6 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 backends/cloud/folderdownloadrequest.cpp create mode 100644 backends/cloud/folderdownloadrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index a1a97e00dd..379d7bb611 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -24,6 +24,7 @@ #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/dropbox/dropboxlistdirectoryrequest.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" @@ -79,8 +80,9 @@ void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); } -void DropboxStorage::printFiles(Common::Array files) { +void DropboxStorage::printFiles(FileArrayResponse pair) { debug("files:"); + Common::Array &files = pair.value; for (uint32 i = 0; i < files.size(); ++i) debug("\t%s", files[i].name().c_str()); } @@ -116,11 +118,20 @@ Networking::Request *DropboxStorage::download(Common::String remotePath, Common: return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); } +Networking::Request *DropboxStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive) { + return ConnMan.addRequest(new FolderDownloadRequest(this, callback, remotePath, localPath, recursive)); +} + Networking::Request *DropboxStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation //"" 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 download("/remote/test.jpg", "local/a/b/c/d/test.jpg", 0); + return downloadFolder( + "/not_flat", "local/not_flat_1_level/", + new Common::Callback(this, &DropboxStorage::printFiles), + false + ); } Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index f95d0c9812..19f2f9cdd4 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -43,7 +43,7 @@ class DropboxStorage: public Cloud::Storage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); - void printFiles(Common::Array files); + void printFiles(FileArrayResponse pair); public: virtual ~DropboxStorage(); @@ -76,6 +76,9 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback); + /** Returns Common::Array with list of files, which were not downloaded. */ + Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false); + /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback) { return nullptr; } //TODO diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp new file mode 100644 index 0000000000..f60c9f6d69 --- /dev/null +++ b/backends/cloud/folderdownloadrequest.cpp @@ -0,0 +1,111 @@ +/* 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/folderdownloadrequest.h" +#include "common/debug.h" + +namespace Cloud { + +FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive): + Request(nullptr), _storage(storage), _fileArrayCallback(callback), + _remoteDirectoryPath(remoteDirectoryPath), _localDirectoryPath(localDirectoryPath), _recursive(recursive), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +void FolderDownloadRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _currentFile = StorageFile(); + _files.clear(); + _failedFiles.clear(); + _ignoreCallback = false; + + //list directory first + _workingRequest = _storage->listDirectory( + _remoteDirectoryPath, + new Common::Callback(this, &FolderDownloadRequest::directoryListedCallback), + _recursive + ); +} + +void FolderDownloadRequest::directoryListedCallback(Storage::FileArrayResponse pair) { + if (_ignoreCallback) return; + //TODO: somehow ListDirectory requests must indicate that file array is incomplete + _files = pair.value; + downloadNextFile(); +} + +void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse pair) { + if (_ignoreCallback) return; + if (!pair.value) _failedFiles.push_back(_currentFile); + downloadNextFile(); +} + +void FolderDownloadRequest::downloadNextFile() { + do { + if (_files.empty()) { + finishFiles(_failedFiles); + return; + } + + _currentFile = _files.back(); + _files.pop_back(); + } while (_currentFile.isDirectory()); //TODO: may be create these directories (in case those are empty) + + Common::String remotePath = _currentFile.path(); + Common::String localPath = remotePath; + if (_remoteDirectoryPath == "" || remotePath.hasPrefix(_remoteDirectoryPath)) { + localPath.erase(0, _remoteDirectoryPath.size()); + if (_remoteDirectoryPath != "" && (_remoteDirectoryPath.lastChar() != '/' && _remoteDirectoryPath.lastChar() != '\\')) + localPath.erase(0, 1); + } else { + warning("Can't process the following paths:"); + warning("remote directory: %s", _remoteDirectoryPath.c_str()); + warning("remote file under that directory: %s", remotePath.c_str()); + } + if (_localDirectoryPath != "") { + if (_localDirectoryPath.lastChar() == '/' || _localDirectoryPath.lastChar() == '\\') + localPath = _localDirectoryPath + localPath; + else + localPath = _localDirectoryPath + "/" + localPath; + } + debug("%s -> %s", remotePath.c_str(), localPath.c_str()); + _workingRequest = _storage->download( + remotePath, localPath, + new Common::Callback(this, &FolderDownloadRequest::fileDownloadedCallback) + ); +} + +void FolderDownloadRequest::finish() { + //TODO: somehow indicate that request was interrupted + Common::Array files; + finishFiles(files); +} + +void FolderDownloadRequest::finishFiles(Common::Array &files) { + Request::finish(); + if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); +} + +} //end of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h new file mode 100644 index 0000000000..038dc642ef --- /dev/null +++ b/backends/cloud/folderdownloadrequest.h @@ -0,0 +1,59 @@ +/* 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_FOLDERDOWNLOADREQUEST_H +#define BACKENDS_CLOUD_FOLDERDOWNLOADREQUEST_H + +#include "backends/networking/curl/request.h" +#include "backends/networking/curl/networkreadstream.h" +#include "backends/cloud/storage.h" +#include "common/file.h" + +namespace Cloud { + +class FolderDownloadRequest: public Networking::Request { + Storage *_storage; + Storage::FileArrayCallback _fileArrayCallback; + Common::String _remoteDirectoryPath, _localDirectoryPath; + bool _recursive; + Common::Array _files, _failedFiles; + StorageFile _currentFile; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void directoryListedCallback(Storage::FileArrayResponse pair); + void fileDownloadedCallback(Storage::BoolResponse pair); + void downloadNextFile(); + void finishFiles(Common::Array &files); +public: + FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive); + virtual ~FolderDownloadRequest() {} + + virtual void handle() {} + virtual void restart() { start(); } + virtual void finish(); +}; + +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp index 02c9cae3cf..c0f8d3a9bc 100644 --- a/backends/cloud/storagefile.cpp +++ b/backends/cloud/storagefile.cpp @@ -24,6 +24,14 @@ namespace Cloud { +StorageFile::StorageFile() { + _path = ""; + _name = ""; + _size = 0; + _timestamp = 0; + _isDirectory = false; +} + StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { _path = pth; diff --git a/backends/cloud/storagefile.h b/backends/cloud/storagefile.h index 8706ba18e9..ced99fae30 100644 --- a/backends/cloud/storagefile.h +++ b/backends/cloud/storagefile.h @@ -39,6 +39,7 @@ class StorageFile { bool _isDirectory; public: + StorageFile(); //invalid empty file StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir); Common::String path() const { return _path; } -- cgit v1.2.3 From 8aa87815a62117c5fd29b335c8e33b0cbea0da44 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 22:33:39 +0600 Subject: CLOUD: Fix "global destructor" warning Plain char * is used instead of Common::String in DropboxStorage and OneDriveStorage's KEY and SECRET. --- backends/cloud/dropbox/dropboxstorage.cpp | 28 +++++++++++++++++++--------- backends/cloud/dropbox/dropboxstorage.h | 4 +++- backends/cloud/onedrive/onedrivestorage.cpp | 28 +++++++++++++++++++--------- backends/cloud/onedrive/onedrivestorage.h | 4 +++- 4 files changed, 44 insertions(+), 20 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 379d7bb611..3d7eafedeb 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -36,8 +36,20 @@ namespace Cloud { namespace Dropbox { -Common::String DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth -Common::String DropboxStorage::SECRET; //TODO: hide these secrets somehow +char *DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth +char *DropboxStorage::SECRET; //TODO: hide these secrets somehow + +void DropboxStorage::loadKeyAndSecret() { + Common::String k = ConfMan.get("DROPBOX_KEY", "cloud"); + KEY = new char[k.size() + 1]; + memcpy(KEY, k.c_str(), k.size()); + KEY[k.size()] = 0; + + k = ConfMan.get("DROPBOX_SECRET", "cloud"); + SECRET = new char[k.size() + 1]; + memcpy(SECRET, k.c_str(), k.size()); + SECRET[k.size()] = 0; +} static void saveAccessTokenCallback(Networking::JsonResponse pair) { Common::JSONValue *json = (Common::JSONValue *)pair.value; @@ -178,8 +190,7 @@ void DropboxStorage::infoMethodCallback(StorageInfoResponse pair) { } DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { - KEY = ConfMan.get("DROPBOX_KEY", "cloud"); - SECRET = ConfMan.get("DROPBOX_SECRET", "cloud"); + loadKeyAndSecret(); if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { warning("No access_token found"); @@ -201,7 +212,7 @@ Common::String DropboxStorage::getAuthLink() { url += "?response_type=code"; url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting //url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening - url += "&client_id=" + KEY; + url += "&client_id="; url += KEY; return url; } @@ -211,8 +222,7 @@ void DropboxStorage::authThroughConsole() { return; } - KEY = ConfMan.get("DROPBOX_KEY", "cloud"); - SECRET = ConfMan.get("DROPBOX_SECRET", "cloud"); + loadKeyAndSecret(); if (ConfMan.hasKey("dropbox_code", "cloud")) { //phase 2: get access_token using specified code @@ -232,8 +242,8 @@ void DropboxStorage::getAccessToken(Common::String code) { Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); - request->addPostField("client_id=" + KEY); - request->addPostField("client_secret=" + SECRET); + request->addPostField("client_id=" + Common::String(KEY)); + request->addPostField("client_secret=" + Common::String(SECRET)); request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); ConnMan.addRequest(request); } diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 19f2f9cdd4..c411e25d73 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -31,7 +31,9 @@ namespace Cloud { namespace Dropbox { class DropboxStorage: public Cloud::Storage { - static Common::String KEY, SECRET; + static char *KEY, *SECRET; + + static void loadKeyAndSecret(); Common::String _token, _uid; diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index e181fecabb..6f3a283fe6 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -37,8 +37,20 @@ namespace Cloud { namespace OneDrive { -Common::String OneDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth -Common::String OneDriveStorage::SECRET; //TODO: hide these secrets somehow +char *OneDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth +char *OneDriveStorage::SECRET; //TODO: hide these secrets somehow + +void OneDriveStorage::loadKeyAndSecret() { + Common::String k = ConfMan.get("ONEDRIVE_KEY", "cloud"); + KEY = new char[k.size() + 1]; + memcpy(KEY, k.c_str(), k.size()); + KEY[k.size()] = 0; + + k = ConfMan.get("ONEDRIVE_SECRET", "cloud"); + SECRET = new char[k.size() + 1]; + memcpy(SECRET, k.c_str(), k.size()); + SECRET[k.size()] = 0; +} OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId, Common::String refreshToken): _token(accessToken), _uid(userId), _refreshToken(refreshToken) {} @@ -67,8 +79,8 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) request->addPostField("refresh_token=" + _refreshToken); request->addPostField("grant_type=refresh_token"); } - request->addPostField("client_id=" + KEY); - request->addPostField("client_secret=" + SECRET); + request->addPostField("client_id=" + Common::String(KEY)); + request->addPostField("client_secret=" + Common::String(SECRET)); request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); ConnMan.addRequest(request); } @@ -186,8 +198,7 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { - KEY = ConfMan.get("ONEDRIVE_KEY", "cloud"); - SECRET = ConfMan.get("ONEDRIVE_SECRET", "cloud"); + loadKeyAndSecret(); if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { warning("No access_token found"); @@ -215,7 +226,7 @@ Common::String OneDriveStorage::getAuthLink() { url += "?response_type=code"; url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting //url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening - url += "&client_id=" + KEY; + url += "&client_id="; url += KEY; url += "&scope=onedrive.appfolder%20offline_access"; //TODO return url; } @@ -226,8 +237,7 @@ void OneDriveStorage::authThroughConsole() { return; } - KEY = ConfMan.get("ONEDRIVE_KEY", "cloud"); - SECRET = ConfMan.get("ONEDRIVE_SECRET", "cloud"); + loadKeyAndSecret(); if (ConfMan.hasKey("onedrive_code", "cloud")) { //phase 2: get access_token using specified code diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 858af6c9bf..290abd7926 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -31,7 +31,9 @@ namespace Cloud { namespace OneDrive { class OneDriveStorage: public Cloud::Storage { - static Common::String KEY, SECRET; + static char *KEY, *SECRET; + + static void loadKeyAndSecret(); Common::String _token, _uid, _refreshToken; -- cgit v1.2.3 From 14d60e62f8452dd433fcf275cd87fd9b8c3bd6fd Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 27 May 2016 22:37:03 +0600 Subject: CLOUD: Fix format string warnings I get 'warning: ISO C++98 does not support the '%lg' ms_printf format' warning though. --- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 3d7eafedeb..ad6702c967 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -168,7 +168,7 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ if (outerCallback) { //Dropbox documentation states there is no errors for this API method Common::JSONObject info = json->asObject(); - Common::String uid = Common::String::format("%d", info.getVal("uid")->asNumber()); + Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asNumber()); Common::String name = info.getVal("display_name")->asString(); Common::String email = info.getVal("email")->asString(); Common::JSONObject quota = info.getVal("quota_info")->asObject(); -- cgit v1.2.3 From 827c7e43da118f12ae614530340a566a23c42746 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 28 May 2016 01:08:51 +0600 Subject: CLOUD: Add OneDriveListDirectoryRequest Works as charm. --- .../onedrive/onedrivelistdirectoryrequest.cpp | 138 +++++++++++++++++++++ .../cloud/onedrive/onedrivelistdirectoryrequest.h | 64 ++++++++++ backends/cloud/onedrive/onedrivestorage.cpp | 15 ++- backends/cloud/onedrive/onedrivestorage.h | 3 +- 4 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp create mode 100644 backends/cloud/onedrive/onedrivelistdirectoryrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp new file mode 100644 index 0000000000..2c47852fd1 --- /dev/null +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -0,0 +1,138 @@ +/* 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/onedrivelistdirectoryrequest.h" +#include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/cloud/onedrive/onedrivetokenrefresher.h" +#include "backends/cloud/iso8601.h" +#include "backends/networking/curl/connectionmanager.h" +#include "common/json.h" + +namespace Cloud { +namespace OneDrive { + +OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::FileArrayCallback cb, bool recursive): + Networking::Request(0), + _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _filesCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +void OneDriveListDirectoryRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _files.clear(); + _directoriesQueue.clear(); + _currentDirectory = ""; + _ignoreCallback = false; + + _directoriesQueue.push_back(_requestedPath); + listNextDirectory(); +} + +void OneDriveListDirectoryRequest::listNextDirectory() { + if (_directoriesQueue.empty()) { + finishFiles(_files); + return; + } + + _currentDirectory = _directoriesQueue.back(); + _directoriesQueue.pop_back(); + + if (_currentDirectory != "" && _currentDirectory.lastChar() != '/' && _currentDirectory.lastChar() != '\\') + _currentDirectory += '/'; + + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + _currentDirectory; + url.deleteLastChar(); + url += ":/children"; + makeRequest(url); +} + +void OneDriveListDirectoryRequest::makeRequest(Common::String url) { + Networking::JsonCallback callback = new Common::Callback(this, &OneDriveListDirectoryRequest::listedDirectoryCallback); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, url.c_str()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); + _workingRequest = ConnMan.addRequest(request); +} + + +void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse pair) { + Common::JSONValue *json = pair.value; + + if (_ignoreCallback) { + delete json; + return; + } + + if (!json) { + finish(); + return; + } + + Common::JSONObject response = json->asObject(); + + //TODO: check that all keys exist to avoid segfaults + + Common::JSONArray items = response.getVal("value")->asArray(); + for (uint32 i = 0; i < items.size(); ++i) { + Common::JSONObject item = items[i]->asObject(); + + Common::String path = _currentDirectory + item.getVal("name")->asString(); + bool isDirectory = item.contains("folder"); + uint32 size = 0, timestamp = 0; + //if (!isDirectory) { + size = item.getVal("size")->asNumber(); + timestamp = ISO8601::convertToTimestamp(item.getVal("lastModifiedDateTime")->asString()); + //} + + StorageFile file(path, size, timestamp, isDirectory); + _files.push_back(file); + if (_requestedRecursive && file.isDirectory()) { + _directoriesQueue.push_back(file.path()); + } + } + + bool hasMore = response.contains("@odata.nextLink"); + if (hasMore) { + makeRequest(response.getVal("@odata.nextLink")->asString()); + } else { + listNextDirectory(); + } + + delete json; +} + +void OneDriveListDirectoryRequest::finish() { + //TODO: indicate it's interrupted + Common::Array files; + finishFiles(files); +} + +void OneDriveListDirectoryRequest::finishFiles(Common::Array &files) { + Request::finish(); + if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); +} + +} //end of namespace OneDrive +} //end of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h new file mode 100644 index 0000000000..61eebb2669 --- /dev/null +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h @@ -0,0 +1,64 @@ +/* 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_ONEDRIVELISTDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVELISTDIRECTORYREQUEST_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 OneDriveListDirectoryRequest: public Networking::Request { + Common::String _requestedPath; + bool _requestedRecursive; + OneDriveStorage *_storage; + Storage::FileArrayCallback _filesCallback; + Common::Array _files; + Common::Array _directoriesQueue; + Common::String _currentDirectory; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void listNextDirectory(); + void listedDirectoryCallback(Networking::JsonResponse pair); + void makeRequest(Common::String url); + void finishFiles(Common::Array &files); +public: + OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); + virtual ~OneDriveListDirectoryRequest() { delete _filesCallback; } + + virtual void handle() {} + virtual void restart() { start(); } + virtual void finish(); +}; + +} //end of namespace OneDrive +} //end of namespace Cloud + +#endif diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 6f3a283fe6..d14379393b 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -23,6 +23,7 @@ #include "backends/cloud/onedrive/onedrivestorage.h" #include "backends/cloud/onedrive/onedrivetokenrefresher.h" +#include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h" #include "backends/cloud/downloadrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" @@ -161,6 +162,11 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out delete pair.value; } +Networking::Request *OneDriveStorage::listDirectory(Common::String path, FileArrayCallback callback, bool recursive) { + return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, recursive)); +} + + Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback) { Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); @@ -186,6 +192,13 @@ void OneDriveStorage::fileDownloaded(BoolResponse pair) { else debug("download failed!"); } +void OneDriveStorage::printFiles(FileArrayResponse pair) { + debug("files:"); + Common::Array &files = pair.value; + for (uint32 i = 0; i < files.size(); ++i) + debug("\t%s", files[i].path().c_str()); +} + Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation /* @@ -194,7 +207,7 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); */ - return download("pic.jpg", "local/onedrive/2/doom.jpg", new Common::Callback(this, &OneDriveStorage::fileDownloaded)); + return listDirectory("subfolder", new Common::Callback(this, &OneDriveStorage::printFiles), true); } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 290abd7926..c9a32a802f 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -51,6 +51,7 @@ class OneDriveStorage: public Cloud::Storage { void printJson(Networking::JsonResponse pair); void fileDownloaded(BoolResponse pair); + void printFiles(FileArrayResponse pair); void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse pair); public: @@ -73,7 +74,7 @@ public: /** Public Cloud API comes down there. */ /** Returns Common::Array. */ - virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) { return nullptr; } //TODO + 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 -- cgit v1.2.3 From b74d7a6861dbb5d0fafec0e6587deb7637b0ab12 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 28 May 2016 01:18:37 +0600 Subject: CLOUD: Fix Requests destructors I forgot to delete callbacks! --- backends/cloud/downloadrequest.h | 5 ++++- backends/cloud/folderdownloadrequest.cpp | 7 +++++++ backends/cloud/folderdownloadrequest.h | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index 4ea85760ae..c9c243be44 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -40,7 +40,10 @@ class DownloadRequest: public Networking::Request { void finishBool(bool success); public: DownloadRequest(Storage *storage, Storage::BoolCallback callback, Common::String remoteFile, Common::DumpFile *dumpFile); - virtual ~DownloadRequest() { delete _localFile; } + virtual ~DownloadRequest() { + delete _boolCallback; + delete _localFile; + } virtual void handle(); virtual void restart(); diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index f60c9f6d69..cbd3501772 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -32,6 +32,13 @@ FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArra start(); } +FolderDownloadRequest::~FolderDownloadRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _fileArrayCallback; +} + + void FolderDownloadRequest::start() { //cleanup _ignoreCallback = true; diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 038dc642ef..949bcad6ee 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -47,7 +47,7 @@ class FolderDownloadRequest: public Networking::Request { void finishFiles(Common::Array &files); public: FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive); - virtual ~FolderDownloadRequest() {} + virtual ~FolderDownloadRequest(); virtual void handle() {} virtual void restart() { start(); } -- cgit v1.2.3 From 6f35fc42721895be70c6c21f87eb9a75693ff168 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 28 May 2016 20:40:20 +0600 Subject: CLOUD: Add OneDriveStorage::downloadFolder() Just uses FolderDownloadRequest the way DropboxStorage does. --- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/onedrive/onedrivestorage.cpp | 8 +++++++- backends/cloud/onedrive/onedrivestorage.h | 3 +++ backends/cloud/storage.h | 3 +++ 4 files changed, 14 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index c411e25d73..59dea9d210 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -79,7 +79,7 @@ public: virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback); /** Returns Common::Array with list of files, which were not downloaded. */ - Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false); + virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false); /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback) { return nullptr; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index d14379393b..c924dbf093 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -25,6 +25,7 @@ #include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/onedrive/onedrivelistdirectoryrequest.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/cloudmanager.h" @@ -187,6 +188,11 @@ Networking::Request *OneDriveStorage::download(Common::String remotePath, Common return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); } +/** Returns Common::Array with list of files, which were not downloaded. */ +Networking::Request *OneDriveStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive) { + return ConnMan.addRequest(new FolderDownloadRequest(this, callback, remotePath, localPath, recursive)); +} + void OneDriveStorage::fileDownloaded(BoolResponse pair) { if (pair.value) debug("file downloaded!"); else debug("download failed!"); @@ -207,7 +213,7 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); */ - return listDirectory("subfolder", new Common::Callback(this, &OneDriveStorage::printFiles), true); + return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback(this, &OneDriveStorage::printFiles), false); } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index c9a32a802f..674d13634d 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -85,6 +85,9 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback); + /** Returns Common::Array with list of files, which were not downloaded. */ + virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false); + /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback) { return nullptr; } //TODO diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 8ae5308a1c..8009075d0c 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -81,6 +81,9 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; + /** Returns Common::Array with list of files, which were not downloaded. */ + virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false) = 0; + /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback) = 0; -- cgit v1.2.3 From f4dfaed19d14c309e44d390b44bff571566779a5 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sat, 28 May 2016 19:52:56 +0200 Subject: Replace 0 constant with nullptr in getCurrentStorage() --- backends/cloud/manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index a7e92dfe03..9e11f0d4bd 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -97,7 +97,7 @@ void Manager::addStorage(Cloud::Storage *storage, bool makeCurrent, bool saveCon Storage *Manager::getCurrentStorage() { if (_currentStorageIndex < _storages.size()) return _storages[_currentStorageIndex]; - return 0; + return nullptr; } void Manager::syncSaves(Storage::BoolCallback callback) { -- 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/downloadrequest.cpp | 2 +- backends/cloud/downloadrequest.h | 2 +- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 +- .../cloud/dropbox/dropboxlistdirectoryrequest.h | 4 +- backends/cloud/dropbox/dropboxstorage.cpp | 4 +- backends/cloud/dropbox/dropboxstorage.h | 35 ++++++++-------- backends/cloud/folderdownloadrequest.cpp | 2 +- backends/cloud/folderdownloadrequest.h | 2 +- backends/cloud/iso8601.cpp | 4 +- backends/cloud/iso8601.h | 4 +- backends/cloud/manager.cpp | 2 +- backends/cloud/manager.h | 2 +- .../onedrive/onedrivelistdirectoryrequest.cpp | 4 +- .../cloud/onedrive/onedrivelistdirectoryrequest.h | 4 +- backends/cloud/onedrive/onedrivestorage.cpp | 4 +- backends/cloud/onedrive/onedrivestorage.h | 49 +++++++++++----------- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 4 +- backends/cloud/onedrive/onedrivetokenrefresher.h | 4 +- backends/cloud/storage.h | 3 +- backends/cloud/storagefile.cpp | 2 +- backends/cloud/storagefile.h | 11 +++-- backends/cloud/storageinfo.h | 2 +- 22 files changed, 75 insertions(+), 79 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index c7f6f75346..8d5e244e45 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -100,4 +100,4 @@ void DownloadRequest::finishBool(bool success) { if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } -} //end of namespace Cloud +} // End of namespace Cloud diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index c9c243be44..0bad5df279 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -50,6 +50,6 @@ public: virtual void finish(); }; -} //end of namespace Cloud +} // End of namespace Cloud #endif 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 diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index e2a9ebf3a4..8539be1e1e 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -55,7 +55,7 @@ public: virtual void finish(); }; -} //end of namespace Dropbox -} //end of namespace Cloud +} // End of namespace Dropbox +} // End of namespace Cloud #endif diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index ad6702c967..b1dd865ee2 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -248,5 +248,5 @@ void DropboxStorage::getAccessToken(Common::String code) { ConnMan.addRequest(request); } -} //end of namespace Dropbox -} //end of namespace Cloud +} // End of namespace Dropbox +} // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 59dea9d210..da508d7844 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -51,17 +51,16 @@ public: virtual ~DropboxStorage(); /** - * Storage methods, which are used by CloudManager to save - * storage in configuration file. - */ + * Storage methods, which are used by CloudManager to save + * storage in configuration file. + */ /** - * Save storage data using ConfMan. - * @param keyPrefix all saved keys must start with this prefix. - * @note every Storage must write keyPrefix + "type" key - * with common value (e.g. "Dropbox"). - */ - + * Save storage data using ConfMan. + * @param keyPrefix all saved keys must start with this prefix. + * @note every Storage must write keyPrefix + "type" key + * with common value (e.g. "Dropbox"). + */ virtual void saveConfig(Common::String keyPrefix); /** Public Cloud API comes down there. */ @@ -106,23 +105,23 @@ public: virtual bool isWorking() { return false; } //TODO /** - * Load token and user id from configs and return DropboxStorage for those. - * @return pointer to the newly created DropboxStorage or 0 if some problem occured. - */ + * Load token and user id from configs and return DropboxStorage for those. + * @return pointer to the newly created DropboxStorage or 0 if some problem occured. + */ static DropboxStorage *loadFromConfig(Common::String keyPrefix); /** - * Returns Dropbox auth link. - */ + * Returns Dropbox auth link. + */ static Common::String getAuthLink(); /** - * Show message with Dropbox auth instructions. (Temporary) - */ + * Show message with Dropbox auth instructions. (Temporary) + */ static void authThroughConsole(); }; -} //end of namespace Dropbox -} //end of namespace Cloud +} // End of namespace Dropbox +} // End of namespace Cloud #endif diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index cbd3501772..9c2e8b173a 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -115,4 +115,4 @@ void FolderDownloadRequest::finishFiles(Common::Array &files) { if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); } -} //end of namespace Cloud +} // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 949bcad6ee..33fa5992c6 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -54,6 +54,6 @@ public: virtual void finish(); }; -} //end of namespace Cloud +} // End of namespace Cloud #endif diff --git a/backends/cloud/iso8601.cpp b/backends/cloud/iso8601.cpp index 12cbb742b8..3bc169ae85 100644 --- a/backends/cloud/iso8601.cpp +++ b/backends/cloud/iso8601.cpp @@ -87,5 +87,5 @@ uint32 convertToTimestamp(const Common::String &iso8601Date) { return minutes * 60 + s; } -} //end of namespace ISO8601 -} //end of namespace Cloud +} // End of namespace ISO8601 +} // End of namespace Cloud diff --git a/backends/cloud/iso8601.h b/backends/cloud/iso8601.h index a53b3bb501..6e11322cdb 100644 --- a/backends/cloud/iso8601.h +++ b/backends/cloud/iso8601.h @@ -31,7 +31,7 @@ namespace ISO8601 { /** Returns timestamp corresponding to given ISO 8601 date */ uint32 convertToTimestamp(const Common::String &iso8601Date); -} //end of namespace ISO8601 -} //end of namespace Cloud +} // End of namespace ISO8601 +} // End of namespace Cloud #endif diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 9e11f0d4bd..959f395243 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -105,4 +105,4 @@ void Manager::syncSaves(Storage::BoolCallback callback) { if (storage) storage->syncSaves(callback); } -} //end of namespace Cloud +} // End of namespace Cloud diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index 08106e0513..6eaf17bc91 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -44,6 +44,6 @@ public: virtual void syncSaves(Storage::BoolCallback callback); }; -} //end of namespace Cloud +} // End of namespace Cloud #endif diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index 2c47852fd1..452c47ac13 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -134,5 +134,5 @@ void OneDriveListDirectoryRequest::finishFiles(Common::Array &files if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); } -} //end of namespace OneDrive -} //end of namespace Cloud +} // End of namespace OneDrive +} // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h index 61eebb2669..ce407c041e 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h @@ -58,7 +58,7 @@ public: virtual void finish(); }; -} //end of namespace OneDrive -} //end of namespace Cloud +} // End of namespace OneDrive +} // End of namespace Cloud #endif diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index c924dbf093..c8b4ab1ad3 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -271,5 +271,5 @@ void OneDriveStorage::authThroughConsole() { debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); } -} //end of namespace OneDrive -} //end of namespace Cloud +} // End of namespace OneDrive +} // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 674d13634d..3dc5b7a7ad 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -41,9 +41,9 @@ class OneDriveStorage: public Cloud::Storage { OneDriveStorage(Common::String token, Common::String uid, Common::String refreshToken); /** - * This private constructor is called from authThroughConsole() (phase 2). - * It uses OAuth code flow to get tokens. - */ + * This private constructor is called from authThroughConsole() (phase 2). + * It uses OAuth code flow to get tokens. + */ OneDriveStorage(Common::String code); void tokenRefreshed(BoolCallback callback, Networking::JsonResponse pair); @@ -58,17 +58,16 @@ public: virtual ~OneDriveStorage(); /** - * Storage methods, which are used by CloudManager to save - * storage in configuration file. - */ + * Storage methods, which are used by CloudManager to save + * storage in configuration file. + */ /** - * Save storage data using ConfMan. - * @param keyPrefix all saved keys must start with this prefix. - * @note every Storage must write keyPrefix + "type" key - * with common value (e.g. "Dropbox"). - */ - + * Save storage data using ConfMan. + * @param keyPrefix all saved keys must start with this prefix. + * @note every Storage must write keyPrefix + "type" key + * with common value (e.g. "Dropbox"). + */ virtual void saveConfig(Common::String keyPrefix); /** Public Cloud API comes down there. */ @@ -110,32 +109,32 @@ public: virtual bool isWorking() { return false; } //TODO /** - * Load token and user id from configs and return OneDriveStorage for those. - * @return pointer to the newly created OneDriveStorage or 0 if some problem occured. - */ + * Load token and user id from configs and return OneDriveStorage for those. + * @return pointer to the newly created OneDriveStorage or 0 if some problem occured. + */ static OneDriveStorage *loadFromConfig(Common::String keyPrefix); /** - * Returns OneDrive auth link. - */ + * Returns OneDrive auth link. + */ static Common::String getAuthLink(); /** - * Show message with OneDrive auth instructions. (Temporary) - */ + * Show message with OneDrive auth instructions. (Temporary) + */ static void authThroughConsole(); /** - * Gets new access_token. If passed is "", refresh_token is used. - * Use "" in order to refresh token and pass a callback, so you could - * continue your work when new token is available. - */ + * Gets new access_token. If passed is "", refresh_token is used. + * Use "" in order to refresh token and pass a callback, so you could + * continue your work when new token is available. + */ void getAccessToken(BoolCallback callback, Common::String code = ""); Common::String accessToken() { return _token; } }; -} //end of namespace OneDrive -} //end of namespace Cloud +} // End of namespace OneDrive +} // End of namespace Cloud #endif diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 94214834b0..d932f9ab17 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -93,5 +93,5 @@ void OneDriveTokenRefresher::setHeaders(Common::Array &headers) } -} //end of namespace OneDrive -} //end of namespace Cloud +} // End of namespace OneDrive +} // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h index 08212bf6f5..90ca9d603a 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.h +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -50,7 +50,7 @@ public: } }; -} //end of namespace OneDrive -} //end of namespace Cloud +} // End of namespace OneDrive +} // End of namespace Cloud #endif diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 8009075d0c..ac74f90b57 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -58,7 +58,6 @@ public: * @note every Storage must write keyPrefix + "type" key * with common value (e.g. "Dropbox"). */ - virtual void saveConfig(Common::String keyPrefix) = 0; /** @@ -106,6 +105,6 @@ public: virtual bool isWorking() = 0; }; -} //end of namespace Cloud +} // End of namespace Cloud #endif diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp index c0f8d3a9bc..b37b5e0d53 100644 --- a/backends/cloud/storagefile.cpp +++ b/backends/cloud/storagefile.cpp @@ -53,4 +53,4 @@ StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { _isDirectory = dir; } -} //end of namespace Cloud +} // End of namespace Cloud diff --git a/backends/cloud/storagefile.h b/backends/cloud/storagefile.h index ced99fae30..704a03867f 100644 --- a/backends/cloud/storagefile.h +++ b/backends/cloud/storagefile.h @@ -28,11 +28,10 @@ namespace Cloud { /** -* StorageFile represents a file storaged on remote cloud storage. -* It contains basic information about a file, and might be used -* when listing directories or syncing files. -*/ - + * StorageFile represents a file storaged on remote cloud storage. + * It contains basic information about a file, and might be used + * when listing directories or syncing files. + */ class StorageFile { Common::String _path, _name; uint32 _size, _timestamp; @@ -49,6 +48,6 @@ public: bool isDirectory() const { return _isDirectory; } }; -} //end of namespace Cloud +} // End of namespace Cloud #endif diff --git a/backends/cloud/storageinfo.h b/backends/cloud/storageinfo.h index f09563570f..1492898a6c 100644 --- a/backends/cloud/storageinfo.h +++ b/backends/cloud/storageinfo.h @@ -48,6 +48,6 @@ public: }; -} //end of namespace Cloud +} // End of namespace Cloud #endif -- cgit v1.2.3 From 86d5b1b2e13c09f52d1af21b1f9b43d4b3c712c3 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sat, 28 May 2016 20:38:10 +0200 Subject: Remove some unnecessary blank lines --- backends/cloud/folderdownloadrequest.cpp | 1 - backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp | 1 - 2 files changed, 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 9c2e8b173a..00bddb9f09 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -38,7 +38,6 @@ FolderDownloadRequest::~FolderDownloadRequest() { delete _fileArrayCallback; } - void FolderDownloadRequest::start() { //cleanup _ignoreCallback = true; diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index 452c47ac13..f1402c43b2 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -76,7 +76,6 @@ void OneDriveListDirectoryRequest::makeRequest(Common::String url) { _workingRequest = ConnMan.addRequest(request); } - void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse pair) { Common::JSONValue *json = pair.value; -- cgit v1.2.3 From 1747f8ec420edd0517e37a88e5fdd57f1b11b22f Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 29 May 2016 20:12:22 +0600 Subject: CLOUD: Add "device_id" into configuration file --- backends/cloud/manager.cpp | 14 ++++++++++++-- backends/cloud/manager.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 959f395243..13f23b8e6e 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -22,12 +22,13 @@ #include "backends/cloud/manager.h" #include "backends/cloud/dropbox/dropboxstorage.h" +#include "backends/cloud/onedrive/onedrivestorage.h" #include "common/config-manager.h" -#include "onedrive/onedrivestorage.h" +#include "common/random.h" namespace Cloud { -Manager::Manager(): _currentStorageIndex(0) {} +Manager::Manager(): _currentStorageIndex(0), _deviceId(0) {} Manager::~Manager() { //TODO: do we have to save storages on manager destruction? @@ -40,6 +41,15 @@ void Manager::init() { bool offerDropbox = false; bool offerOneDrive = true; + if (!ConfMan.hasKey("device_id", "cloud")) { + Common::RandomSource source("Cloud Random Source"); + _deviceId = source.getRandomNumber(UINT_MAX - 1); + ConfMan.setInt("device_id", _deviceId, "cloud"); + ConfMan.flushToDisk(); + } else { + _deviceId = ConfMan.getInt("device_id", "cloud"); + } + if (ConfMan.hasKey("storages_number", "cloud")) { int storages = ConfMan.getInt("storages_number", "cloud"); for (int i = 1; i <= storages; ++i) { diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index 6eaf17bc91..f472b80ae3 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -31,6 +31,7 @@ namespace Cloud { class Manager: public Common::CloudManager { Common::Array _storages; uint _currentStorageIndex; + uint _deviceId; public: Manager(); -- cgit v1.2.3 From c235aa29f997b9bd000be5424662b114957f1640 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 29 May 2016 23:25:08 +0600 Subject: CLOUD: Add SavesSyncRequest sketch Never tested it, actually. It requires Storage to implement upload() method and me to find some way to get saves' ReadStream. The saveTimestamps() and loadTimestamps() part should be tested, other parts should work fine. --- backends/cloud/savessyncrequest.cpp | 229 ++++++++++++++++++++++++++++++++++++ backends/cloud/savessyncrequest.h | 63 ++++++++++ 2 files changed, 292 insertions(+) create mode 100644 backends/cloud/savessyncrequest.cpp create mode 100644 backends/cloud/savessyncrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp new file mode 100644 index 0000000000..d48ec6ba45 --- /dev/null +++ b/backends/cloud/savessyncrequest.cpp @@ -0,0 +1,229 @@ +/* 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/savessyncrequest.h" +#include "common/debug.h" +#include "common/file.h" + +namespace Cloud { + +SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback): + Request(nullptr), _storage(storage), _boolCallback(callback), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +SavesSyncRequest::~SavesSyncRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; +} + +void SavesSyncRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _currentDownloadingFile = StorageFile(); + _currentUploadingFile = ""; + _filesToDownload.clear(); + _filesToUpload.clear(); + _localFilesTimestamps.clear(); + _ignoreCallback = false; + + //load timestamps + loadTimestamps(); + + //list saves directory + _workingRequest = _storage->listDirectory("saves", new Common::Callback(this, &SavesSyncRequest::directoryListedCallback)); +} + +void SavesSyncRequest::directoryListedCallback(Storage::FileArrayResponse pair) { + if (_ignoreCallback) return; + //TODO: somehow ListDirectory requests must indicate that file array is incomplete + + const uint32 INVALID_TIMESTAMP = UINT_MAX; + + //determine which files to download and which files to upload + Common::Array &remoteFiles = pair.value; + for (uint32 i = 0; i < remoteFiles.size(); ++i) { + StorageFile &file = remoteFiles[i]; + if (file.isDirectory()) continue; + Common::String name = file.name(); + if (!_localFilesTimestamps.contains(name)) + _filesToDownload.push_back(file); + else { + if (_localFilesTimestamps[name] != INVALID_TIMESTAMP) { + if (_localFilesTimestamps[name] == file.timestamp()) + continue; + + //we actually can have some files not only with timestamp < remote + //but also with timestamp > remote (when we have been using ANOTHER CLOUD and then switched back) + if (_localFilesTimestamps[name] < file.timestamp()) + _filesToDownload.push_back(file); + else + _filesToUpload.push_back(file.name()); + } + } + } + + //upload files with invalid timestamp (the ones we've added - means they might not have any remote version) + for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { + if (i->_value == INVALID_TIMESTAMP) + _filesToUpload.push_back(i->_key); + } + + //start downloading files + downloadNextFile(); +} + +void SavesSyncRequest::downloadNextFile() { + if (_filesToDownload.empty()) { + uploadNextFile(); + return; + } + + _currentDownloadingFile = _filesToDownload.back(); + _filesToDownload.pop_back(); + + _workingRequest = _storage->download(_currentDownloadingFile.path(), "saves/" + _currentDownloadingFile.name(), + new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback) + ); +} + +void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse pair) { + if (_ignoreCallback) return; + + //stop syncing if download failed + if (!pair.value) { + finish(); + return; + } + + //update local timestamp for downloaded file + _localFilesTimestamps[_currentDownloadingFile.name()] = _currentDownloadingFile.timestamp(); + + //continue downloading files + downloadNextFile(); +} + +void SavesSyncRequest::uploadNextFile() { + if (_filesToUpload.empty()) { + finishBool(true); + return; + } + + _currentUploadingFile = _filesToUpload.back(); + _filesToUpload.pop_back(); + + _workingRequest = _storage->upload("saves/" + _currentUploadingFile, nullptr, //TODO: pass save's read stream + new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback) + ); +} + +void SavesSyncRequest::fileUploadedCallback(Storage::BoolResponse pair) { + if (_ignoreCallback) return; + + //stop syncing if upload failed + if (!pair.value) { + finish(); + return; + } + + //TODO: update local timestamp for the uploaded file + //_localFilesTimestamps[_currentUploadingFile] = pair.request.; + + //continue uploading files + uploadNextFile(); +} + +void SavesSyncRequest::handle() {} + +void SavesSyncRequest::restart() { start(); } + +void SavesSyncRequest::finish() { finishBool(false); } + +void SavesSyncRequest::finishBool(bool success) { + Request::finish(); + + //save updated timestamps (even if Request failed, there would be only valid timestamps) + saveTimestamps(); + + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +void SavesSyncRequest::loadTimestamps() { + Common::File f; + if (!f.open("saves/timestamps")) + error("SavesSyncRequest: failed to open 'saves/timestamps' file to load timestamps"); + + while (!f.eos()) { + //read filename into buffer (reading until the first ' ') + Common::String buffer; + while (!f.eos()) { + byte b = f.readByte(); + if (b == ' ') break; + buffer += (char)b; + } + + //read timestamp info buffer (reading until ' ' or some line ending char) + Common::String filename = buffer; + bool lineEnded = false; + buffer = ""; + while (!f.eos()) { + byte b = f.readByte(); + if (b == ' ' || b == '\n' || b == '\r') { + lineEnded = (b == '\n'); + break; + } + buffer += (char)b; + } + + //parse timestamp + uint timestamp = atol(buffer.c_str()); + _localFilesTimestamps[filename] = timestamp; + + //read until the end of the line + if (!lineEnded) { + while (!f.eos()) { + byte b = f.readByte(); + if (b == '\n') break; + } + } + } + + f.close(); +} + +void SavesSyncRequest::saveTimestamps() { + Common::DumpFile f; + if (!f.open("saves/timestamps", true)) + error("SavesSyncRequest: failed to open 'saves/timestamps' file to save timestamps"); + Common::String data; + for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) + data += i->_key + Common::String::format(" %u\n", i->_value); + if (f.write(data.c_str(), data.size()) != data.size()) + error("SavesSyncRequest: failed to write timestamps data into 'saves/timestamps'"); + f.close(); +} + + +} // End of namespace Cloud diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h new file mode 100644 index 0000000000..a8c54d44ad --- /dev/null +++ b/backends/cloud/savessyncrequest.h @@ -0,0 +1,63 @@ +/* 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_SAVESSYNCREQUEST_H +#define BACKENDS_CLOUD_SAVESSYNCREQUEST_H + +#include "backends/networking/curl/request.h" +#include "backends/cloud/storage.h" +#include "common/hashmap.h" + +namespace Cloud { + +class SavesSyncRequest: public Networking::Request { + Storage *_storage; + Storage::BoolCallback _boolCallback; + Common::HashMap _localFilesTimestamps; + Common::Array _filesToDownload; + Common::Array _filesToUpload; + StorageFile _currentDownloadingFile; + Common::String _currentUploadingFile; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void directoryListedCallback(Storage::FileArrayResponse pair); + void fileDownloadedCallback(Storage::BoolResponse pair); + void fileUploadedCallback(Storage::BoolResponse pair); + void downloadNextFile(); + void uploadNextFile(); + void finishBool(bool success); + void loadTimestamps(); + void saveTimestamps(); +public: + SavesSyncRequest(Storage *storage, Storage::BoolCallback callback); + virtual ~SavesSyncRequest(); + + virtual void handle(); + virtual void restart(); + virtual void finish(); +}; + +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From d917592099381402c2681b291d379bda78a1c3f7 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 30 May 2016 02:23:29 +0600 Subject: CLOUD: Add DropboxUploadRequest --- backends/cloud/dropbox/dropboxstorage.cpp | 20 ++- backends/cloud/dropbox/dropboxstorage.h | 3 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 163 ++++++++++++++++++++++++ backends/cloud/dropbox/dropboxuploadrequest.h | 60 +++++++++ backends/cloud/onedrive/onedrivestorage.h | 2 +- backends/cloud/savessyncrequest.h | 1 + backends/cloud/storage.h | 2 +- 7 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 backends/cloud/dropbox/dropboxuploadrequest.cpp create mode 100644 backends/cloud/dropbox/dropboxuploadrequest.h (limited to 'backends/cloud') 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 -#include 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(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(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(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 diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 3dc5b7a7ad..41d84f9770 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -76,7 +76,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) { return nullptr; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback); diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index a8c54d44ad..dd43cab2a0 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -26,6 +26,7 @@ #include "backends/networking/curl/request.h" #include "backends/cloud/storage.h" #include "common/hashmap.h" +#include "common/hash-str.h" namespace Cloud { diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index ac74f90b57..dbd862822b 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -72,7 +72,7 @@ public: virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *upload(Common::String path, Common::ReadStream *contents, BoolCallback callback) = 0; + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback) = 0; /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) = 0; -- 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. --- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 +- backends/cloud/dropbox/dropboxstorage.cpp | 50 ++++++++++++++++------ backends/cloud/dropbox/dropboxstorage.h | 4 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 49 +++++++++++++++------ backends/cloud/dropbox/dropboxuploadrequest.h | 6 +-- backends/cloud/onedrive/onedrivestorage.h | 3 +- backends/cloud/savessyncrequest.cpp | 23 ++++++---- backends/cloud/savessyncrequest.h | 2 +- backends/cloud/storage.h | 25 ++++++++++- 9 files changed, 124 insertions(+), 42 deletions(-) (limited to 'backends/cloud') 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)); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 1220a99035..1f983cec67 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -104,14 +104,46 @@ void DropboxStorage::printBool(BoolResponse pair) { debug("bool: %s", (pair.value?"true":"false")); } +void DropboxStorage::printUploadStatus(UploadResponse pair) { + UploadStatus status = pair.value; + if (status.interrupted) { + debug("upload interrupted by user"); + return; + } + if (status.failed) { + debug("upload failed with following response:"); + debug("%s", status.response.c_str()); + return; + } + debug("upload HTTP response code = %ld", status.httpResponseCode); + if (!status.failed) { + debug("uploaded file info:"); + debug("path: %s", status.file.path().c_str()); + debug("size: %u", status.file.size()); + debug("timestamp: %u", status.file.timestamp()); + } +} + 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) { +Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) { return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback)); } +Networking::Request *DropboxStorage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback) { + Common::File *f = new Common::File(); + if (!f->open(localPath)) { + warning("DropboxStorage: unable to open file to upload from"); + UploadStatus status(false, true, StorageFile(), "", -1); + if (callback) (*callback)(UploadResponse(nullptr, status)); + delete f; + return nullptr; + } + return upload(remotePath, f, callback); +} + Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) { Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("path", new Common::JSONValue(path)); @@ -155,13 +187,7 @@ Networking::Request *DropboxStorage::syncSaves(BoolCallback callback) { 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(this, &DropboxStorage::printBool)); + return upload("/remote/test4.bmp", "final.bmp", new Common::Callback(this, &DropboxStorage::printUploadStatus)); } Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) { @@ -186,13 +212,13 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ if (outerCallback) { //Dropbox documentation states there is no errors for this API method Common::JSONObject info = json->asObject(); - Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asNumber()); + Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asIntegerNumber()); Common::String name = info.getVal("display_name")->asString(); Common::String email = info.getVal("email")->asString(); Common::JSONObject quota = info.getVal("quota_info")->asObject(); - uint32 quotaNormal = quota.getVal("normal")->asNumber(); - uint32 quotaShared = quota.getVal("shared")->asNumber(); - uint32 quotaAllocated = quota.getVal("quota")->asNumber(); + uint32 quotaNormal = quota.getVal("normal")->asIntegerNumber(); + uint32 quotaShared = quota.getVal("shared")->asIntegerNumber(); + uint32 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index cc515fef41..ca285802a4 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -47,6 +47,7 @@ class DropboxStorage: public Cloud::Storage { void printFiles(FileArrayResponse pair); void printBool(BoolResponse pair); + void printUploadStatus(UploadResponse pair); public: virtual ~DropboxStorage(); @@ -70,7 +71,8 @@ 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::SeekableReadStream *contents, BoolCallback callback); + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback); + virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback 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 index d068078502..18e1173eef 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -21,17 +21,19 @@ */ #include "backends/cloud/dropbox/dropboxuploadrequest.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" 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), +DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback): + Networking::Request(0), _token(token), _savePath(path), _contentsStream(contents), _uploadCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { start(); } @@ -40,7 +42,7 @@ DropboxUploadRequest::~DropboxUploadRequest() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); delete _contentsStream; - delete _boolCallback; + delete _uploadCallback; } @@ -105,6 +107,11 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) { if (_ignoreCallback) return; _workingRequest = nullptr; + UploadStatus status; + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request; + if (rq && rq->getNetworkReadStream()) + status.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + Common::JSONValue *json = pair.value; if (json) { bool needsFinishRequest = false; @@ -117,13 +124,19 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) { if (response.contains("error") || response.contains("error_summary")) { warning("Dropbox returned error: %s", response.getVal("error_summary")->asString().c_str()); delete json; - finish(); + status.failed = true; + status.response = json->stringify(true); + finishUpload(status); return; } if (response.contains("server_modified")) { //finished - finishBool(true); + Common::String path = response.getVal("path_lower")->asString(); + uint32 size = response.getVal("size")->asIntegerNumber(); + uint32 timestamp = ISO8601::convertToTimestamp(response.getVal("server_modified")->asString()); + status.file = StorageFile(path, size, timestamp, false); + finishUpload(status); return; } @@ -136,13 +149,19 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) { } } - if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) - finishBool(true); - else + if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { + if (status.file.name() == "") { + status.file = StorageFile(_savePath, 0, 0, false); + warning("no file info to put into status"); + } + finishUpload(status); + } else { uploadNextPart(); + } } else { - warning("null, not json"); - finish(); + warning("null, not json"); + status.failed = true; + finishUpload(status); } delete json; @@ -152,11 +171,15 @@ void DropboxUploadRequest::handle() {} void DropboxUploadRequest::restart() { start(); } -void DropboxUploadRequest::finish() { finishBool(false); } +void DropboxUploadRequest::finish() { + UploadStatus status; + status.interrupted = true; + finishUpload(status); +} -void DropboxUploadRequest::finishBool(bool success) { +void DropboxUploadRequest::finishUpload(UploadStatus status) { Request::finish(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); + if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, status)); } } // End of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxuploadrequest.h b/backends/cloud/dropbox/dropboxuploadrequest.h index a7d7a6c581..9b68995969 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.h +++ b/backends/cloud/dropbox/dropboxuploadrequest.h @@ -35,7 +35,7 @@ class DropboxUploadRequest: public Networking::Request { Common::String _token; Common::String _savePath; Common::SeekableReadStream *_contentsStream; - Storage::BoolCallback _boolCallback; + Storage::UploadCallback _uploadCallback; Request *_workingRequest; bool _ignoreCallback; Common::String _sessionId; @@ -43,10 +43,10 @@ class DropboxUploadRequest: public Networking::Request { void start(); void uploadNextPart(); void partUploadedCallback(Networking::JsonResponse pair); - void finishBool(bool success); + void finishUpload(UploadStatus status); public: - DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::BoolCallback callback); + DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback); virtual ~DropboxUploadRequest(); virtual void handle(); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 41d84f9770..7028667819 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -76,7 +76,8 @@ 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::SeekableReadStream *contents, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) { return nullptr; } //TODO + virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) { return nullptr; } /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index d48ec6ba45..be1075cb4d 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -23,6 +23,8 @@ #include "backends/cloud/savessyncrequest.h" #include "common/debug.h" #include "common/file.h" +#include "common/system.h" +#include "common/savefile.h" namespace Cloud { @@ -85,6 +87,8 @@ void SavesSyncRequest::directoryListedCallback(Storage::FileArrayResponse pair) } } + //TODO: upload files which are added to local directory (not available on cloud), but have no timestamp + //upload files with invalid timestamp (the ones we've added - means they might not have any remote version) for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { if (i->_value == INVALID_TIMESTAMP) @@ -104,7 +108,7 @@ void SavesSyncRequest::downloadNextFile() { _currentDownloadingFile = _filesToDownload.back(); _filesToDownload.pop_back(); - _workingRequest = _storage->download(_currentDownloadingFile.path(), "saves/" + _currentDownloadingFile.name(), + _workingRequest = _storage->download(_currentDownloadingFile.path(), "saves/" + _currentDownloadingFile.name(), //TODO: real saves folder here new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback) ); } @@ -133,23 +137,24 @@ void SavesSyncRequest::uploadNextFile() { _currentUploadingFile = _filesToUpload.back(); _filesToUpload.pop_back(); - - _workingRequest = _storage->upload("saves/" + _currentUploadingFile, nullptr, //TODO: pass save's read stream - new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback) + + _workingRequest = _storage->upload("saves/" + _currentUploadingFile, g_system->getSavefileManager()->openForLoading(_currentUploadingFile), + new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback) ); } -void SavesSyncRequest::fileUploadedCallback(Storage::BoolResponse pair) { +void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse pair) { if (_ignoreCallback) return; + UploadStatus status = pair.value; //stop syncing if upload failed - if (!pair.value) { + if (status.interrupted || status.failed) { finish(); return; } - //TODO: update local timestamp for the uploaded file - //_localFilesTimestamps[_currentUploadingFile] = pair.request.; + //update local timestamp for the uploaded file + _localFilesTimestamps[_currentUploadingFile] = status.file.timestamp(); //continue uploading files uploadNextFile(); @@ -172,6 +177,7 @@ void SavesSyncRequest::finishBool(bool success) { void SavesSyncRequest::loadTimestamps() { Common::File f; + //TODO: real saves folder here if (!f.open("saves/timestamps")) error("SavesSyncRequest: failed to open 'saves/timestamps' file to load timestamps"); @@ -215,6 +221,7 @@ void SavesSyncRequest::loadTimestamps() { void SavesSyncRequest::saveTimestamps() { Common::DumpFile f; + //TODO: real saves folder here if (!f.open("saves/timestamps", true)) error("SavesSyncRequest: failed to open 'saves/timestamps' file to save timestamps"); Common::String data; diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index dd43cab2a0..dca1fb750b 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -44,7 +44,7 @@ class SavesSyncRequest: public Networking::Request { void start(); void directoryListedCallback(Storage::FileArrayResponse pair); void fileDownloadedCallback(Storage::BoolResponse pair); - void fileUploadedCallback(Storage::BoolResponse pair); + void fileUploadedCallback(Storage::UploadResponse pair); void downloadNextFile(); void uploadNextFile(); void finishBool(bool success); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index dbd862822b..1749881a7d 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -34,15 +34,37 @@ namespace Cloud { +/** Struct to represent upload() resulting status. */ +struct UploadStatus { + /** true if Request was interrupted (finished by user with finish()) */ + bool interrupted; + /** true if Request has failed (bad server response or some other error occurred) */ + bool failed; + /** Contains uploaded file description (empty if failed) */ + StorageFile file; + /** Server's original response (empty if not failed) */ + Common::String response; + /** Server's HTTP response code. */ + long httpResponseCode; + + UploadStatus(): + interrupted(false), failed(false), file(), response(), httpResponseCode(-1) {} + + UploadStatus(bool interrupt, bool failure, StorageFile f, Common::String resp, long code): + interrupted(interrupt), failed(failure), file(f), response(resp), httpResponseCode(code) {} +}; + class Storage { public: typedef Networking::Response&> FileArrayResponse; typedef Networking::Response StorageInfoResponse; typedef Networking::Response BoolResponse; + typedef Networking::Response UploadResponse; typedef Common::BaseCallback *FileArrayCallback; typedef Common::BaseCallback *StorageInfoCallback; typedef Common::BaseCallback *BoolCallback; + typedef Common::BaseCallback *UploadCallback; Storage() {} virtual ~Storage() {} @@ -72,7 +94,8 @@ public: virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, BoolCallback callback) = 0; + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) = 0; + virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) = 0; /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) = 0; -- cgit v1.2.3 From a19fc52c329fdb0611eee7aedfb20fb0d1b9269c Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 30 May 2016 13:46:14 +0600 Subject: CLOUD: Make DropboxUploadRequest use "/upload" too If file could be uploaded in one API call, no need to create a session (which requires at least two calls: to start and then to finish it). --- backends/cloud/dropbox/dropboxstorage.cpp | 7 ++++--- backends/cloud/dropbox/dropboxuploadrequest.cpp | 12 ++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 1f983cec67..ab3f5d0874 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -105,6 +105,7 @@ void DropboxStorage::printBool(BoolResponse pair) { } void DropboxStorage::printUploadStatus(UploadResponse pair) { + debug(" "); UploadStatus status = pair.value; if (status.interrupted) { debug("upload interrupted by user"); @@ -118,9 +119,9 @@ void DropboxStorage::printUploadStatus(UploadResponse pair) { debug("upload HTTP response code = %ld", status.httpResponseCode); if (!status.failed) { debug("uploaded file info:"); - debug("path: %s", status.file.path().c_str()); - debug("size: %u", status.file.size()); - debug("timestamp: %u", status.file.timestamp()); + debug("\tpath: %s", status.file.path().c_str()); + debug("\tsize: %u", status.file.size()); + debug("\ttimestamp: %u", status.file.timestamp()); } } diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index 18e1173eef..e422793bc4 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -65,8 +65,16 @@ void DropboxUploadRequest::uploadNextPart() { Common::JSONObject jsonRequestParameters; if (_contentsStream->pos() == 0 || _sessionId == "") { - url += "start"; - jsonRequestParameters.setVal("close", new Common::JSONValue(false)); + if (_contentsStream->size() <= UPLOAD_PER_ONE_REQUEST) { + url = "https://content.dropboxapi.com/2/files/upload"; + jsonRequestParameters.setVal("path", new Common::JSONValue(_savePath)); + jsonRequestParameters.setVal("mode", new Common::JSONValue("overwrite")); + jsonRequestParameters.setVal("autorename", new Common::JSONValue(false)); + jsonRequestParameters.setVal("mute", new Common::JSONValue(false)); + } else { + url += "start"; + jsonRequestParameters.setVal("close", new Common::JSONValue(false)); + } } else { if (_contentsStream->size() - _contentsStream->pos() <= UPLOAD_PER_ONE_REQUEST) { url += "finish"; -- 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 ++++++++++++---------- .../cloud/dropbox/dropboxlistdirectoryrequest.h | 18 ++-- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- backends/cloud/dropbox/dropboxstorage.h | 8 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 1 - backends/cloud/folderdownloadrequest.cpp | 14 +++- backends/cloud/folderdownloadrequest.h | 3 +- .../onedrive/onedrivelistdirectoryrequest.cpp | 52 +++++++----- .../cloud/onedrive/onedrivelistdirectoryrequest.h | 10 +-- backends/cloud/onedrive/onedrivestorage.cpp | 2 +- backends/cloud/onedrive/onedrivestorage.h | 6 +- backends/cloud/savessyncrequest.cpp | 13 ++- backends/cloud/savessyncrequest.h | 2 +- backends/cloud/storage.h | 30 ++++++- 14 files changed, 156 insertions(+), 102 deletions(-) (limited to 'backends/cloud') 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 diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 8539be1e1e..3c7c1fd464 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -35,20 +35,18 @@ class DropboxListDirectoryRequest: public Networking::Request { Common::String _requestedPath; bool _requestedRecursive; - Storage::FileArrayCallback _filesCallback; + Storage::ListDirectoryCallback _listDirectoryCallback; Common::String _token; - bool _complete; Common::Array _files; - Request *_innerRequest; - + Request *_workingRequest; + bool _ignoreCallback; + + void start(); void responseCallback(Networking::JsonResponse pair); - void startupWork(); - - void finishFiles(Common::Array &files); - + void finishStatus(ListDirectoryStatus status); public: - DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); - virtual ~DropboxListDirectoryRequest() { delete _filesCallback; } + DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, bool recursive = false); + virtual ~DropboxListDirectoryRequest(); virtual void handle(); virtual void restart(); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index ab3f5d0874..4a17afe6c6 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -125,7 +125,7 @@ void DropboxStorage::printUploadStatus(UploadResponse pair) { } } -Networking::Request *DropboxStorage::listDirectory(Common::String path, FileArrayCallback outerCallback, bool recursive) { +Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, bool recursive) { return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); } diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index ca285802a4..d9967d69f6 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -67,10 +67,10 @@ public: /** Public Cloud API comes down there. */ - /** Returns Common::Array. */ - virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); - - /** Calls the callback when finished. */ + /** Returns ListDirectoryStatus struct with list of files. */ + virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive = false); + + /** Returns UploadStatus struct with info about uploaded file. */ virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback); virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback); diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index e422793bc4..e64a8837b8 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -45,7 +45,6 @@ DropboxUploadRequest::~DropboxUploadRequest() { delete _uploadCallback; } - void DropboxUploadRequest::start() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 00bddb9f09..db132ffc8a 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -50,15 +50,21 @@ void FolderDownloadRequest::start() { //list directory first _workingRequest = _storage->listDirectory( _remoteDirectoryPath, - new Common::Callback(this, &FolderDownloadRequest::directoryListedCallback), + new Common::Callback(this, &FolderDownloadRequest::directoryListedCallback), _recursive ); } -void FolderDownloadRequest::directoryListedCallback(Storage::FileArrayResponse pair) { +void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) { if (_ignoreCallback) return; - //TODO: somehow ListDirectory requests must indicate that file array is incomplete - _files = pair.value; + + ListDirectoryStatus status = pair.value; + if (status.failed || status.interrupted) { + finish(); + return; + } + + _files = pair.value.files; downloadNextFile(); } diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 33fa5992c6..779ea3334f 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -26,7 +26,6 @@ #include "backends/networking/curl/request.h" #include "backends/networking/curl/networkreadstream.h" #include "backends/cloud/storage.h" -#include "common/file.h" namespace Cloud { @@ -41,7 +40,7 @@ class FolderDownloadRequest: public Networking::Request { bool _ignoreCallback; void start(); - void directoryListedCallback(Storage::FileArrayResponse pair); + void directoryListedCallback(Storage::ListDirectoryResponse pair); void fileDownloadedCallback(Storage::BoolResponse pair); void downloadNextFile(); void finishFiles(Common::Array &files); diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index f1402c43b2..dbd5e44c0b 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -25,18 +25,25 @@ #include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/iso8601.h" #include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/networkreadstream.h" #include "common/json.h" namespace Cloud { namespace OneDrive { -OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::FileArrayCallback cb, bool recursive): +OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, bool recursive): Networking::Request(0), - _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _filesCallback(cb), + _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), _workingRequest(nullptr), _ignoreCallback(false) { start(); } +OneDriveListDirectoryRequest::~OneDriveListDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _listDirectoryCallback; +} + void OneDriveListDirectoryRequest::start() { //cleanup _ignoreCallback = true; @@ -48,12 +55,12 @@ void OneDriveListDirectoryRequest::start() { _ignoreCallback = false; _directoriesQueue.push_back(_requestedPath); - listNextDirectory(); + listNextDirectory(_files); } -void OneDriveListDirectoryRequest::listNextDirectory() { +void OneDriveListDirectoryRequest::listNextDirectory(ListDirectoryStatus status) { if (_directoriesQueue.empty()) { - finishFiles(_files); + finishStatus(status); return; } @@ -76,7 +83,8 @@ void OneDriveListDirectoryRequest::makeRequest(Common::String url) { _workingRequest = ConnMan.addRequest(request); } -void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse pair) { +void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse pair) { + _workingRequest = nullptr; Common::JSONValue *json = pair.value; if (_ignoreCallback) { @@ -84,26 +92,29 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo return; } + ListDirectoryStatus status(_files); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request; + if (rq && rq->getNetworkReadStream()) + status.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + if (!json) { - finish(); + status.failed = true; + finishStatus(status); return; } Common::JSONObject response = json->asObject(); - //TODO: check that all keys exist to avoid segfaults + //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults Common::JSONArray items = response.getVal("value")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { Common::JSONObject item = items[i]->asObject(); Common::String path = _currentDirectory + item.getVal("name")->asString(); - bool isDirectory = item.contains("folder"); - uint32 size = 0, timestamp = 0; - //if (!isDirectory) { - size = item.getVal("size")->asNumber(); - timestamp = ISO8601::convertToTimestamp(item.getVal("lastModifiedDateTime")->asString()); - //} + bool isDirectory = item.contains("folder"); + uint32 size = item.getVal("size")->asIntegerNumber(); + uint32 timestamp = ISO8601::convertToTimestamp(item.getVal("lastModifiedDateTime")->asString()); StorageFile file(path, size, timestamp, isDirectory); _files.push_back(file); @@ -116,21 +127,22 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo if (hasMore) { makeRequest(response.getVal("@odata.nextLink")->asString()); } else { - listNextDirectory(); + listNextDirectory(status); } delete json; } -void OneDriveListDirectoryRequest::finish() { - //TODO: indicate it's interrupted +void OneDriveListDirectoryRequest::finish() { Common::Array files; - finishFiles(files); + ListDirectoryStatus status(files); + status.interrupted = true; + finishStatus(status); } -void OneDriveListDirectoryRequest::finishFiles(Common::Array &files) { +void OneDriveListDirectoryRequest::finishStatus(ListDirectoryStatus status) { Request::finish(); - if (_filesCallback) (*_filesCallback)(Storage::FileArrayResponse(this, files)); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, status)); } } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h index ce407c041e..a05dd871dd 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h @@ -37,7 +37,7 @@ class OneDriveListDirectoryRequest: public Networking::Request { Common::String _requestedPath; bool _requestedRecursive; OneDriveStorage *_storage; - Storage::FileArrayCallback _filesCallback; + Storage::ListDirectoryCallback _listDirectoryCallback; Common::Array _files; Common::Array _directoriesQueue; Common::String _currentDirectory; @@ -45,13 +45,13 @@ class OneDriveListDirectoryRequest: public Networking::Request { bool _ignoreCallback; void start(); - void listNextDirectory(); + void listNextDirectory(ListDirectoryStatus status); void listedDirectoryCallback(Networking::JsonResponse pair); void makeRequest(Common::String url); - void finishFiles(Common::Array &files); + void finishStatus(ListDirectoryStatus status); public: - OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::FileArrayCallback cb, bool recursive = false); - virtual ~OneDriveListDirectoryRequest() { delete _filesCallback; } + OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, bool recursive = false); + virtual ~OneDriveListDirectoryRequest(); virtual void handle() {} virtual void restart() { start(); } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index c8b4ab1ad3..19e497258b 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -163,7 +163,7 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out delete pair.value; } -Networking::Request *OneDriveStorage::listDirectory(Common::String path, FileArrayCallback callback, bool recursive) { +Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive) { return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, recursive)); } diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 7028667819..55d039653a 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -72,10 +72,10 @@ public: /** Public Cloud API comes down there. */ - /** Returns Common::Array. */ - virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false); + /** Returns ListDirectoryStatus struct with list of files. */ + virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive = false); - /** Calls the callback when finished. */ + /** Returns UploadStatus struct with info about uploaded file. */ virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) { return nullptr; } //TODO virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) { return nullptr; } diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index be1075cb4d..96386ee62c 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -55,17 +55,22 @@ void SavesSyncRequest::start() { loadTimestamps(); //list saves directory - _workingRequest = _storage->listDirectory("saves", new Common::Callback(this, &SavesSyncRequest::directoryListedCallback)); + _workingRequest = _storage->listDirectory("saves", new Common::Callback(this, &SavesSyncRequest::directoryListedCallback)); } -void SavesSyncRequest::directoryListedCallback(Storage::FileArrayResponse pair) { +void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) { if (_ignoreCallback) return; - //TODO: somehow ListDirectory requests must indicate that file array is incomplete + + ListDirectoryStatus status = pair.value; + if (status.interrupted || status.failed) { + finishBool(false); + return; + } const uint32 INVALID_TIMESTAMP = UINT_MAX; //determine which files to download and which files to upload - Common::Array &remoteFiles = pair.value; + Common::Array &remoteFiles = status.files; for (uint32 i = 0; i < remoteFiles.size(); ++i) { StorageFile &file = remoteFiles[i]; if (file.isDirectory()) continue; diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index dca1fb750b..f2f2aba403 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -42,7 +42,7 @@ class SavesSyncRequest: public Networking::Request { bool _ignoreCallback; void start(); - void directoryListedCallback(Storage::FileArrayResponse pair); + void directoryListedCallback(Storage::ListDirectoryResponse pair); void fileDownloadedCallback(Storage::BoolResponse pair); void fileUploadedCallback(Storage::UploadResponse pair); void downloadNextFile(); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 1749881a7d..311b3fdc9f 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -54,17 +54,39 @@ struct UploadStatus { interrupted(interrupt), failed(failure), file(f), response(resp), httpResponseCode(code) {} }; +/** Struct to represent upload() resulting status. */ +struct ListDirectoryStatus { + /** true if Request was interrupted (finished by user with finish()) */ + bool interrupted; + /** true if Request has failed (bad server response or some other error occurred) */ + bool failed; + /** Contains listed files (might be incomplete if failed or interrupted) */ + Common::Array &files; + /** Server's original response (empty if not failed) */ + Common::String response; + /** Server's HTTP response code. */ + long httpResponseCode; + + ListDirectoryStatus(Common::Array &f) : + interrupted(false), failed(false), files(f), response(), httpResponseCode(-1) {} + + ListDirectoryStatus(bool interrupt, bool failure, Common::Array &f, Common::String resp, long code) : + interrupted(interrupt), failed(failure), files(f), response(resp), httpResponseCode(code) {} +}; + class Storage { public: typedef Networking::Response&> FileArrayResponse; typedef Networking::Response StorageInfoResponse; typedef Networking::Response BoolResponse; typedef Networking::Response UploadResponse; + typedef Networking::Response ListDirectoryResponse; typedef Common::BaseCallback *FileArrayCallback; typedef Common::BaseCallback *StorageInfoCallback; typedef Common::BaseCallback *BoolCallback; typedef Common::BaseCallback *UploadCallback; + typedef Common::BaseCallback *ListDirectoryCallback; Storage() {} virtual ~Storage() {} @@ -90,10 +112,10 @@ public: * a callback, which is called, when request is complete. */ - /** Returns Common::Array. */ - virtual Networking::Request *listDirectory(Common::String path, FileArrayCallback callback, bool recursive = false) = 0; - - /** Calls the callback when finished. */ + /** Returns ListDirectoryStatus struct with list of files. */ + virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive = false) = 0; + + /** Returns UploadStatus struct with info about uploaded file. */ virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) = 0; virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) = 0; -- cgit v1.2.3 From af37ecca3430c871ec8a03bcada90303e6bf9877 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 30 May 2016 21:21:31 +0600 Subject: CLOUD: Make SavesSyncRequest work It now actually read the "timestamps" file, loads and saves files as it should, ignores Dropbox's "not_found" error. --- backends/cloud/dropbox/dropboxstorage.cpp | 16 +++- backends/cloud/savessyncrequest.cpp | 132 +++++++++++++++++++++++------- backends/cloud/savessyncrequest.h | 6 +- 3 files changed, 121 insertions(+), 33 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 4a17afe6c6..b33e2b6776 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -33,6 +33,9 @@ #include "common/file.h" #include "common/json.h" #include +#include "common/system.h" +#include "common/savefile.h" +#include "../savessyncrequest.h" namespace Cloud { namespace Dropbox { @@ -188,7 +191,18 @@ Networking::Request *DropboxStorage::syncSaves(BoolCallback callback) { false ); */ - return upload("/remote/test4.bmp", "final.bmp", new Common::Callback(this, &DropboxStorage::printUploadStatus)); + /* + debug("%s", ConfMan.get("savepath").c_str()); + Common::StringArray arr = g_system->getSavefileManager()->listSavefiles("*"); + for (uint32 i = 0; i < arr.size(); ++i) { + debug("%s", arr[i].c_str()); + } + debug("EOL"); + */ + //return upload("/remote/backslash", "C:\\Users\\Tkachov\\AppData\\Roaming\\ScummVM\\Saved games\\sword25.000", new Common::Callback(this, &DropboxStorage::printUploadStatus)); + //return upload("/remote/slash", "C:/Users/Tkachov/AppData/Roaming/ScummVM/Saved games/sword25.000", new Common::Callback(this, &DropboxStorage::printUploadStatus)); + return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &DropboxStorage::printBool))); + //return upload("/remote/test4.bmp", "final.bmp", new Common::Callback(this, &DropboxStorage::printUploadStatus)); } Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) { diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 96386ee62c..e632bfff84 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -21,13 +21,17 @@ */ #include "backends/cloud/savessyncrequest.h" +#include "common/config-manager.h" #include "common/debug.h" #include "common/file.h" -#include "common/system.h" #include "common/savefile.h" +#include "common/system.h" +#include namespace Cloud { +const char *SavesSyncRequest::TIMESTAMPS_FILENAME = "timestamps"; + SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback): Request(nullptr), _storage(storage), _boolCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { @@ -55,25 +59,44 @@ void SavesSyncRequest::start() { loadTimestamps(); //list saves directory - _workingRequest = _storage->listDirectory("saves", new Common::Callback(this, &SavesSyncRequest::directoryListedCallback)); + _workingRequest = _storage->listDirectory("/saves", new Common::Callback(this, &SavesSyncRequest::directoryListedCallback)); } void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) { + _workingRequest = nullptr; if (_ignoreCallback) return; ListDirectoryStatus status = pair.value; - if (status.interrupted || status.failed) { + bool irrecoverable = status.interrupted || status.failed; + if (status.failed) { + Common::JSONValue *value = Common::JSON::parse(status.response.c_str()); + if (value) { + if (value->isObject()) { + Common::JSONObject object = value->asObject(); + //Dropbox-related error: + if (object.contains("error_summary")) { + Common::String summary = object.getVal("error_summary")->asString(); + if (summary.contains("not_found")) { + //oh how lucky we are! It's just user don't have /cloud/ folder yet! + irrecoverable = false; + } + } + } + delete value; + } + } + + if (irrecoverable) { finishBool(false); return; } - - const uint32 INVALID_TIMESTAMP = UINT_MAX; //determine which files to download and which files to upload Common::Array &remoteFiles = status.files; for (uint32 i = 0; i < remoteFiles.size(); ++i) { StorageFile &file = remoteFiles[i]; if (file.isDirectory()) continue; + if (file.name() == TIMESTAMPS_FILENAME) continue; Common::String name = file.name(); if (!_localFilesTimestamps.contains(name)) _filesToDownload.push_back(file); @@ -92,14 +115,24 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pa } } - //TODO: upload files which are added to local directory (not available on cloud), but have no timestamp - //upload files with invalid timestamp (the ones we've added - means they might not have any remote version) for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { + if (i->_key == TIMESTAMPS_FILENAME) continue; if (i->_value == INVALID_TIMESTAMP) _filesToUpload.push_back(i->_key); } + /////// + debug("\ndownload files:"); + for (uint32 i = 0; i < _filesToDownload.size(); ++i) { + debug("%s", _filesToDownload[i].name().c_str()); + } + debug("\nupload files:"); + for (uint32 i = 0; i < _filesToUpload.size(); ++i) { + debug("%s", _filesToUpload[i].c_str()); + } + /////// + //start downloading files downloadNextFile(); } @@ -113,12 +146,16 @@ void SavesSyncRequest::downloadNextFile() { _currentDownloadingFile = _filesToDownload.back(); _filesToDownload.pop_back(); - _workingRequest = _storage->download(_currentDownloadingFile.path(), "saves/" + _currentDownloadingFile.name(), //TODO: real saves folder here + /////// + debug("downloading %s", _currentDownloadingFile.name().c_str()); + /////// + _workingRequest = _storage->download(_currentDownloadingFile.path(), concatWithSavesPath(_currentDownloadingFile.name()), new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback) ); } void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse pair) { + _workingRequest = nullptr; if (_ignoreCallback) return; //stop syncing if download failed @@ -143,12 +180,16 @@ void SavesSyncRequest::uploadNextFile() { _currentUploadingFile = _filesToUpload.back(); _filesToUpload.pop_back(); - _workingRequest = _storage->upload("saves/" + _currentUploadingFile, g_system->getSavefileManager()->openForLoading(_currentUploadingFile), + /////// + debug("uploading %s", _currentUploadingFile.c_str()); + /////// + _workingRequest = _storage->upload("/saves/" + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback) ); } void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse pair) { + _workingRequest = nullptr; if (_ignoreCallback) return; UploadStatus status = pair.value; @@ -181,16 +222,24 @@ void SavesSyncRequest::finishBool(bool success) { } void SavesSyncRequest::loadTimestamps() { - Common::File f; - //TODO: real saves folder here - if (!f.open("saves/timestamps")) - error("SavesSyncRequest: failed to open 'saves/timestamps' file to load timestamps"); + //start with listing all the files in saves/ directory and setting invalid timestamp to them + Common::StringArray localFiles = g_system->getSavefileManager()->listSavefiles("*"); + for (uint32 i = 0; i < localFiles.size(); ++i) + _localFilesTimestamps[localFiles[i]] = INVALID_TIMESTAMP; + + //now actually load timestamps from file + Common::InSaveFile *file = g_system->getSavefileManager()->openRawFile(TIMESTAMPS_FILENAME); + if (!file) { + warning("SavesSyncRequest: failed to open '%s' file to load timestamps", TIMESTAMPS_FILENAME); + return; + } + - while (!f.eos()) { + while (!file->eos()) { //read filename into buffer (reading until the first ' ') Common::String buffer; - while (!f.eos()) { - byte b = f.readByte(); + while (!file->eos()) { + byte b = file->readByte(); if (b == ' ') break; buffer += (char)b; } @@ -199,8 +248,8 @@ void SavesSyncRequest::loadTimestamps() { Common::String filename = buffer; bool lineEnded = false; buffer = ""; - while (!f.eos()) { - byte b = f.readByte(); + while (!file->eos()) { + byte b = file->readByte(); if (b == ' ' || b == '\n' || b == '\r') { lineEnded = (b == '\n'); break; @@ -210,32 +259,53 @@ void SavesSyncRequest::loadTimestamps() { //parse timestamp uint timestamp = atol(buffer.c_str()); + if (buffer == "" || timestamp == 0) break; _localFilesTimestamps[filename] = timestamp; //read until the end of the line if (!lineEnded) { - while (!f.eos()) { - byte b = f.readByte(); + while (!file->eos()) { + byte b = file->readByte(); if (b == '\n') break; } } } - - f.close(); + + delete file; } void SavesSyncRequest::saveTimestamps() { - Common::DumpFile f; - //TODO: real saves folder here - if (!f.open("saves/timestamps", true)) - error("SavesSyncRequest: failed to open 'saves/timestamps' file to save timestamps"); - Common::String data; - for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) - data += i->_key + Common::String::format(" %u\n", i->_value); - if (f.write(data.c_str(), data.size()) != data.size()) - error("SavesSyncRequest: failed to write timestamps data into 'saves/timestamps'"); + Common::DumpFile f; + Common::String filename = concatWithSavesPath(TIMESTAMPS_FILENAME); + if (!f.open(filename, true)) { + warning("SavesSyncRequest: failed to open '%s' file to save timestamps", filename.c_str()); + return; + } + + for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { + Common::String data = i->_key + Common::String::format(" %u\n", i->_value); + if (f.write(data.c_str(), data.size()) != data.size()) { + warning("SavesSyncRequest: failed to write timestamps data into '%s'", filename.c_str()); + return; + } + } + f.close(); } +Common::String SavesSyncRequest::concatWithSavesPath(Common::String name) { + Common::String path = ConfMan.get("savepath"); + if (path.size() > 0 && (path.lastChar() == '/' || path.lastChar() == '\\')) + return path + name; + + //simple heuristic to determine which path separator to use + int backslashes = 0; + for (uint32 i = 0; i < path.size(); ++i) + if (path[i] == '/') --backslashes; + else if (path[i] == '\\') ++backslashes; + + if (backslashes) return path + '\\' + name; + return path + '/' + name; +} } // End of namespace Cloud diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index f2f2aba403..da7b27e9b6 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -31,6 +31,9 @@ namespace Cloud { class SavesSyncRequest: public Networking::Request { + const uint32 INVALID_TIMESTAMP = UINT_MAX; + static const char *TIMESTAMPS_FILENAME; + Storage *_storage; Storage::BoolCallback _boolCallback; Common::HashMap _localFilesTimestamps; @@ -49,7 +52,8 @@ class SavesSyncRequest: public Networking::Request { void uploadNextFile(); void finishBool(bool success); void loadTimestamps(); - void saveTimestamps(); + void saveTimestamps(); + Common::String concatWithSavesPath(Common::String name); public: SavesSyncRequest(Storage *storage, Storage::BoolCallback callback); virtual ~SavesSyncRequest(); -- cgit v1.2.3 From 001b417f33beeb3b2da11f58105b971dc7e6f600 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 30 May 2016 22:18:33 +0600 Subject: CLOUD: Fix OneDriveTokenRefresher It was calling finish(), causing stack overflow. Some minor changes are added also. --- backends/cloud/onedrive/onedrivestorage.cpp | 9 ++++++++- backends/cloud/onedrive/onedrivestorage.h | 1 + backends/cloud/onedrive/onedrivetokenrefresher.cpp | 22 +++++++++++++++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 19e497258b..b0f4f7be65 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -35,6 +35,7 @@ #include "common/json.h" #include "common/system.h" #include +#include "../savessyncrequest.h" namespace Cloud { namespace OneDrive { @@ -205,6 +206,11 @@ void OneDriveStorage::printFiles(FileArrayResponse pair) { debug("\t%s", files[i].path().c_str()); } +void OneDriveStorage::printBool(BoolResponse pair) { + debug("bool: %s", pair.value ? "true" : "false"); +} + + Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { //this is not the real syncSaves() implementation /* @@ -213,7 +219,8 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); */ - return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback(this, &OneDriveStorage::printFiles), false); + //return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback(this, &OneDriveStorage::printFiles), false); + return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool))); } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 55d039653a..43675fbfa5 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -52,6 +52,7 @@ class OneDriveStorage: public Cloud::Storage { void printJson(Networking::JsonResponse pair); void fileDownloaded(BoolResponse pair); void printFiles(FileArrayResponse pair); + void printBool(BoolResponse pair); void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse pair); public: diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index d932f9ab17..a0c41ff471 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -60,7 +60,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (!json) { //notify user of failure warning("OneDriveTokenRefresher: got NULL instead of JSON"); - CurlJsonRequest::finish(); + CurlJsonRequest::finishJson(nullptr); return; } @@ -72,8 +72,24 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { } Common::JSONObject error = result.getVal("error")->asObject(); - debug("code = %s", error.getVal("code")->asString().c_str()); - debug("message = %s", error.getVal("message")->asString().c_str()); + bool irrecoverable = true; + + if (error.contains("code")) { + Common::String code = error.getVal("code")->asString(); + debug("code = %s", code.c_str()); + //if (code == "itemNotFound") irrecoverable = true; + } + + if (error.contains("message")) { + Common::String message = error.getVal("message")->asString(); + debug("message = %s", message.c_str()); + } + + if (irrecoverable) { + CurlJsonRequest::finishJson(nullptr); + return; + } + pause(); delete json; _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); -- 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. --- backends/cloud/downloadrequest.cpp | 68 ++++++---- backends/cloud/downloadrequest.h | 23 ++-- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 72 +++++----- .../cloud/dropbox/dropboxlistdirectoryrequest.h | 8 +- backends/cloud/dropbox/dropboxstorage.cpp | 123 +++++++---------- backends/cloud/dropbox/dropboxstorage.h | 33 +++-- backends/cloud/dropbox/dropboxuploadrequest.cpp | 81 ++++++----- backends/cloud/dropbox/dropboxuploadrequest.h | 8 +- backends/cloud/folderdownloadrequest.cpp | 49 ++++--- backends/cloud/folderdownloadrequest.h | 15 +- backends/cloud/manager.cpp | 4 +- backends/cloud/manager.h | 2 +- .../onedrive/onedrivelistdirectoryrequest.cpp | 56 ++++---- .../cloud/onedrive/onedrivelistdirectoryrequest.h | 14 +- backends/cloud/onedrive/onedrivestorage.cpp | 72 +++++----- backends/cloud/onedrive/onedrivestorage.h | 39 +++--- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 42 +++--- backends/cloud/onedrive/onedrivetokenrefresher.h | 12 +- backends/cloud/savessyncrequest.cpp | 151 ++++++++++++++------- backends/cloud/savessyncrequest.h | 17 ++- backends/cloud/storage.h | 66 ++------- 21 files changed, 493 insertions(+), 462 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 8d5e244e45..7dde74f88d 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -27,31 +27,55 @@ namespace Cloud { -DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callback, Common::String remoteFile, Common::DumpFile *dumpFile): - Request(0), _boolCallback(callback), _remoteFileStream(0), _localFile(dumpFile) { - storage->streamFile(remoteFile, new Common::Callback(this, &DownloadRequest::streamCallback)); +DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFile, Common::DumpFile *dumpFile): + Request(nullptr, ecb), _boolCallback(callback), _localFile(dumpFile), _remoteFileName(remoteFile), _storage(storage), + _remoteFileStream(nullptr), _workingRequest(nullptr), _ignoreCallback(false) { + start(); } -void DownloadRequest::streamCallback(Networking::NetworkReadStreamResponse pair) { - if (!pair.value) { - warning("DownloadRequest: no ReadStream passed"); - finish(); - return; - } +DownloadRequest::~DownloadRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; + delete _localFile; +} + +void DownloadRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _remoteFileStream = nullptr; + //TODO: reopen DumpFile + _ignoreCallback = false; + + _workingRequest = _storage->streamFile( + _remoteFileName, + new Common::Callback(this, &DownloadRequest::streamCallback), + new Common::Callback(this, &DownloadRequest::streamErrorCallback) + ); +} - _remoteFileStream = (Networking::NetworkReadStream *)pair.value; +void DownloadRequest::streamCallback(Networking::NetworkReadStreamResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + _remoteFileStream = (Networking::NetworkReadStream *)response.value; +} + +void DownloadRequest::streamErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); } void DownloadRequest::handle() { if (!_localFile) { warning("DownloadRequest: no file to write"); - finish(); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; } if (!_localFile->isOpen()) { warning("DownloadRequest: failed to open file to write"); - finish(); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; } @@ -67,7 +91,7 @@ void DownloadRequest::handle() { if (readBytes != 0) if (_localFile->write(buf, readBytes) != readBytes) { warning("DownloadRequest: unable to write all received bytes into output file"); - finish(); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; } @@ -77,26 +101,20 @@ void DownloadRequest::handle() { //TODO: do something about it actually } - finishBool(_remoteFileStream->httpResponseCode() == 200); + finishSuccess(_remoteFileStream->httpResponseCode() == 200); _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() } } void DownloadRequest::restart() { - //this request doesn't know anything about the _remoteFileStream it's reading - //thus, it can't restart it - warning("DownloadRequest: cannot be restarted"); - finish(); - //TODO: fix that -} - -void DownloadRequest::finish() { - finishBool(false); + warning("DownloadRequest: can't restart as there are no means to reopen DumpFile"); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); + //start(); } -void DownloadRequest::finishBool(bool success) { - Request::finish(); +void DownloadRequest::finishSuccess(bool success) { + Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index 0bad5df279..9e3421d777 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -31,23 +31,24 @@ namespace Cloud { class DownloadRequest: public Networking::Request { - Storage::BoolCallback _boolCallback; + Storage::BoolCallback _boolCallback; + Common::DumpFile *_localFile; + Common::String _remoteFileName; + Storage *_storage; Networking::NetworkReadStream *_remoteFileStream; - Common::DumpFile *_localFile; + Request *_workingRequest; + bool _ignoreCallback; - void streamCallback(Networking::NetworkReadStreamResponse pair); - - void finishBool(bool success); + void start(); + void streamCallback(Networking::NetworkReadStreamResponse response); + void streamErrorCallback(Networking::ErrorResponse error); + void finishSuccess(bool success); public: - DownloadRequest(Storage *storage, Storage::BoolCallback callback, Common::String remoteFile, Common::DumpFile *dumpFile); - virtual ~DownloadRequest() { - delete _boolCallback; - delete _localFile; - } + DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFile, Common::DumpFile *dumpFile); + virtual ~DownloadRequest(); virtual void handle(); virtual void restart(); - virtual void finish(); }; } // End of namespace Cloud 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 diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 3c7c1fd464..3a83af06aa 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -42,15 +42,15 @@ class DropboxListDirectoryRequest: public Networking::Request { bool _ignoreCallback; void start(); - void responseCallback(Networking::JsonResponse pair); - void finishStatus(ListDirectoryStatus status); + void responseCallback(Networking::JsonResponse response); + void errorCallback(Networking::ErrorResponse error); + void finishSuccess(Common::Array &files); public: - DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, bool recursive = false); + DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); virtual ~DropboxListDirectoryRequest(); virtual void handle(); virtual void restart(); - virtual void finish(); }; } // End of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index b33e2b6776..d22e0abf60 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -96,118 +96,93 @@ void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); } -void DropboxStorage::printFiles(FileArrayResponse pair) { +void DropboxStorage::printFiles(FileArrayResponse response) { debug("files:"); - Common::Array &files = pair.value; + Common::Array &files = response.value; for (uint32 i = 0; i < files.size(); ++i) debug("\t%s", files[i].name().c_str()); } -void DropboxStorage::printBool(BoolResponse pair) { - debug("bool: %s", (pair.value?"true":"false")); +void DropboxStorage::printBool(BoolResponse response) { + debug("bool: %s", (response.value?"true":"false")); } -void DropboxStorage::printUploadStatus(UploadResponse pair) { - debug(" "); - UploadStatus status = pair.value; - if (status.interrupted) { - debug("upload interrupted by user"); - return; - } - if (status.failed) { - debug("upload failed with following response:"); - debug("%s", status.response.c_str()); - return; - } - debug("upload HTTP response code = %ld", status.httpResponseCode); - if (!status.failed) { - debug("uploaded file info:"); - debug("\tpath: %s", status.file.path().c_str()); - debug("\tsize: %u", status.file.size()); - debug("\ttimestamp: %u", status.file.timestamp()); - } +void DropboxStorage::printStorageFile(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()); } -Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, bool recursive) { - return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, recursive)); +void DropboxStorage::printErrorResponse(Networking::ErrorResponse error) { + debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug("%s", error.response.c_str()); } -Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) { - return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback)); +Networking::ErrorCallback DropboxStorage::getErrorPrintingCallback() { + return new Common::Callback(this, &DropboxStorage::printErrorResponse); } -Networking::Request *DropboxStorage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback) { +Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, Networking::ErrorCallback errorCallback, bool recursive) { + return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive)); +} + +Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback 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"); - UploadStatus status(false, true, StorageFile(), "", -1); - if (callback) (*callback)(UploadResponse(nullptr, status)); + if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1)); + delete errorCallback; + delete callback; delete f; return nullptr; } - return upload(remotePath, f, callback); + return upload(remotePath, f, callback, errorCallback); } -Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) { +Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("path", new Common::JSONValue(path)); Common::JSONValue value(jsonRequestParameters); - Networking::CurlRequest *request = new Networking::CurlRequest(0, "https://content.dropboxapi.com/2/files/download"); + Networking::CurlRequest *request = new Networking::CurlRequest(nullptr, nullptr, "https://content.dropboxapi.com/2/files/download"); //TODO: is it right? request->addHeader("Authorization: Bearer " + _token); request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); request->addHeader("Content-Type: "); //required to be empty (as we do POST, it's usually app/form-url-encoded) - Networking::NetworkReadStreamResponse pair = request->execute(); - if (callback) (*callback)(pair); - return pair.request; + Networking::NetworkReadStreamResponse response = request->execute(); + if (callback) (*callback)(response); + return response.request; } -Networking::Request *DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { +Networking::Request *DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { Common::DumpFile *f = new Common::DumpFile(); if (!f->open(localPath, true)) { warning("DropboxStorage: unable to open file to download into"); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1)); delete f; return nullptr; } - return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); + return ConnMan.addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); } -Networking::Request *DropboxStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive) { - return ConnMan.addRequest(new FolderDownloadRequest(this, callback, remotePath, localPath, recursive)); +Networking::Request *DropboxStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); } -Networking::Request *DropboxStorage::syncSaves(BoolCallback callback) { - //this is not the real syncSaves() implementation - //"" 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(this, &DropboxStorage::printFiles), - false - ); - */ - /* - debug("%s", ConfMan.get("savepath").c_str()); - Common::StringArray arr = g_system->getSavefileManager()->listSavefiles("*"); - for (uint32 i = 0; i < arr.size(); ++i) { - debug("%s", arr[i].c_str()); - } - debug("EOL"); - */ - //return upload("/remote/backslash", "C:\\Users\\Tkachov\\AppData\\Roaming\\ScummVM\\Saved games\\sword25.000", new Common::Callback(this, &DropboxStorage::printUploadStatus)); - //return upload("/remote/slash", "C:/Users/Tkachov/AppData/Roaming/ScummVM/Saved games/sword25.000", new Common::Callback(this, &DropboxStorage::printUploadStatus)); - return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &DropboxStorage::printBool))); - //return upload("/remote/test4.bmp", "final.bmp", new Common::Callback(this, &DropboxStorage::printUploadStatus)); +Networking::Request *DropboxStorage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { + //this might be the real syncSaves() implementation + return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &DropboxStorage::printBool), getErrorPrintingCallback())); //TODO } -Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) { +Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.dropboxapi.com/1/account/info"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); return ConnMan.addRequest(request); //that callback bridge wraps the outerCallback (passed in arguments from user) into innerCallback @@ -216,8 +191,8 @@ Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback) { //and then calls the outerCallback (which wants to receive StorageInfo, not void *) } -void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse pair) { - Common::JSONValue *json = pair.value; +void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; if (!json) { warning("NULL passed instead of JSON"); delete outerCallback; @@ -241,11 +216,11 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ delete json; } -void DropboxStorage::infoMethodCallback(StorageInfoResponse pair) { +void DropboxStorage::infoMethodCallback(StorageInfoResponse response) { debug("\nStorage info:"); - debug("User name: %s", pair.value.name().c_str()); - debug("Email: %s", pair.value.email().c_str()); - debug("Disk usage: %u/%u", pair.value.used(), pair.value.available()); + debug("User name: %s", response.value.name().c_str()); + debug("Email: %s", response.value.email().c_str()); + debug("Disk usage: %u/%u", response.value.used(), response.value.available()); } DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { @@ -298,7 +273,7 @@ void DropboxStorage::authThroughConsole() { void DropboxStorage::getAccessToken(Common::String code) { Networking::JsonCallback callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://api.dropboxapi.com/1/oauth2/token"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, nullptr, "https://api.dropboxapi.com/1/oauth2/token"); //TODO request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + Common::String(KEY)); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index d9967d69f6..0082e5cebd 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -45,9 +45,12 @@ class DropboxStorage: public Cloud::Storage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); - void printFiles(FileArrayResponse pair); - void printBool(BoolResponse pair); - void printUploadStatus(UploadResponse pair); + void printFiles(FileArrayResponse response); + void printBool(BoolResponse response); + void printStorageFile(UploadResponse response); + void printErrorResponse(Networking::ErrorResponse error); + + Networking::ErrorCallback getErrorPrintingCallback(); public: virtual ~DropboxStorage(); @@ -68,38 +71,38 @@ public: /** Public Cloud API comes down there. */ /** Returns ListDirectoryStatus struct with list of files. */ - virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, 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. */ - virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback); - virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback); + 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. */ - virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback); + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ - virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback); + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Returns Common::Array with list of files, which were not downloaded. */ - virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false); + virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual Networking::Request *syncSaves(BoolCallback callback); + virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ - virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual Networking::Request *touch(Common::String path, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Returns the StorageInfo struct. */ - virtual Networking::Request *info(StorageInfoCallback callback); + virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); /** This method is passed into info(). (Temporary) */ - void infoMethodCallback(StorageInfoResponse pair); + void infoMethodCallback(StorageInfoResponse response); /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index e64a8837b8..50a1b8a612 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -32,8 +32,8 @@ namespace Cloud { namespace Dropbox { -DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback): - Networking::Request(0), _token(token), _savePath(path), _contentsStream(contents), _uploadCallback(callback), +DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _token(token), _savePath(path), _contentsStream(contents), _uploadCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { start(); } @@ -50,7 +50,7 @@ void DropboxUploadRequest::start() { if (_workingRequest) _workingRequest->finish(); if (!_contentsStream->seek(0)) { warning("DropboxUploadRequest: cannot restart because stream couldn't seek(0)"); - finish(); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); } _ignoreCallback = false; @@ -97,8 +97,9 @@ void DropboxUploadRequest::uploadNextPart() { } Common::JSONValue value(jsonRequestParameters); - Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxUploadRequest::partUploadedCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, url); + Networking::JsonCallback callback = new Common::Callback(this, &DropboxUploadRequest::partUploadedCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxUploadRequest::partUploadedErrorCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, url); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/octet-stream"); request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); @@ -110,46 +111,45 @@ void DropboxUploadRequest::uploadNextPart() { _workingRequest = ConnMan.addRequest(request); } -void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) { - if (_ignoreCallback) return; +void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse response) { + debug("partUploadedCallback"); _workingRequest = nullptr; + if (_ignoreCallback) return; - UploadStatus status; - Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)pair.request; + Networking::ErrorResponse error(this, false, true, "", -1); + 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) { bool needsFinishRequest = false; if (json->isObject()) { - Common::JSONObject response = json->asObject(); + Common::JSONObject object = 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()); + if (object.contains("error") || object.contains("error_summary")) { + warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); delete json; - status.failed = true; - status.response = json->stringify(true); - finishUpload(status); + error.response = json->stringify(true); + finishError(error); return; } - if (response.contains("server_modified")) { + if (object.contains("server_modified")) { //finished - Common::String path = response.getVal("path_lower")->asString(); - uint32 size = response.getVal("size")->asIntegerNumber(); - uint32 timestamp = ISO8601::convertToTimestamp(response.getVal("server_modified")->asString()); - status.file = StorageFile(path, size, timestamp, false); - finishUpload(status); + Common::String path = object.getVal("path_lower")->asString(); + uint32 size = object.getVal("size")->asIntegerNumber(); + uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("server_modified")->asString()); + finishSuccess(StorageFile(path, size, timestamp, false)); return; } if (_sessionId == "") { - if (response.contains("session_id")) - _sessionId = response.getVal("session_id")->asString(); + if (object.contains("session_id")) + _sessionId = object.getVal("session_id")->asString(); else warning("no session_id found in Dropbox's response"); needsFinishRequest = true; @@ -157,36 +157,33 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse pair) { } if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { - if (status.file.name() == "") { - status.file = StorageFile(_savePath, 0, 0, false); - warning("no file info to put into status"); - } - finishUpload(status); + warning("no file info to return"); + finishSuccess(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } } else { - warning("null, not json"); - status.failed = true; - finishUpload(status); + warning("null, not json"); + finishError(error); } delete json; } +void DropboxUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { + debug("partUploadedErrorCallback"); + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + void DropboxUploadRequest::handle() {} void DropboxUploadRequest::restart() { start(); } -void DropboxUploadRequest::finish() { - UploadStatus status; - status.interrupted = true; - finishUpload(status); -} - -void DropboxUploadRequest::finishUpload(UploadStatus status) { - Request::finish(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, status)); +void DropboxUploadRequest::finishSuccess(StorageFile file) { + Request::finishSuccess(); + if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); } } // End of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxuploadrequest.h b/backends/cloud/dropbox/dropboxuploadrequest.h index 9b68995969..a85d7ef883 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.h +++ b/backends/cloud/dropbox/dropboxuploadrequest.h @@ -42,16 +42,16 @@ class DropboxUploadRequest: public Networking::Request { void start(); void uploadNextPart(); - void partUploadedCallback(Networking::JsonResponse pair); - void finishUpload(UploadStatus status); + void partUploadedCallback(Networking::JsonResponse response); + void partUploadedErrorCallback(Networking::ErrorResponse error); + void finishSuccess(StorageFile status); public: - DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback); + DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb); virtual ~DropboxUploadRequest(); virtual void handle(); virtual void restart(); - virtual void finish(); }; } // End of namespace Dropbox diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index db132ffc8a..19f6c6c9b7 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -25,8 +25,8 @@ namespace Cloud { -FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive): - Request(nullptr), _storage(storage), _fileArrayCallback(callback), +FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive): + Request(nullptr, ecb), _storage(storage), _fileArrayCallback(callback), _remoteDirectoryPath(remoteDirectoryPath), _localDirectoryPath(localDirectoryPath), _recursive(recursive), _workingRequest(nullptr), _ignoreCallback(false) { start(); @@ -51,33 +51,39 @@ void FolderDownloadRequest::start() { _workingRequest = _storage->listDirectory( _remoteDirectoryPath, new Common::Callback(this, &FolderDownloadRequest::directoryListedCallback), + new Common::Callback(this, &FolderDownloadRequest::directoryListedErrorCallback), _recursive ); } -void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) { +void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryResponse response) { + _workingRequest = nullptr; if (_ignoreCallback) return; - - ListDirectoryStatus status = pair.value; - if (status.failed || status.interrupted) { - finish(); - return; - } - - _files = pair.value.files; + _files = response.value; downloadNextFile(); } -void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse pair) { +void FolderDownloadRequest::directoryListedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; if (_ignoreCallback) return; - if (!pair.value) _failedFiles.push_back(_currentFile); + if (!response.value) _failedFiles.push_back(_currentFile); downloadNextFile(); } +void FolderDownloadRequest::fileDownloadedErrorCallback(Networking::ErrorResponse error) { + fileDownloadedCallback(Storage::BoolResponse(error.request, false)); +} + void FolderDownloadRequest::downloadNextFile() { do { if (_files.empty()) { - finishFiles(_failedFiles); + finishSuccess(_failedFiles); return; } @@ -105,18 +111,17 @@ void FolderDownloadRequest::downloadNextFile() { debug("%s -> %s", remotePath.c_str(), localPath.c_str()); _workingRequest = _storage->download( remotePath, localPath, - new Common::Callback(this, &FolderDownloadRequest::fileDownloadedCallback) + new Common::Callback(this, &FolderDownloadRequest::fileDownloadedCallback), + new Common::Callback(this, &FolderDownloadRequest::fileDownloadedErrorCallback) ); } -void FolderDownloadRequest::finish() { - //TODO: somehow indicate that request was interrupted - Common::Array files; - finishFiles(files); -} +void FolderDownloadRequest::handle() {} + +void FolderDownloadRequest::restart() { start(); } -void FolderDownloadRequest::finishFiles(Common::Array &files) { - Request::finish(); +void FolderDownloadRequest::finishSuccess(Common::Array &files) { + Request::finishSuccess(); if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); } diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 779ea3334f..8fa3b1188b 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -40,17 +40,18 @@ class FolderDownloadRequest: public Networking::Request { bool _ignoreCallback; void start(); - void directoryListedCallback(Storage::ListDirectoryResponse pair); - void fileDownloadedCallback(Storage::BoolResponse pair); + void directoryListedCallback(Storage::ListDirectoryResponse response); + void directoryListedErrorCallback(Networking::ErrorResponse error); + void fileDownloadedCallback(Storage::BoolResponse response); + void fileDownloadedErrorCallback(Networking::ErrorResponse error); void downloadNextFile(); - void finishFiles(Common::Array &files); + void finishSuccess(Common::Array &files); public: - FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive); + FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive); virtual ~FolderDownloadRequest(); - virtual void handle() {} - virtual void restart() { start(); } - virtual void finish(); + virtual void handle(); + virtual void restart(); }; } // End of namespace Cloud diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 13f23b8e6e..2f1533c50d 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -110,9 +110,9 @@ Storage *Manager::getCurrentStorage() { return nullptr; } -void Manager::syncSaves(Storage::BoolCallback callback) { +void Manager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); - if (storage) storage->syncSaves(callback); + if (storage) storage->syncSaves(callback, errorCallback); } } // End of namespace Cloud diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index f472b80ae3..013e117046 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -42,7 +42,7 @@ public: virtual void addStorage(Cloud::Storage *storage, bool makeCurrent = true, bool saveConfig = true); virtual Storage *getCurrentStorage(); - virtual void syncSaves(Storage::BoolCallback callback); + virtual void syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback); }; } // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index dbd5e44c0b..e362600389 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -31,8 +31,8 @@ namespace Cloud { namespace OneDrive { -OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, bool recursive): - Networking::Request(0), +OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), _workingRequest(nullptr), _ignoreCallback(false) { start(); @@ -55,12 +55,12 @@ void OneDriveListDirectoryRequest::start() { _ignoreCallback = false; _directoriesQueue.push_back(_requestedPath); - listNextDirectory(_files); + listNextDirectory(); } -void OneDriveListDirectoryRequest::listNextDirectory(ListDirectoryStatus status) { +void OneDriveListDirectoryRequest::listNextDirectory() { if (_directoriesQueue.empty()) { - finishStatus(status); + finishSuccess(_files); return; } @@ -78,36 +78,37 @@ void OneDriveListDirectoryRequest::listNextDirectory(ListDirectoryStatus status) void OneDriveListDirectoryRequest::makeRequest(Common::String url) { Networking::JsonCallback callback = new Common::Callback(this, &OneDriveListDirectoryRequest::listedDirectoryCallback); - Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, url.c_str()); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &OneDriveListDirectoryRequest::listedDirectoryErrorCallback); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _storage->accessToken()); _workingRequest = ConnMan.addRequest(request); } -void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse pair) { +void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - Common::JSONValue *json = pair.value; + Common::JSONValue *json = response.value; if (_ignoreCallback) { delete json; 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(); if (!json) { - status.failed = true; - finishStatus(status); + error.failed = true; + finishError(error); return; } - Common::JSONObject response = json->asObject(); + Common::JSONObject object = json->asObject(); //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults - Common::JSONArray items = response.getVal("value")->asArray(); + Common::JSONArray items = object.getVal("value")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { Common::JSONObject item = items[i]->asObject(); @@ -123,26 +124,29 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo } } - bool hasMore = response.contains("@odata.nextLink"); + bool hasMore = object.contains("@odata.nextLink"); if (hasMore) { - makeRequest(response.getVal("@odata.nextLink")->asString()); + makeRequest(object.getVal("@odata.nextLink")->asString()); } else { - listNextDirectory(status); + listNextDirectory(); } delete json; } -void OneDriveListDirectoryRequest::finish() { - Common::Array files; - ListDirectoryStatus status(files); - status.interrupted = true; - finishStatus(status); +void OneDriveListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); } -void OneDriveListDirectoryRequest::finishStatus(ListDirectoryStatus status) { - Request::finish(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, status)); +void OneDriveListDirectoryRequest::handle() {} + +void OneDriveListDirectoryRequest::restart() { start(); } + +void OneDriveListDirectoryRequest::finishSuccess(Common::Array &files) { + Request::finishSuccess(); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h index a05dd871dd..b8adfe7ef0 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h @@ -45,17 +45,17 @@ class OneDriveListDirectoryRequest: public Networking::Request { bool _ignoreCallback; void start(); - void listNextDirectory(ListDirectoryStatus status); - void listedDirectoryCallback(Networking::JsonResponse pair); + void listNextDirectory(); + void listedDirectoryCallback(Networking::JsonResponse response); + void listedDirectoryErrorCallback(Networking::ErrorResponse error); void makeRequest(Common::String url); - void finishStatus(ListDirectoryStatus status); + void finishSuccess(Common::Array &files); public: - OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, bool recursive = false); + OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); virtual ~OneDriveListDirectoryRequest(); - virtual void handle() {} - virtual void restart() { start(); } - virtual void finish(); + virtual void handle(); + virtual void restart(); }; } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index b0f4f7be65..8746b7ab33 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -74,7 +74,7 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) } Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://login.live.com/oauth20_token.srf"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, getErrorPrintingCallback(), "https://login.live.com/oauth20_token.srf"); //TODO if (codeFlow) { request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); @@ -88,8 +88,8 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) ConnMan.addRequest(request); } -void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse pair) { - Common::JSONValue *json = pair.value; +void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; if (!json) { warning("OneDriveStorage: got NULL instead of JSON"); if (callback) (*callback)(BoolResponse(nullptr, false)); @@ -111,8 +111,8 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResp delete json; } -void OneDriveStorage::codeFlowComplete(BoolResponse pair) { - if (!pair.value) { +void OneDriveStorage::codeFlowComplete(BoolResponse response) { + if (!response.value) { warning("OneDriveStorage: failed to get access token through code flow"); return; } @@ -130,8 +130,8 @@ void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } -void OneDriveStorage::printJson(Networking::JsonResponse pair) { - Common::JSONValue *json = pair.value; +void OneDriveStorage::printJson(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; if (!json) { warning("printJson: NULL"); return; @@ -141,77 +141,85 @@ void OneDriveStorage::printJson(Networking::JsonResponse pair) { delete json; } -void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse pair) { - if (!pair.value) { +void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { + if (!response.value) { warning("fileInfoCallback: NULL"); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(pair.request, 0)); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); return; } - Common::JSONObject result = pair.value->asObject(); + Common::JSONObject result = response.value->asObject(); if (result.contains("@content.downloadUrl")) { const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse( - pair.request, + response.request, new Networking::NetworkReadStream(url, 0, "") )); } else { warning("downloadUrl not found in passed JSON"); - debug("%s", pair.value->stringify().c_str()); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(pair.request, 0)); + debug("%s", response.value->stringify().c_str()); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); } - delete pair.value; + delete response.value; } -Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive) { - return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, recursive)); +Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); } -Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback) { +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; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); - Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, url.c_str()); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _token); return ConnMan.addRequest(request); } -Networking::Request *OneDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback) { +Networking::Request *OneDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { Common::DumpFile *f = new Common::DumpFile(); if (!f->open(localPath, true)) { warning("OneDriveStorage: unable to open file to download into"); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1)); delete f; return nullptr; } - return ConnMan.addRequest(new DownloadRequest(this, callback, remotePath, f)); + return ConnMan.addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); } /** Returns Common::Array with list of files, which were not downloaded. */ -Networking::Request *OneDriveStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive) { - return ConnMan.addRequest(new FolderDownloadRequest(this, callback, remotePath, localPath, recursive)); +Networking::Request *OneDriveStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); } -void OneDriveStorage::fileDownloaded(BoolResponse pair) { - if (pair.value) debug("file downloaded!"); +void OneDriveStorage::fileDownloaded(BoolResponse response) { + if (response.value) debug("file downloaded!"); else debug("download failed!"); } -void OneDriveStorage::printFiles(FileArrayResponse pair) { +void OneDriveStorage::printFiles(FileArrayResponse response) { debug("files:"); - Common::Array &files = pair.value; + Common::Array &files = response.value; for (uint32 i = 0; i < files.size(); ++i) debug("\t%s", files[i].path().c_str()); } -void OneDriveStorage::printBool(BoolResponse pair) { - debug("bool: %s", pair.value ? "true" : "false"); +void OneDriveStorage::printBool(BoolResponse response) { + debug("bool: %s", response.value ? "true" : "false"); +} + +void OneDriveStorage::printErrorResponse(Networking::ErrorResponse error) { + debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug("%s", error.response.c_str()); } +Networking::ErrorCallback OneDriveStorage::getErrorPrintingCallback() { + return new Common::Callback(this, &OneDriveStorage::printErrorResponse); +} -Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { +Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { //this is not the real syncSaves() implementation /* Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); @@ -220,7 +228,7 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback) { return ConnMan.addRequest(request); */ //return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback(this, &OneDriveStorage::printFiles), false); - return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool))); + return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 43675fbfa5..f95ea89bc1 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -46,15 +46,18 @@ class OneDriveStorage: public Cloud::Storage { */ OneDriveStorage(Common::String code); - void tokenRefreshed(BoolCallback callback, Networking::JsonResponse pair); - void codeFlowComplete(BoolResponse pair); + void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); + void codeFlowComplete(BoolResponse response); - void printJson(Networking::JsonResponse pair); - void fileDownloaded(BoolResponse pair); - void printFiles(FileArrayResponse pair); - void printBool(BoolResponse pair); + void printJson(Networking::JsonResponse response); + void fileDownloaded(BoolResponse response); + void printFiles(FileArrayResponse response); + void printBool(BoolResponse response); + void printErrorResponse(Networking::ErrorResponse error); - void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse pair); + Networking::ErrorCallback getErrorPrintingCallback(); + + void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); public: virtual ~OneDriveStorage(); @@ -74,35 +77,35 @@ public: /** Public Cloud API comes down there. */ /** Returns ListDirectoryStatus struct with list of files. */ - virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, 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. */ - virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) { return nullptr; } //TODO - virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) { return nullptr; } + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback); + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ - virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback); + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Returns Common::Array with list of files, which were not downloaded. */ - virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false); + virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual Networking::Request *syncSaves(BoolCallback callback); + virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ - virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual Networking::Request *touch(Common::String path, BoolCallback callback) { return nullptr; } //TODO + virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Returns the StorageInfo struct. */ - virtual Networking::Request *info(StorageInfoCallback callback) { return nullptr; } //TODO + virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index a0c41ff471..bc7bd74dbe 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -31,16 +31,16 @@ namespace Cloud { namespace OneDrive { -OneDriveTokenRefresher::OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url): - CurlJsonRequest(callback, url), _parentStorage(parent) {} +OneDriveTokenRefresher::OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url): + CurlJsonRequest(callback, ecb, url), _parentStorage(parent) {} OneDriveTokenRefresher::~OneDriveTokenRefresher() {} -void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse pair) { - if (!pair.value) { +void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { + if (!response.value) { //failed to refresh token, notify user with NULL in original callback warning("OneDriveTokenRefresher: failed to refresh token"); - finish(); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; } @@ -56,11 +56,10 @@ void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse pair) { retry(0); } -void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { +void OneDriveTokenRefresher::finishSuccess(Common::JSONValue *json) { if (!json) { - //notify user of failure - warning("OneDriveTokenRefresher: got NULL instead of JSON"); - CurlJsonRequest::finishJson(nullptr); + //that's probably not an error (200 OK) + CurlJsonRequest::finishSuccess(nullptr); return; } @@ -74,19 +73,26 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::JSONObject error = result.getVal("error")->asObject(); bool irrecoverable = true; + Common::String code, message; if (error.contains("code")) { - Common::String code = error.getVal("code")->asString(); - debug("code = %s", code.c_str()); - //if (code == "itemNotFound") irrecoverable = true; + code = error.getVal("code")->asString(); + debug("code = %s", code.c_str()); } if (error.contains("message")) { - Common::String message = error.getVal("message")->asString(); + message = error.getVal("message")->asString(); debug("message = %s", message.c_str()); } - if (irrecoverable) { - CurlJsonRequest::finishJson(nullptr); + //determine whether token refreshing would help in this situation + if (code == "itemNotFound") { + if (message.contains("application ID")) + irrecoverable = false; + } + + if (irrecoverable) { + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode + delete json; return; } @@ -97,7 +103,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { } //notify user of success - CurlJsonRequest::finishJson(json); + CurlJsonRequest::finishSuccess(json); } void OneDriveTokenRefresher::setHeaders(Common::Array &headers) { @@ -108,6 +114,10 @@ void OneDriveTokenRefresher::setHeaders(Common::Array &headers) CurlJsonRequest::addHeader(headers[i]); } +void OneDriveTokenRefresher::addHeader(Common::String header) { + _headers.push_back(header); + CurlJsonRequest::addHeader(header); +} } // End of namespace OneDrive } // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h index 90ca9d603a..04b0bf26b8 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.h +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -35,19 +35,15 @@ class OneDriveTokenRefresher: public Networking::CurlJsonRequest { OneDriveStorage *_parentStorage; Common::Array _headers; - void tokenRefreshed(Storage::BoolResponse pair); + void tokenRefreshed(Storage::BoolResponse response); - virtual void finishJson(Common::JSONValue *json); + virtual void finishSuccess(Common::JSONValue *json); public: - OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url); + OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); virtual ~OneDriveTokenRefresher(); virtual void setHeaders(Common::Array &headers); - - virtual void addHeader(Common::String header) { - _headers.push_back(header); - CurlJsonRequest::addHeader(header); - } + virtual void addHeader(Common::String header); }; } // End of namespace OneDrive diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index e632bfff84..b48a99a48c 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -32,8 +32,8 @@ namespace Cloud { const char *SavesSyncRequest::TIMESTAMPS_FILENAME = "timestamps"; -SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback): - Request(nullptr), _storage(storage), _boolCallback(callback), +SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb): + Request(nullptr, ecb), _storage(storage), _boolCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { start(); } @@ -59,48 +59,35 @@ void SavesSyncRequest::start() { loadTimestamps(); //list saves directory - _workingRequest = _storage->listDirectory("/saves", new Common::Callback(this, &SavesSyncRequest::directoryListedCallback)); + _workingRequest = _storage->listDirectory( + "/saves", + new Common::Callback(this, &SavesSyncRequest::directoryListedCallback), + new Common::Callback(this, &SavesSyncRequest::directoryListedErrorCallback) + ); } -void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pair) { +void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - ListDirectoryStatus status = pair.value; - bool irrecoverable = status.interrupted || status.failed; - if (status.failed) { - Common::JSONValue *value = Common::JSON::parse(status.response.c_str()); - if (value) { - if (value->isObject()) { - Common::JSONObject object = value->asObject(); - //Dropbox-related error: - if (object.contains("error_summary")) { - Common::String summary = object.getVal("error_summary")->asString(); - if (summary.contains("not_found")) { - //oh how lucky we are! It's just user don't have /cloud/ folder yet! - irrecoverable = false; - } - } - } - delete value; - } + Common::HashMap localFileNotAvailableInCloud; + for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { + localFileNotAvailableInCloud[i->_key] = true; } - if (irrecoverable) { - finishBool(false); - return; - } - //determine which files to download and which files to upload - Common::Array &remoteFiles = status.files; + Common::Array &remoteFiles = response.value; for (uint32 i = 0; i < remoteFiles.size(); ++i) { StorageFile &file = remoteFiles[i]; if (file.isDirectory()) continue; if (file.name() == TIMESTAMPS_FILENAME) continue; + Common::String name = file.name(); if (!_localFilesTimestamps.contains(name)) _filesToDownload.push_back(file); else { + localFileNotAvailableInCloud[name] = false; + if (_localFilesTimestamps[name] != INVALID_TIMESTAMP) { if (_localFilesTimestamps[name] == file.timestamp()) continue; @@ -115,11 +102,10 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pa } } - //upload files with invalid timestamp (the ones we've added - means they might not have any remote version) - for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { + //upload files which are unavailable in cloud + for (Common::HashMap::iterator i = localFileNotAvailableInCloud.begin(); i != localFileNotAvailableInCloud.end(); ++i) { if (i->_key == TIMESTAMPS_FILENAME) continue; - if (i->_value == INVALID_TIMESTAMP) - _filesToUpload.push_back(i->_key); + if (i->_value) _filesToUpload.push_back(i->_key); } /////// @@ -137,6 +123,50 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse pa downloadNextFile(); } +void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + bool irrecoverable = error.interrupted || error.failed; + if (error.failed) { + Common::JSONValue *value = Common::JSON::parse(error.response.c_str()); + if (value) { + if (value->isObject()) { + Common::JSONObject object = value->asObject(); + + //Dropbox-related error: + if (object.contains("error_summary")) { + Common::String summary = object.getVal("error_summary")->asString(); + if (summary.contains("not_found")) { + irrecoverable = false; + } + } + + //OneDrive-related error: + if (object.contains("error") && object.getVal("error")->isObject()) { + Common::JSONObject errorNode = object.getVal("error")->asObject(); + if (errorNode.contains("code") && errorNode.contains("message")) { + Common::String code = errorNode.getVal("code")->asString(); + if (code == "itemNotFound") { + irrecoverable = false; + } + } + } + } + delete value; + } + } + + if (irrecoverable) { + finishError(error); + return; + } + + //we're lucky - user just lacks his "/cloud/" folder + Common::Array files; + directoryListedCallback(Storage::ListDirectoryResponse(error.request, files)); +} + void SavesSyncRequest::downloadNextFile() { if (_filesToDownload.empty()) { uploadNextFile(); @@ -150,17 +180,18 @@ void SavesSyncRequest::downloadNextFile() { debug("downloading %s", _currentDownloadingFile.name().c_str()); /////// _workingRequest = _storage->download(_currentDownloadingFile.path(), concatWithSavesPath(_currentDownloadingFile.name()), - new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback) + new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), + new Common::Callback(this, &SavesSyncRequest::fileDownloadedErrorCallback) ); } -void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse pair) { +void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; //stop syncing if download failed - if (!pair.value) { - finish(); + if (!response.value) { + finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; } @@ -171,9 +202,17 @@ void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse pair) { downloadNextFile(); } +void SavesSyncRequest::fileDownloadedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //stop syncing if download failed + finishError(error); +} + void SavesSyncRequest::uploadNextFile() { if (_filesToUpload.empty()) { - finishBool(true); + finishSuccess(true); return; } @@ -184,36 +223,45 @@ void SavesSyncRequest::uploadNextFile() { debug("uploading %s", _currentUploadingFile.c_str()); /////// _workingRequest = _storage->upload("/saves/" + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), - new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback) + new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), + new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) ); } -void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse pair) { +void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - UploadStatus status = pair.value; - - //stop syncing if upload failed - if (status.interrupted || status.failed) { - finish(); - return; - } - + //update local timestamp for the uploaded file - _localFilesTimestamps[_currentUploadingFile] = status.file.timestamp(); + _localFilesTimestamps[_currentUploadingFile] = response.value.timestamp(); //continue uploading files uploadNextFile(); } +void SavesSyncRequest::fileUploadedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //stop syncing if upload failed + finishError(error); +} + void SavesSyncRequest::handle() {} void SavesSyncRequest::restart() { start(); } -void SavesSyncRequest::finish() { finishBool(false); } +void SavesSyncRequest::finishError(Networking::ErrorResponse error) { + debug("SavesSync::finishError"); + + //save updated timestamps (even if Request failed, there would be only valid timestamps) + saveTimestamps(); + + Request::finishError(error); +} -void SavesSyncRequest::finishBool(bool success) { - Request::finish(); +void SavesSyncRequest::finishSuccess(bool success) { + Request::finishSuccess(); //save updated timestamps (even if Request failed, there would be only valid timestamps) saveTimestamps(); @@ -233,7 +281,6 @@ void SavesSyncRequest::loadTimestamps() { warning("SavesSyncRequest: failed to open '%s' file to load timestamps", TIMESTAMPS_FILENAME); return; } - while (!file->eos()) { //read filename into buffer (reading until the first ' ') diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index da7b27e9b6..bf44b70390 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -45,22 +45,25 @@ class SavesSyncRequest: public Networking::Request { bool _ignoreCallback; void start(); - void directoryListedCallback(Storage::ListDirectoryResponse pair); - void fileDownloadedCallback(Storage::BoolResponse pair); - void fileUploadedCallback(Storage::UploadResponse pair); + void directoryListedCallback(Storage::ListDirectoryResponse response); + void directoryListedErrorCallback(Networking::ErrorResponse error); + void fileDownloadedCallback(Storage::BoolResponse response); + void fileDownloadedErrorCallback(Networking::ErrorResponse error); + void fileUploadedCallback(Storage::UploadResponse response); + void fileUploadedErrorCallback(Networking::ErrorResponse error); void downloadNextFile(); void uploadNextFile(); - void finishBool(bool success); + virtual void finishError(Networking::ErrorResponse error); + void finishSuccess(bool success); void loadTimestamps(); void saveTimestamps(); Common::String concatWithSavesPath(Common::String name); public: - SavesSyncRequest(Storage *storage, Storage::BoolCallback callback); + SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb); virtual ~SavesSyncRequest(); virtual void handle(); - virtual void restart(); - virtual void finish(); + virtual void restart(); }; } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 311b3fdc9f..32c437857c 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -34,53 +34,13 @@ namespace Cloud { -/** Struct to represent upload() resulting status. */ -struct UploadStatus { - /** true if Request was interrupted (finished by user with finish()) */ - bool interrupted; - /** true if Request has failed (bad server response or some other error occurred) */ - bool failed; - /** Contains uploaded file description (empty if failed) */ - StorageFile file; - /** Server's original response (empty if not failed) */ - Common::String response; - /** Server's HTTP response code. */ - long httpResponseCode; - - UploadStatus(): - interrupted(false), failed(false), file(), response(), httpResponseCode(-1) {} - - UploadStatus(bool interrupt, bool failure, StorageFile f, Common::String resp, long code): - interrupted(interrupt), failed(failure), file(f), response(resp), httpResponseCode(code) {} -}; - -/** Struct to represent upload() resulting status. */ -struct ListDirectoryStatus { - /** true if Request was interrupted (finished by user with finish()) */ - bool interrupted; - /** true if Request has failed (bad server response or some other error occurred) */ - bool failed; - /** Contains listed files (might be incomplete if failed or interrupted) */ - Common::Array &files; - /** Server's original response (empty if not failed) */ - Common::String response; - /** Server's HTTP response code. */ - long httpResponseCode; - - ListDirectoryStatus(Common::Array &f) : - interrupted(false), failed(false), files(f), response(), httpResponseCode(-1) {} - - ListDirectoryStatus(bool interrupt, bool failure, Common::Array &f, Common::String resp, long code) : - interrupted(interrupt), failed(failure), files(f), response(resp), httpResponseCode(code) {} -}; - class Storage { public: typedef Networking::Response&> FileArrayResponse; typedef Networking::Response StorageInfoResponse; typedef Networking::Response BoolResponse; - typedef Networking::Response UploadResponse; - typedef Networking::Response ListDirectoryResponse; + typedef Networking::Response UploadResponse; + typedef Networking::Response &> ListDirectoryResponse; typedef Common::BaseCallback *FileArrayCallback; typedef Common::BaseCallback *StorageInfoCallback; @@ -113,35 +73,35 @@ public: */ /** Returns ListDirectoryStatus struct with list of files. */ - virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, bool recursive = false) = 0; + virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false) = 0; /** Returns UploadStatus struct with info about uploaded file. */ - virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback) = 0; - virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback) = 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; /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback) = 0; + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback) = 0; + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Returns Common::Array with list of files, which were not downloaded. */ - virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, bool recursive = false) = 0; + virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback) = 0; + virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *syncSaves(BoolCallback callback) = 0; + virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback) = 0; + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *touch(Common::String path, BoolCallback callback) = 0; + virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Returns the StorageInfo struct. */ - virtual Networking::Request *info(StorageInfoCallback callback) = 0; + virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Returns whether saves sync process is running. */ virtual bool isSyncing() = 0; -- cgit v1.2.3 From b39f46788a70a6c72d5ca678c79c0b53ebde9b68 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 14:18:32 +0600 Subject: CLOUD: Add OneDriveUploadRequest Doesn't support server's requested ranges yet. Commit also adds some PUT-related code in NetworkReadStream and CurlRequest. --- backends/cloud/dropbox/dropboxstorage.cpp | 13 -- backends/cloud/dropbox/dropboxstorage.h | 3 +- backends/cloud/onedrive/onedrivestorage.cpp | 19 ++- backends/cloud/onedrive/onedrivestorage.h | 4 +- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 2 + backends/cloud/onedrive/onedriveuploadrequest.cpp | 171 +++++++++++++++++++++ backends/cloud/onedrive/onedriveuploadrequest.h | 61 ++++++++ backends/cloud/storage.cpp | 42 +++++ backends/cloud/storage.h | 2 +- 9 files changed, 297 insertions(+), 20 deletions(-) create mode 100644 backends/cloud/onedrive/onedriveuploadrequest.cpp create mode 100644 backends/cloud/onedrive/onedriveuploadrequest.h create mode 100644 backends/cloud/storage.cpp (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index d22e0abf60..7ba072d578 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -131,19 +131,6 @@ Networking::Request *DropboxStorage::upload(Common::String path, Common::Seekabl 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) { Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("path", new Common::JSONValue(path)); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 0082e5cebd..a5ef76a3d6 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -74,8 +74,7 @@ public: virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); /** 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 remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 8746b7ab33..fe10580616 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -24,8 +24,10 @@ #include "backends/cloud/onedrive/onedrivestorage.h" #include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h" +#include "backends/cloud/onedrive/onedriveuploadrequest.h" #include "backends/cloud/downloadrequest.h" #include "backends/cloud/folderdownloadrequest.h" +#include "backends/cloud/savessyncrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "common/cloudmanager.h" @@ -35,7 +37,6 @@ #include "common/json.h" #include "common/system.h" #include -#include "../savessyncrequest.h" namespace Cloud { namespace OneDrive { @@ -168,6 +169,9 @@ Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDir 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) { 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"); } +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) { debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); debug("%s", error.response.c_str()); @@ -228,7 +239,11 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback, Networkin return ConnMan.addRequest(request); */ //return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback(this, &OneDriveStorage::printFiles), false); - return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO + return Storage::upload( + "uploads/test.jpg", "test.jpg", + new Common::Callback(this, &OneDriveStorage::printFile), getErrorPrintingCallback() + ); + //return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index f95ea89bc1..0ced98cd4e 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -53,6 +53,7 @@ class OneDriveStorage: public Cloud::Storage { void fileDownloaded(BoolResponse response); void printFiles(FileArrayResponse response); void printBool(BoolResponse response); + void printFile(UploadResponse response); void printErrorResponse(Networking::ErrorResponse error); Networking::ErrorCallback getErrorPrintingCallback(); @@ -80,8 +81,7 @@ public: virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); /** 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 remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index bc7bd74dbe..bf849f7964 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -90,6 +90,8 @@ void OneDriveTokenRefresher::finishSuccess(Common::JSONValue *json) { irrecoverable = false; } + if (code == "unauthenticated") irrecoverable = false; + if (irrecoverable) { finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode delete json; diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp new file mode 100644 index 0000000000..752907f333 --- /dev/null +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -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(this, &OneDriveUploadRequest::partUploadedCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(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(this, &OneDriveUploadRequest::partUploadedCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(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 diff --git a/backends/cloud/onedrive/onedriveuploadrequest.h b/backends/cloud/onedrive/onedriveuploadrequest.h new file mode 100644 index 0000000000..09419d8a15 --- /dev/null +++ b/backends/cloud/onedrive/onedriveuploadrequest.h @@ -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 diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp new file mode 100644 index 0000000000..6588b05193 --- /dev/null +++ b/backends/cloud/storage.cpp @@ -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 + diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 32c437857c..1d92189fa4 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -77,7 +77,7 @@ public: /** 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 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. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0; -- cgit v1.2.3 From 3638c8348d98273da5c4e2c5bd1afa8a985a2d0c Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 16:23:25 +0600 Subject: CLOUD: Make SavesSyncRequest work with OneDrive It actually works fine, but small Storage::savesDirectoryPath() was added, because Dropbox's directories must start with a slash, and OneDrive's directories must not. Saves sync tested and it works fine with OneDrive. --- backends/cloud/dropbox/dropboxstorage.cpp | 2 ++ backends/cloud/dropbox/dropboxstorage.h | 3 +++ backends/cloud/onedrive/onedrivestorage.cpp | 9 +++------ backends/cloud/onedrive/onedrivestorage.h | 3 +++ backends/cloud/savessyncrequest.cpp | 5 +++-- backends/cloud/storage.h | 3 +++ 6 files changed, 17 insertions(+), 8 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 7ba072d578..beb510882a 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -178,6 +178,8 @@ Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Net //and then calls the outerCallback (which wants to receive StorageInfo, not void *) } +Common::String DropboxStorage::savesDirectoryPath() { return "/saves/"; } + void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index a5ef76a3d6..90a1d270e8 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -103,6 +103,9 @@ public: /** This method is passed into info(). (Temporary) */ void infoMethodCallback(StorageInfoResponse response); + /** Returns storage's saves directory path with the trailing slash. */ + virtual Common::String savesDirectoryPath(); + /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index fe10580616..1e9a641e8a 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -238,14 +238,11 @@ Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback, Networkin request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); */ - //return downloadFolder("subfolder", "local/onedrive/subfolder_downloaded", new Common::Callback(this, &OneDriveStorage::printFiles), false); - return Storage::upload( - "uploads/test.jpg", "test.jpg", - new Common::Callback(this, &OneDriveStorage::printFile), getErrorPrintingCallback() - ); - //return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO + return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO } +Common::String OneDriveStorage::savesDirectoryPath() { return "saves/"; } + OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 0ced98cd4e..45a8dca331 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -107,6 +107,9 @@ public: /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + /** Returns storage's saves directory path with the trailing slash. */ + virtual Common::String savesDirectoryPath(); + /** Returns whether saves sync process is running. */ virtual bool isSyncing() { return false; } //TODO diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index b48a99a48c..9727738654 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -60,7 +60,7 @@ void SavesSyncRequest::start() { //list saves directory _workingRequest = _storage->listDirectory( - "/saves", + _storage->savesDirectoryPath(), new Common::Callback(this, &SavesSyncRequest::directoryListedCallback), new Common::Callback(this, &SavesSyncRequest::directoryListedErrorCallback) ); @@ -165,6 +165,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er //we're lucky - user just lacks his "/cloud/" folder Common::Array files; directoryListedCallback(Storage::ListDirectoryResponse(error.request, files)); + //TODO: create it before uploading stuff } void SavesSyncRequest::downloadNextFile() { @@ -222,7 +223,7 @@ void SavesSyncRequest::uploadNextFile() { /////// debug("uploading %s", _currentUploadingFile.c_str()); /////// - _workingRequest = _storage->upload("/saves/" + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), + _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) ); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 1d92189fa4..4bd2aa3fb1 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -103,6 +103,9 @@ public: /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) = 0; + /** Returns storage's saves directory path with the trailing slash. */ + virtual Common::String savesDirectoryPath() = 0; + /** Returns whether saves sync process is running. */ virtual bool isSyncing() = 0; -- cgit v1.2.3 From 13351a730d79cc2f0d5b964226c69bb04e2c93c1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 19:00:54 +0600 Subject: CLOUD: Add OneDrive::info() Unfortunately, OneDrive doesn't share quota information anymore because of some reason. I had to get as much information as I could. --- backends/cloud/onedrive/onedrivestorage.cpp | 45 +++++++++++++++++++++++++---- backends/cloud/onedrive/onedrivestorage.h | 5 +++- 2 files changed, 44 insertions(+), 6 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 1e9a641e8a..a16a351690 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -131,6 +131,40 @@ void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } +void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("NULL passed instead of JSON"); + delete outerCallback; + return; + } + + if (outerCallback) { + Common::JSONObject info = json->asObject(); + + Common::String uid, name, email; + uint32 quotaUsed = 0, quotaAllocated = 25 * 1024 * 1024 * 1024; // 25 GB, because I actually don't know any way to find out the real one + + if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { + Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); + if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { + Common::JSONObject user = createdBy.getVal("user")->asObject(); + uid = user.getVal("id")->asString(); + name = user.getVal("displayName")->asString(); + } + } + + if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { + quotaUsed = info.getVal("size")->asIntegerNumber(); + } + + (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); + delete outerCallback; + } + + delete json; +} + void OneDriveStorage::printJson(Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { @@ -232,13 +266,14 @@ Networking::ErrorCallback OneDriveStorage::getErrorPrintingCallback() { Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { //this is not the real syncSaves() implementation - /* - Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveStorage::printJson); - Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, "https://api.onedrive.com/v1.0/drive/special/approot"); + return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO +} + +Networking::Request *OneDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::infoInnerCallback, callback); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, "https://api.onedrive.com/v1.0/drive/special/approot"); request->addHeader("Authorization: bearer " + _token); return ConnMan.addRequest(request); - */ - return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO } Common::String OneDriveStorage::savesDirectoryPath() { return "saves/"; } diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 45a8dca331..5741f8e20e 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -49,6 +49,9 @@ class OneDriveStorage: public Cloud::Storage { void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); void codeFlowComplete(BoolResponse response); + /** Constructs StorageInfo based on JSON response from cloud. */ + void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); + void printJson(Networking::JsonResponse response); void fileDownloaded(BoolResponse response); void printFiles(FileArrayResponse response); @@ -105,7 +108,7 @@ public: virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Returns the StorageInfo struct. */ - virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); /** Returns storage's saves directory path with the trailing slash. */ virtual Common::String savesDirectoryPath(); -- cgit v1.2.3 From 0d0033fb6ad00e3081bc2854ce5972746b603105 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 19:18:06 +0600 Subject: CLOUD: Make syncSaves() common for all Storages As it uses SavesSyncRequest and this request is using Storage's upload(), download() and listDirectory(), there is no need to make storage-dependent version of that request and so method could be implemented in base Storage. --- backends/cloud/dropbox/dropboxstorage.cpp | 14 -------------- backends/cloud/dropbox/dropboxstorage.h | 6 ------ backends/cloud/onedrive/onedrivestorage.cpp | 14 -------------- backends/cloud/onedrive/onedrivestorage.h | 6 ------ backends/cloud/storage.cpp | 21 +++++++++++++++++++++ backends/cloud/storage.h | 11 ++++++++++- 6 files changed, 31 insertions(+), 41 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index beb510882a..1aae73e524 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -114,15 +114,6 @@ void DropboxStorage::printStorageFile(UploadResponse response) { debug("\ttimestamp: %u", response.value.timestamp()); } -void DropboxStorage::printErrorResponse(Networking::ErrorResponse error) { - debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); - debug("%s", error.response.c_str()); -} - -Networking::ErrorCallback DropboxStorage::getErrorPrintingCallback() { - return new Common::Callback(this, &DropboxStorage::printErrorResponse); -} - Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, Networking::ErrorCallback errorCallback, bool recursive) { return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive)); } @@ -162,11 +153,6 @@ Networking::Request *DropboxStorage::downloadFolder(Common::String remotePath, C return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); } -Networking::Request *DropboxStorage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { - //this might be the real syncSaves() implementation - return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &DropboxStorage::printBool), getErrorPrintingCallback())); //TODO -} - Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/1/account/info"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 90a1d270e8..7752dddf9b 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -48,9 +48,6 @@ class DropboxStorage: public Cloud::Storage { void printFiles(FileArrayResponse response); void printBool(BoolResponse response); void printStorageFile(UploadResponse response); - void printErrorResponse(Networking::ErrorResponse error); - - Networking::ErrorCallback getErrorPrintingCallback(); public: virtual ~DropboxStorage(); @@ -88,9 +85,6 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Calls the callback when finished. */ - virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index a16a351690..fb2ead3364 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -255,20 +255,6 @@ void OneDriveStorage::printFile(UploadResponse response) { debug("\ttimestamp: %u", response.value.timestamp()); } -void OneDriveStorage::printErrorResponse(Networking::ErrorResponse error) { - debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); - debug("%s", error.response.c_str()); -} - -Networking::ErrorCallback OneDriveStorage::getErrorPrintingCallback() { - return new Common::Callback(this, &OneDriveStorage::printErrorResponse); -} - -Networking::Request *OneDriveStorage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { - //this is not the real syncSaves() implementation - return ConnMan.addRequest(new SavesSyncRequest(this, new Common::Callback(this, &OneDriveStorage::printBool), getErrorPrintingCallback())); //TODO -} - Networking::Request *OneDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::infoInnerCallback, callback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, "https://api.onedrive.com/v1.0/drive/special/approot"); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 5741f8e20e..241b6a8742 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -57,9 +57,6 @@ class OneDriveStorage: public Cloud::Storage { void printFiles(FileArrayResponse response); void printBool(BoolResponse response); void printFile(UploadResponse response); - void printErrorResponse(Networking::ErrorResponse error); - - Networking::ErrorCallback getErrorPrintingCallback(); void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); public: @@ -98,9 +95,6 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Calls the callback when finished. */ - virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 6588b05193..2e13376fa8 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -21,11 +21,25 @@ */ #include "backends/cloud/storage.h" +#include "backends/cloud/savessyncrequest.h" +#include "backends/networking/curl/connectionmanager.h" +#include "common/debug.h" #include "common/file.h" namespace Cloud { +Networking::ErrorCallback Storage::getErrorPrintingCallback() { + return new Common::Callback(this, &Storage::printErrorResponse); +} + +void Storage::printErrorResponse(Networking::ErrorResponse error) { + debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug("%s", error.response.c_str()); +} + Networking::Request *Storage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + Common::File *f = new Common::File(); if (!f->open(localPath)) { warning("Storage: unable to open file to upload from"); @@ -35,8 +49,15 @@ Networking::Request *Storage::upload(Common::String remotePath, Common::String l delete f; return nullptr; } + return upload(remotePath, f, callback, errorCallback); } +Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + return ConnMan.addRequest(new SavesSyncRequest(this, callback, errorCallback)); +} + + } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 4bd2aa3fb1..b4d2680e31 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -48,6 +48,15 @@ public: typedef Common::BaseCallback *UploadCallback; typedef Common::BaseCallback *ListDirectoryCallback; +protected: + + /** Returns default error callback (printErrorResponse). */ + virtual Networking::ErrorCallback getErrorPrintingCallback(); + + /** Prints ErrorResponse contents with debug(). */ + virtual void printErrorResponse(Networking::ErrorResponse error); + +public: Storage() {} virtual ~Storage() {} @@ -92,7 +101,7 @@ public: virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; + virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; -- cgit v1.2.3 From ca85d4482af0b2e570565d5aa6d562ec86b10100 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 19:32:16 +0600 Subject: CLOUD: Use uint64 in StorageInfo There was a warning regarding 25 GB constant. By the way, I'm not sure how to print uint64 (%llu is available in C99 only, and gcc produces a warning about that). --- backends/cloud/dropbox/dropboxstorage.cpp | 8 ++++---- backends/cloud/onedrive/onedrivestorage.cpp | 2 +- backends/cloud/storageinfo.h | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 1aae73e524..263c2c8132 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -181,9 +181,9 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ Common::String name = info.getVal("display_name")->asString(); Common::String email = info.getVal("email")->asString(); Common::JSONObject quota = info.getVal("quota_info")->asObject(); - uint32 quotaNormal = quota.getVal("normal")->asIntegerNumber(); - uint32 quotaShared = quota.getVal("shared")->asIntegerNumber(); - uint32 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); + uint64 quotaNormal = quota.getVal("normal")->asIntegerNumber(); + uint64 quotaShared = quota.getVal("shared")->asIntegerNumber(); + uint64 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); delete outerCallback; } @@ -195,7 +195,7 @@ void DropboxStorage::infoMethodCallback(StorageInfoResponse response) { debug("\nStorage info:"); debug("User name: %s", response.value.name().c_str()); debug("Email: %s", response.value.email().c_str()); - debug("Disk usage: %u/%u", response.value.used(), response.value.available()); + debug("Disk usage: %u/%u", (uint32)response.value.used(), (uint32)response.value.available()); } DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index fb2ead3364..c64ed6bf72 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -143,7 +143,7 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo Common::JSONObject info = json->asObject(); Common::String uid, name, email; - uint32 quotaUsed = 0, quotaAllocated = 25 * 1024 * 1024 * 1024; // 25 GB, because I actually don't know any way to find out the real one + uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); diff --git a/backends/cloud/storageinfo.h b/backends/cloud/storageinfo.h index 1492898a6c..e0666bc190 100644 --- a/backends/cloud/storageinfo.h +++ b/backends/cloud/storageinfo.h @@ -34,17 +34,17 @@ namespace Cloud { class StorageInfo { Common::String _uid, _name, _email; - uint32 _usedBytes, _allocatedBytes; + uint64 _usedBytes, _allocatedBytes; public: - StorageInfo(Common::String uid, Common::String name, Common::String email, uint32 used, uint32 allocated): + StorageInfo(Common::String uid, Common::String name, Common::String email, uint64 used, uint64 allocated): _uid(uid), _name(name), _email(email), _usedBytes(used), _allocatedBytes(allocated) {} Common::String uid() const { return _uid; } Common::String name() const { return _name; } Common::String email() const { return _email; } - uint32 used() const { return _usedBytes; } - uint32 available() const { return _allocatedBytes; } + uint64 used() const { return _usedBytes; } + uint64 available() const { return _allocatedBytes; } }; -- cgit v1.2.3 From 675e7a6ed1d19e64e2f80a4dd1f454e646cb52f5 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 19:41:11 +0600 Subject: CLOUD: Move download methods into Storage DownloadRequest and FolderDownloadRequest are using other Storage's methods. Thus, download() and downloadFolder() could be implemented in base Storage class. --- backends/cloud/dropbox/dropboxstorage.cpp | 16 ---------------- backends/cloud/dropbox/dropboxstorage.h | 6 ------ backends/cloud/onedrive/onedrivestorage.cpp | 17 ----------------- backends/cloud/onedrive/onedrivestorage.h | 6 ------ backends/cloud/storage.cpp | 23 +++++++++++++++++++++++ backends/cloud/storage.h | 4 ++-- 6 files changed, 25 insertions(+), 47 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 263c2c8132..acc96f9476 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -137,22 +137,6 @@ Networking::Request *DropboxStorage::streamFile(Common::String path, Networking: return response.request; } -Networking::Request *DropboxStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { - Common::DumpFile *f = new Common::DumpFile(); - if (!f->open(localPath, true)) { - warning("DropboxStorage: unable to open file to download into"); - if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1)); - delete f; - return nullptr; - } - - return ConnMan.addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); -} - -Networking::Request *DropboxStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); -} - Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/1/account/info"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 7752dddf9b..5db2bb7ee3 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -76,12 +76,6 @@ public: /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); - - /** Returns Common::Array with list of files, which were not downloaded. */ - virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); - /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index c64ed6bf72..e1c6861efd 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -215,23 +215,6 @@ Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking return ConnMan.addRequest(request); } -Networking::Request *OneDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { - Common::DumpFile *f = new Common::DumpFile(); - if (!f->open(localPath, true)) { - warning("OneDriveStorage: unable to open file to download into"); - if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1)); - delete f; - return nullptr; - } - - return ConnMan.addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); -} - -/** Returns Common::Array with list of files, which were not downloaded. */ -Networking::Request *OneDriveStorage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); -} - void OneDriveStorage::fileDownloaded(BoolResponse response) { if (response.value) debug("file downloaded!"); else debug("download failed!"); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 241b6a8742..49d63b98a6 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -86,12 +86,6 @@ public: /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); - - /** Returns Common::Array with list of files, which were not downloaded. */ - virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); - /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 2e13376fa8..90e095a146 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -21,6 +21,8 @@ */ #include "backends/cloud/storage.h" +#include "backends/cloud/downloadrequest.h" +#include "backends/cloud/folderdownloadrequest.h" #include "backends/cloud/savessyncrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "common/debug.h" @@ -53,6 +55,27 @@ Networking::Request *Storage::upload(Common::String remotePath, Common::String l return upload(remotePath, f, callback, errorCallback); } +Networking::Request *Storage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + + Common::DumpFile *f = new Common::DumpFile(); + if (!f->open(localPath, true)) { + warning("Storage: unable to open file to download into"); + if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1)); + delete errorCallback; + delete callback; + delete f; + return nullptr; + } + + return ConnMan.addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); +} + +Networking::Request *Storage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); +} + Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); return ConnMan.addRequest(new SavesSyncRequest(this, callback, errorCallback)); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index b4d2680e31..4956d5f617 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -92,10 +92,10 @@ public: virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Returns Common::Array with list of files, which were not downloaded. */ - virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false) = 0; + virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; -- cgit v1.2.3 From 4e7dec550077bc37cf254311aefb621cdeebbdfe Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 20:54:41 +0600 Subject: CLOUD: Add DropboxCreateDirectoryRequest Also add CloudManager::testFeature(), because syncSaves() now works fine and I don't want to break it again and again with my testing requests. --- .../dropbox/dropboxcreatedirectoryrequest.cpp | 109 +++++++++++++++++++++ .../cloud/dropbox/dropboxcreatedirectoryrequest.h | 55 +++++++++++ backends/cloud/dropbox/dropboxstorage.cpp | 12 +-- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/manager.cpp | 11 +++ backends/cloud/manager.h | 3 + backends/cloud/onedrive/onedrivestorage.cpp | 5 +- backends/cloud/savessyncrequest.cpp | 4 +- 8 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp create mode 100644 backends/cloud/dropbox/dropboxcreatedirectoryrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp new file mode 100644 index 0000000000..c077d8df11 --- /dev/null +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -0,0 +1,109 @@ +/* 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/dropboxcreatedirectoryrequest.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" + +namespace Cloud { +namespace Dropbox { + +DropboxCreateDirectoryRequest::DropboxCreateDirectoryRequest(Common::String token, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _token(token), _path(path), _boolCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +DropboxCreateDirectoryRequest::~DropboxCreateDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; +} + +void DropboxCreateDirectoryRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _ignoreCallback = false; + + Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxCreateDirectoryRequest::responseCallback); + Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxCreateDirectoryRequest::errorCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/2/files/create_folder"); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Content-Type: application/json"); + + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("path", new Common::JSONValue(_path)); + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + _workingRequest = ConnMan.addRequest(request); +} + +void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + _workingRequest = nullptr; + if (_ignoreCallback) { + delete json; + return; + } + + Networking::ErrorResponse error(this); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + if (rq && rq->getNetworkReadStream()) + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + + if (!json) { + warning("NULL passed instead of JSON"); + finishError(error); + return; + } + + Common::JSONObject info = json->asObject(); + if (info.contains("id")) finishSuccess(true); + else { + error.response = json->stringify(true); + finishError(error); + } + + delete json; +} + +void DropboxCreateDirectoryRequest::errorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void DropboxCreateDirectoryRequest::handle() {} + +void DropboxCreateDirectoryRequest::restart() { start(); } + +void DropboxCreateDirectoryRequest::finishSuccess(bool success) { + Request::finishSuccess(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +} // End of namespace Dropbox +} // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h new file mode 100644 index 0000000000..ea3175bb50 --- /dev/null +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h @@ -0,0 +1,55 @@ +/* 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_DROPBOXCREATEDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_DROPBOX_DROPBOXCREATEDIRECTORYREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace Dropbox { + +class DropboxCreateDirectoryRequest: public Networking::Request { + Common::String _token; + Common::String _path; + Storage::BoolCallback _boolCallback; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void responseCallback(Networking::JsonResponse response); + void errorCallback(Networking::ErrorResponse error); + void finishSuccess(bool success); +public: + DropboxCreateDirectoryRequest(Common::String token, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb); + virtual ~DropboxCreateDirectoryRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace Dropbox +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index acc96f9476..f51819ccae 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -22,20 +22,15 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/dropbox/dropboxstorage.h" +#include "backends/cloud/dropbox/dropboxcreatedirectoryrequest.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 -#include "common/system.h" -#include "common/savefile.h" -#include "../savessyncrequest.h" namespace Cloud { namespace Dropbox { @@ -137,6 +132,11 @@ Networking::Request *DropboxStorage::streamFile(Common::String path, Networking: return response.request; } +Networking::Request *DropboxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + return ConnMan.addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback)); +} + Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/1/account/info"); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 5db2bb7ee3..2f57b052b2 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -80,7 +80,7 @@ public: virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 2f1533c50d..70f2c3a3ef 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -25,6 +25,7 @@ #include "backends/cloud/onedrive/onedrivestorage.h" #include "common/config-manager.h" #include "common/random.h" +#include "common/debug.h" namespace Cloud { @@ -110,9 +111,19 @@ Storage *Manager::getCurrentStorage() { return nullptr; } +void Manager::printBool(Storage::BoolResponse response) { + debug("bool = %s", (response.value ? "true" : "false")); +} + void Manager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); if (storage) storage->syncSaves(callback, errorCallback); } +void Manager::testFeature() { + Storage *storage = getCurrentStorage(); + if (storage) storage->createDirectory("/remote/sub2/dir", + new Common::Callback(this, &Manager::printBool), nullptr); +} + } // End of namespace Cloud diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h index 013e117046..f68b33517d 100644 --- a/backends/cloud/manager.h +++ b/backends/cloud/manager.h @@ -33,6 +33,8 @@ class Manager: public Common::CloudManager { uint _currentStorageIndex; uint _deviceId; + void printBool(Storage::BoolResponse response); + public: Manager(); virtual ~Manager(); @@ -43,6 +45,7 @@ public: virtual Storage *getCurrentStorage(); virtual void syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback); + virtual void testFeature(); }; } // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index e1c6861efd..2adf5fffed 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -25,15 +25,12 @@ #include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h" #include "backends/cloud/onedrive/onedriveuploadrequest.h" -#include "backends/cloud/downloadrequest.h" -#include "backends/cloud/folderdownloadrequest.h" -#include "backends/cloud/savessyncrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" +#include "backends/networking/curl/networkreadstream.h" #include "common/cloudmanager.h" #include "common/config-manager.h" #include "common/debug.h" -#include "common/file.h" #include "common/json.h" #include "common/system.h" #include diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 9727738654..cf0c427294 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -59,8 +59,10 @@ void SavesSyncRequest::start() { loadTimestamps(); //list saves directory + Common::String dir = _storage->savesDirectoryPath(); + if (dir.lastChar() == '/') dir.deleteLastChar(); _workingRequest = _storage->listDirectory( - _storage->savesDirectoryPath(), + dir, new Common::Callback(this, &SavesSyncRequest::directoryListedCallback), new Common::Callback(this, &SavesSyncRequest::directoryListedErrorCallback) ); -- cgit v1.2.3 From 8cdde307f7b1d3eff71050817921ea0aa8c318fe Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 21:21:35 +0600 Subject: CLOUD: Add OneDriveCreateDirectoryRequest --- backends/cloud/manager.cpp | 2 +- .../onedrive/onedrivecreatedirectoryrequest.cpp | 128 +++++++++++++++++++++ .../onedrive/onedrivecreatedirectoryrequest.h | 57 +++++++++ backends/cloud/onedrive/onedrivestorage.cpp | 6 + backends/cloud/onedrive/onedrivestorage.h | 2 +- 5 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp create mode 100644 backends/cloud/onedrive/onedrivecreatedirectoryrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp index 70f2c3a3ef..13424ba8c6 100644 --- a/backends/cloud/manager.cpp +++ b/backends/cloud/manager.cpp @@ -122,7 +122,7 @@ void Manager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallbac void Manager::testFeature() { Storage *storage = getCurrentStorage(); - if (storage) storage->createDirectory("/remote/sub2/dir", + if (storage) storage->createDirectory("base/belong_to_us", new Common::Callback(this, &Manager::printBool), nullptr); } diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp new file mode 100644 index 0000000000..c48ae1dfbe --- /dev/null +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -0,0 +1,128 @@ +/* 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/onedrivecreatedirectoryrequest.h" +#include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/cloud/onedrive/onedrivetokenrefresher.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/curljsonrequest.h" +#include "backends/networking/curl/networkreadstream.h" +#include "common/json.h" + +namespace Cloud { +namespace OneDrive { + +OneDriveCreateDirectoryRequest::OneDriveCreateDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _storage(storage), _path(path), _boolCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +OneDriveCreateDirectoryRequest::~OneDriveCreateDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; +} + +void OneDriveCreateDirectoryRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _ignoreCallback = false; + + Common::String name = _path, parent = _path; + if (name.size() != 0) { + uint32 i = name.size() - 1; + while (true) { + parent.deleteLastChar(); + if (name[i] == '/' || name[i] == '\\') { + name.erase(0, i + 1); + break; + } + if (i == 0) break; + --i; + } + } + + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot"; + if (parent != "") url += ":/" + parent + ":"; + url += "/children"; + Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::responseCallback); + Networking::ErrorCallback errorCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::errorCallback); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, innerCallback, errorCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); + request->addHeader("Content-Type: application/json"); + + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("name", new Common::JSONValue(name)); + jsonRequestParameters.setVal("folder", new Common::JSONValue(Common::JSONObject())); + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + _workingRequest = ConnMan.addRequest(request); +} + +void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + _workingRequest = nullptr; + if (_ignoreCallback) { + delete json; + return; + } + + Networking::ErrorResponse error(this); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + if (rq && rq->getNetworkReadStream()) + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + + if (!json) { + warning("NULL passed instead of JSON"); + finishError(error); + return; + } + + Common::JSONObject info = json->asObject(); + if (info.contains("id")) finishSuccess(true); + else { + error.response = json->stringify(true); + finishError(error); + } + + delete json; +} + +void OneDriveCreateDirectoryRequest::errorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void OneDriveCreateDirectoryRequest::handle() {} + +void OneDriveCreateDirectoryRequest::restart() { start(); } + +void OneDriveCreateDirectoryRequest::finishSuccess(bool success) { + Request::finishSuccess(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +} // End of namespace OneDrive +} // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h new file mode 100644 index 0000000000..4bf0d9ef36 --- /dev/null +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h @@ -0,0 +1,57 @@ +/* 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_ONEDRIVECREATEDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVECREATEDIRECTORYREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace OneDrive { + +class OneDriveStorage; + +class OneDriveCreateDirectoryRequest: public Networking::Request { + OneDriveStorage *_storage; + Common::String _path; + Storage::BoolCallback _boolCallback; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void responseCallback(Networking::JsonResponse response); + void errorCallback(Networking::ErrorResponse error); + void finishSuccess(bool success); +public: + OneDriveCreateDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb); + virtual ~OneDriveCreateDirectoryRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace OneDrive +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 2adf5fffed..190a7ab603 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -22,6 +22,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/cloud/onedrive/onedrivecreatedirectoryrequest.h" #include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h" #include "backends/cloud/onedrive/onedriveuploadrequest.h" @@ -235,6 +236,11 @@ void OneDriveStorage::printFile(UploadResponse response) { debug("\ttimestamp: %u", response.value.timestamp()); } +Networking::Request *OneDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + return ConnMan.addRequest(new OneDriveCreateDirectoryRequest(this, path, callback, errorCallback)); +} + Networking::Request *OneDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::infoInnerCallback, callback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, "https://api.onedrive.com/v1.0/drive/special/approot"); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 49d63b98a6..8fc7b2ac4d 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -90,7 +90,7 @@ public: virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO /** Calls the callback when finished. */ - virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO -- cgit v1.2.3 From 06163cb8b907e30f8463b2b9700d136c73b19a33 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 31 May 2016 21:47:57 +0600 Subject: CLOUD: Fix SavesSyncRequest to create saves folder --- backends/cloud/savessyncrequest.cpp | 33 ++++++++++++++++++++++++++++++--- backends/cloud/savessyncrequest.h | 2 ++ 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index cf0c427294..d5cb6f6f76 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -164,10 +164,37 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er return; } - //we're lucky - user just lacks his "/cloud/" folder + //we're lucky - user just lacks his "/cloud/" folder - let's create one + Common::String dir = _storage->savesDirectoryPath(); + if (dir.lastChar() == '/') dir.deleteLastChar(); + debug("creating %s", dir.c_str()); + _workingRequest = _storage->createDirectory(dir, + new Common::Callback(this, &SavesSyncRequest::directoryCreatedCallback), + new Common::Callback(this, &SavesSyncRequest::directoryCreatedErrorCallback) + ); +} + +void SavesSyncRequest::directoryCreatedCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //stop syncing if failed to create saves directory + if (!response.value) { + finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; + } + + //continue with empty files list Common::Array files; - directoryListedCallback(Storage::ListDirectoryResponse(error.request, files)); - //TODO: create it before uploading stuff + directoryListedCallback(Storage::ListDirectoryResponse(response.request, files)); +} + +void SavesSyncRequest::directoryCreatedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //stop syncing if failed to create saves directory + finishError(error); } void SavesSyncRequest::downloadNextFile() { diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index bf44b70390..0e20159845 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -47,6 +47,8 @@ class SavesSyncRequest: public Networking::Request { void start(); void directoryListedCallback(Storage::ListDirectoryResponse response); void directoryListedErrorCallback(Networking::ErrorResponse error); + void directoryCreatedCallback(Storage::BoolResponse response); + void directoryCreatedErrorCallback(Networking::ErrorResponse error); void fileDownloadedCallback(Storage::BoolResponse response); void fileDownloadedErrorCallback(Networking::ErrorResponse error); void fileUploadedCallback(Storage::UploadResponse response); -- cgit v1.2.3 From 4b3a8be0b9db448971e6095a24501c66714c484f Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 1 Jun 2016 12:08:47 +0600 Subject: CLOUD: Shorten Cloud API touch() and isSyncing() are not needed. remove() is not needed too, but it could be used in the future. --- backends/cloud/dropbox/dropboxstorage.h | 6 ------ backends/cloud/onedrive/onedrivestorage.h | 6 ------ backends/cloud/storage.h | 6 ------ 3 files changed, 18 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 2f57b052b2..2c60097701 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -82,9 +82,6 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); @@ -94,9 +91,6 @@ public: /** Returns storage's saves directory path with the trailing slash. */ virtual Common::String savesDirectoryPath(); - /** Returns whether saves sync process is running. */ - virtual bool isSyncing() { return false; } //TODO - /** Returns whether there are any requests running. */ virtual bool isWorking() { return false; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 8fc7b2ac4d..5edd96e59c 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -92,18 +92,12 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); /** Returns storage's saves directory path with the trailing slash. */ virtual Common::String savesDirectoryPath(); - /** Returns whether saves sync process is running. */ - virtual bool isSyncing() { return false; } //TODO - /** Returns whether there are any requests running. */ virtual bool isWorking() { return false; } //TODO diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 4956d5f617..1efee85bb3 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -106,18 +106,12 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; - /** Calls the callback when finished. */ - virtual Networking::Request *touch(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; - /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Returns storage's saves directory path with the trailing slash. */ virtual Common::String savesDirectoryPath() = 0; - /** Returns whether saves sync process is running. */ - virtual bool isSyncing() = 0; - /** Returns whether there are any requests running. */ virtual bool isWorking() = 0; }; -- cgit v1.2.3 From a66322408f95ff7b29cf6967eaecaac06dfe5b31 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 1 Jun 2016 12:39:10 +0600 Subject: CLOUD: Implement Storage's isWorking() It now keeps track of how many Requests are running. To achieve that, we had to pass a callback to ConnectionManager, so each Request has a callback paired with it. If that's one of Storage's Requests, it has a callback, which would decrease a counter. When Storage adds a Request, it also increases a counter and passes that callback. Callback is called by ConnMan when Request is deleted. isWorking() returns true if there is at least one Request running. --- backends/cloud/dropbox/dropboxstorage.cpp | 8 ++++---- backends/cloud/dropbox/dropboxstorage.h | 3 --- backends/cloud/onedrive/onedrivestorage.cpp | 12 ++++++------ backends/cloud/onedrive/onedrivestorage.h | 3 --- backends/cloud/storage.cpp | 24 +++++++++++++++++++++--- backends/cloud/storage.h | 26 ++++++++++++++++++++++---- 6 files changed, 53 insertions(+), 23 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index f51819ccae..861a58db4b 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -110,11 +110,11 @@ void DropboxStorage::printStorageFile(UploadResponse response) { } Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, Networking::ErrorCallback errorCallback, bool recursive) { - return ConnMan.addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive)); + return addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive)); } Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { - return ConnMan.addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback)); + return addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback)); } Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { @@ -134,14 +134,14 @@ Networking::Request *DropboxStorage::streamFile(Common::String path, Networking: Networking::Request *DropboxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - return ConnMan.addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback)); + return addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback)); } Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/1/account/info"); request->addHeader("Authorization: Bearer " + _token); - return ConnMan.addRequest(request); + return addRequest(request); //that callback bridge wraps the outerCallback (passed in arguments from user) into innerCallback //so, when CurlJsonRequest is finished, it calls the innerCallback //innerCallback (which is DropboxStorage::infoInnerCallback in this case) processes the void *ptr diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 2c60097701..c186d1e5d6 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -91,9 +91,6 @@ public: /** Returns storage's saves directory path with the trailing slash. */ virtual Common::String savesDirectoryPath(); - /** Returns whether there are any requests running. */ - virtual bool isWorking() { return false; } //TODO - /** * Load token and user id from configs and return DropboxStorage for those. * @return pointer to the newly created DropboxStorage or 0 if some problem occured. diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 190a7ab603..98f0ac5a4d 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -84,7 +84,7 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); - ConnMan.addRequest(request); + addRequest(request); } void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse response) { @@ -198,11 +198,11 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out } Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - return ConnMan.addRequest(new OneDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); + return 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)); + return addRequest(new OneDriveUploadRequest(this, path, contents, callback, errorCallback)); } Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { @@ -210,7 +210,7 @@ Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _token); - return ConnMan.addRequest(request); + return addRequest(request); } void OneDriveStorage::fileDownloaded(BoolResponse response) { @@ -238,14 +238,14 @@ void OneDriveStorage::printFile(UploadResponse response) { Networking::Request *OneDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - return ConnMan.addRequest(new OneDriveCreateDirectoryRequest(this, path, callback, errorCallback)); + return addRequest(new OneDriveCreateDirectoryRequest(this, path, callback, errorCallback)); } Networking::Request *OneDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::infoInnerCallback, callback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, "https://api.onedrive.com/v1.0/drive/special/approot"); request->addHeader("Authorization: bearer " + _token); - return ConnMan.addRequest(request); + return addRequest(request); } Common::String OneDriveStorage::savesDirectoryPath() { return "saves/"; } diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 5edd96e59c..a09d68b6fd 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -98,9 +98,6 @@ public: /** Returns storage's saves directory path with the trailing slash. */ virtual Common::String savesDirectoryPath(); - /** Returns whether there are any requests running. */ - virtual bool isWorking() { return false; } //TODO - /** * Load token and user id from configs and return OneDriveStorage for those. * @return pointer to the newly created OneDriveStorage or 0 if some problem occured. diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 90e095a146..0f9a2a168a 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -30,6 +30,10 @@ namespace Cloud { +Storage::Storage(): _runningRequestsCount(0) {} + +Storage::~Storage() {} + Networking::ErrorCallback Storage::getErrorPrintingCallback() { return new Common::Callback(this, &Storage::printErrorResponse); } @@ -39,6 +43,17 @@ void Storage::printErrorResponse(Networking::ErrorResponse error) { debug("%s", error.response.c_str()); } +Networking::Request *Storage::addRequest(Networking::Request *request) { + ++_runningRequestsCount; + if (_runningRequestsCount == 1) debug("Storage is working now"); + return ConnMan.addRequest(request, new Common::Callback(this, &Storage::requestFinishedCallback)); +} + +void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer) { + --_runningRequestsCount; + if (_runningRequestsCount == 0) debug("Storage is not working now"); +} + Networking::Request *Storage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); @@ -68,19 +83,22 @@ Networking::Request *Storage::download(Common::String remotePath, Common::String return nullptr; } - return ConnMan.addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); + return addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); } Networking::Request *Storage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - return ConnMan.addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); + return addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); } Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - return ConnMan.addRequest(new SavesSyncRequest(this, callback, errorCallback)); + return addRequest(new SavesSyncRequest(this, callback, errorCallback)); } +bool Storage::isWorking() { + return _runningRequestsCount > 0; +} } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 1efee85bb3..b1c62ba05b 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -48,7 +48,9 @@ public: typedef Common::BaseCallback *UploadCallback; typedef Common::BaseCallback *ListDirectoryCallback; -protected: +protected: + /** Keeps track of running requests. */ + uint32 _runningRequestsCount; /** Returns default error callback (printErrorResponse). */ virtual Networking::ErrorCallback getErrorPrintingCallback(); @@ -56,9 +58,25 @@ protected: /** Prints ErrorResponse contents with debug(). */ virtual void printErrorResponse(Networking::ErrorResponse error); + /** + * Adds request to the ConnMan, but also increases _runningRequestsCount. + * This method should be used by Storage implementations instead of + * direct ConnMan.addRequest() call. + * + * @return the same Request pointer, just as a shortcut + */ + virtual Networking::Request *addRequest(Networking::Request *request); + + /** + * Decreases _runningRequestCount. It's called from ConnMan automatically. + * Passed pointer is dangling, but one can use the address to determine + * some special Requests (which addresses were remembered somewhere). + */ + virtual void requestFinishedCallback(Networking::Request *invalidRequestPointer); + public: - Storage() {} - virtual ~Storage() {} + Storage(); + virtual ~Storage(); /** * Storage methods, which are used by CloudManager to save @@ -113,7 +131,7 @@ public: virtual Common::String savesDirectoryPath() = 0; /** Returns whether there are any requests running. */ - virtual bool isWorking() = 0; + virtual bool isWorking(); }; } // End of namespace Cloud -- cgit v1.2.3 From b3bf5322117d03c003011839ea1e7897c48183fa Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 1 Jun 2016 16:22:42 +0600 Subject: CLOUD: Make CloudManager singleton It's needed to ::destroy() it in main(). --- backends/cloud/cloudmanager.cpp | 122 ++++++++++++++++++++++++++ backends/cloud/cloudmanager.h | 87 +++++++++++++++++++ backends/cloud/manager.cpp | 129 ---------------------------- backends/cloud/manager.h | 53 ------------ backends/cloud/onedrive/onedrivestorage.cpp | 9 +- 5 files changed, 213 insertions(+), 187 deletions(-) create mode 100644 backends/cloud/cloudmanager.cpp create mode 100644 backends/cloud/cloudmanager.h delete mode 100644 backends/cloud/manager.cpp delete mode 100644 backends/cloud/manager.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp new file mode 100644 index 0000000000..d18bb6ff9a --- /dev/null +++ b/backends/cloud/cloudmanager.cpp @@ -0,0 +1,122 @@ +/* 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/cloudmanager.h" +#include "backends/cloud/dropbox/dropboxstorage.h" +#include "backends/cloud/onedrive/onedrivestorage.h" +#include "common/config-manager.h" +#include "common/debug.h" + +namespace Common { + +DECLARE_SINGLETON(Cloud::CloudManager); + +} + +namespace Cloud { + +CloudManager::CloudManager() : _currentStorageIndex(0) {} + +CloudManager::~CloudManager() { + //TODO: do we have to save storages on manager destruction? + for (uint32 i = 0; i < _storages.size(); ++i) + delete _storages[i]; + _storages.clear(); +} + +void CloudManager::init() { + bool offerDropbox = false; + bool offerOneDrive = true; + + if (ConfMan.hasKey("storages_number", "cloud")) { + int storages = ConfMan.getInt("storages_number", "cloud"); + for (int i = 1; i <= storages; ++i) { + Storage *loaded = 0; + Common::String keyPrefix = Common::String::format("storage%d_", i); + if (ConfMan.hasKey(keyPrefix + "type", "cloud")) { + Common::String storageType = ConfMan.get(keyPrefix + "type", "cloud"); + if (storageType == "Dropbox") loaded = Dropbox::DropboxStorage::loadFromConfig(keyPrefix); + else if (storageType == "OneDrive") { + loaded = OneDrive::OneDriveStorage::loadFromConfig(keyPrefix); + offerOneDrive = false; + } else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); + } else { + warning("Cloud storage #%d (out of %d) is missing.", i, storages); + } + if (loaded) _storages.push_back(loaded); + } + + uint32 index = 0; + if (ConfMan.hasKey("current_storage", "cloud")) { + index = ConfMan.getInt("current_storage", "cloud") - 1; //count from 1, all for UX + } + if (index >= _storages.size()) index = 0; + _currentStorageIndex = index; + + if (_storages.size() == 0) offerDropbox = true; + } else { + offerDropbox = true; + } + if (offerDropbox) { + //this is temporary console offer to auth with Dropbox + Dropbox::DropboxStorage::authThroughConsole(); + } else if (offerOneDrive) { + //OneDrive time + OneDrive::OneDriveStorage::authThroughConsole(); + } +} + +void CloudManager::save() { + ConfMan.set("storages_number", Common::String::format("%d", _storages.size()), "cloud"); + ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex + 1), "cloud"); + for (uint32 i = 0; i < _storages.size(); ++i) + _storages[i]->saveConfig(Common::String::format("storage%d_", i + 1)); + ConfMan.flushToDisk(); +} + +void CloudManager::addStorage(Storage *storage, bool makeCurrent, bool saveConfig) { + if (!storage) error("Cloud::CloudManager: NULL storage passed"); + _storages.push_back(storage); + if (makeCurrent) _currentStorageIndex = _storages.size() - 1; + if (saveConfig) save(); +} + +Storage *CloudManager::getCurrentStorage() { + if (_currentStorageIndex < _storages.size()) + return _storages[_currentStorageIndex]; + return nullptr; +} + +void CloudManager::printBool(Storage::BoolResponse response) const { + debug("bool = %s", (response.value ? "true" : "false")); +} + +void CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { + Storage *storage = getCurrentStorage(); + if (storage) storage->syncSaves(callback, errorCallback); +} + +void CloudManager::testFeature() { + Storage *storage = getCurrentStorage(); +} + +} // End of namespace Common diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h new file mode 100644 index 0000000000..a13eeebb94 --- /dev/null +++ b/backends/cloud/cloudmanager.h @@ -0,0 +1,87 @@ +/* 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 CLOUD_CLOUDMANAGER_H +#define CLOUD_CLOUDMANAGER_H + +#include "backends/cloud/storage.h" +#include "common/array.h" +#include "common/singleton.h" + +namespace Cloud { + +class CloudManager : public Common::Singleton { + Common::Array _storages; + uint _currentStorageIndex; + + void printBool(Cloud::Storage::BoolResponse response) const; + +public: + CloudManager(); + virtual ~CloudManager(); + + /** + * Loads all information from configs and creates current Storage instance. + * + * @note It's called once on startup in scummvm_main(). + */ + void init(); + + /** + * Saves all information into configuration file. + */ + void save(); + + /** + * Adds new Storage into list. + * + * @param storage Cloud::Storage to add. + * @param makeCurrent whether added storage should be the new current storage. + * @param saveConfig whether save() should be called to update configuration file. + */ + void addStorage(Cloud::Storage *storage, bool makeCurrent = true, bool saveConfig = true); + + /** + * Returns active Storage, which could be used to interact + * with cloud storage. + * + * @return active Cloud::Storage or null, if there is no active Storage. + */ + Cloud::Storage *getCurrentStorage(); + + /** + * Starts saves syncing process in currently active storage if there is any. + */ + void syncSaves(Cloud::Storage::BoolCallback callback = nullptr, Networking::ErrorCallback errorCallback = nullptr); + + /** + * Starts feature testing (the one I'm working on currently). (Temporary) + */ + void testFeature(); +}; + +/** Shortcut for accessing the connection manager. */ +#define CloudMan Cloud::CloudManager::instance() + +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/manager.cpp b/backends/cloud/manager.cpp deleted file mode 100644 index 13424ba8c6..0000000000 --- a/backends/cloud/manager.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* 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/manager.h" -#include "backends/cloud/dropbox/dropboxstorage.h" -#include "backends/cloud/onedrive/onedrivestorage.h" -#include "common/config-manager.h" -#include "common/random.h" -#include "common/debug.h" - -namespace Cloud { - -Manager::Manager(): _currentStorageIndex(0), _deviceId(0) {} - -Manager::~Manager() { - //TODO: do we have to save storages on manager destruction? - for (uint32 i = 0; i < _storages.size(); ++i) - delete _storages[i]; - _storages.clear(); -} - -void Manager::init() { - bool offerDropbox = false; - bool offerOneDrive = true; - - if (!ConfMan.hasKey("device_id", "cloud")) { - Common::RandomSource source("Cloud Random Source"); - _deviceId = source.getRandomNumber(UINT_MAX - 1); - ConfMan.setInt("device_id", _deviceId, "cloud"); - ConfMan.flushToDisk(); - } else { - _deviceId = ConfMan.getInt("device_id", "cloud"); - } - - if (ConfMan.hasKey("storages_number", "cloud")) { - int storages = ConfMan.getInt("storages_number", "cloud"); - for (int i = 1; i <= storages; ++i) { - Storage *loaded = 0; - Common::String keyPrefix = Common::String::format("storage%d_", i); - if (ConfMan.hasKey(keyPrefix + "type", "cloud")) { - Common::String storageType = ConfMan.get(keyPrefix + "type", "cloud"); - if (storageType == "Dropbox") loaded = Dropbox::DropboxStorage::loadFromConfig(keyPrefix); - else if (storageType == "OneDrive") { - loaded = OneDrive::OneDriveStorage::loadFromConfig(keyPrefix); - offerOneDrive = false; - } else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); - } else { - warning("Cloud storage #%d (out of %d) is missing.", i, storages); - } - if (loaded) _storages.push_back(loaded); - } - - uint32 index = 0; - if (ConfMan.hasKey("current_storage", "cloud")) { - index = ConfMan.getInt("current_storage", "cloud") - 1; //count from 1, all for UX - } - if (index >= _storages.size()) index = 0; - _currentStorageIndex = index; - - if (_storages.size() == 0) offerDropbox = true; - } else { - offerDropbox = true; - } - - if (offerDropbox) { - //this is temporary console offer to auth with Dropbox - Dropbox::DropboxStorage::authThroughConsole(); - } else if(offerOneDrive) { - //OneDrive time - OneDrive::OneDriveStorage::authThroughConsole(); - } -} - -void Manager::save() { - ConfMan.set("storages_number", Common::String::format("%d", _storages.size()), "cloud"); - ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex + 1), "cloud"); - for (uint32 i = 0; i < _storages.size(); ++i) - _storages[i]->saveConfig(Common::String::format("storage%d_", i+1)); - ConfMan.flushToDisk(); -} - -void Manager::addStorage(Cloud::Storage *storage, bool makeCurrent, bool saveConfig) { - if (!storage) error("Cloud::Manager: NULL storage passed"); - _storages.push_back(storage); - if (makeCurrent) _currentStorageIndex = _storages.size() - 1; - if (saveConfig) save(); -} - -Storage *Manager::getCurrentStorage() { - if (_currentStorageIndex < _storages.size()) - return _storages[_currentStorageIndex]; - return nullptr; -} - -void Manager::printBool(Storage::BoolResponse response) { - debug("bool = %s", (response.value ? "true" : "false")); -} - -void Manager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { - Storage *storage = getCurrentStorage(); - if (storage) storage->syncSaves(callback, errorCallback); -} - -void Manager::testFeature() { - Storage *storage = getCurrentStorage(); - if (storage) storage->createDirectory("base/belong_to_us", - new Common::Callback(this, &Manager::printBool), nullptr); -} - -} // End of namespace Cloud diff --git a/backends/cloud/manager.h b/backends/cloud/manager.h deleted file mode 100644 index f68b33517d..0000000000 --- a/backends/cloud/manager.h +++ /dev/null @@ -1,53 +0,0 @@ -/* 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_MANAGER_H -#define BACKENDS_CLOUD_MANAGER_H - -#include "common/cloudmanager.h" -#include "common/str.h" - -namespace Cloud { - -class Manager: public Common::CloudManager { - Common::Array _storages; - uint _currentStorageIndex; - uint _deviceId; - - void printBool(Storage::BoolResponse response); - -public: - Manager(); - virtual ~Manager(); - - virtual void init(); - virtual void save(); - virtual void addStorage(Cloud::Storage *storage, bool makeCurrent = true, bool saveConfig = true); - - virtual Storage *getCurrentStorage(); - virtual void syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback); - virtual void testFeature(); -}; - -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 98f0ac5a4d..ca8a2346ad 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -22,6 +22,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/cloud/cloudmanager.h" #include "backends/cloud/onedrive/onedrivecreatedirectoryrequest.h" #include "backends/cloud/onedrive/onedrivetokenrefresher.h" #include "backends/cloud/onedrive/onedrivelistdirectoryrequest.h" @@ -29,11 +30,9 @@ #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" -#include "common/cloudmanager.h" #include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" -#include "common/system.h" #include namespace Cloud { @@ -104,7 +103,7 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResp _token = result.getVal("access_token")->asString(); _uid = result.getVal("user_id")->asString(); _refreshToken = result.getVal("refresh_token")->asString(); - g_system->getCloudManager()->save(); //ask CloudManager to save our new refreshToken + CloudMan.save(); //ask CloudManager to save our new refreshToken if (callback) (*callback)(BoolResponse(nullptr, true)); } delete json; @@ -116,10 +115,10 @@ void OneDriveStorage::codeFlowComplete(BoolResponse response) { return; } - g_system->getCloudManager()->addStorage(this); + CloudMan.addStorage(this); ConfMan.removeKey("onedrive_code", "cloud"); debug("Done! You can use OneDrive now! Look:"); - g_system->getCloudManager()->syncSaves(); + CloudMan.syncSaves(); } void OneDriveStorage::saveConfig(Common::String keyPrefix) { -- cgit v1.2.3 From 00d8d232366f418d3a25046786ab9ab5c90a52c2 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 1 Jun 2016 16:33:45 +0600 Subject: CLOUD: Add mutexes in Storage --- backends/cloud/storage.cpp | 9 ++++++++- backends/cloud/storage.h | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 0f9a2a168a..f035c93368 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -44,14 +44,18 @@ void Storage::printErrorResponse(Networking::ErrorResponse error) { } Networking::Request *Storage::addRequest(Networking::Request *request) { + _runningRequestsMutex.lock(); ++_runningRequestsCount; if (_runningRequestsCount == 1) debug("Storage is working now"); + _runningRequestsMutex.unlock(); return ConnMan.addRequest(request, new Common::Callback(this, &Storage::requestFinishedCallback)); } void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer) { + _runningRequestsMutex.lock(); --_runningRequestsCount; if (_runningRequestsCount == 0) debug("Storage is not working now"); + _runningRequestsMutex.unlock(); } Networking::Request *Storage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { @@ -97,7 +101,10 @@ Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::Error } bool Storage::isWorking() { - return _runningRequestsCount > 0; + _runningRequestsMutex.lock(); + bool working = _runningRequestsCount > 0; + _runningRequestsMutex.unlock(); + return working; } } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index b1c62ba05b..1276b81827 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -28,9 +28,10 @@ #include "backends/networking/curl/request.h" #include "backends/networking/curl/curlrequest.h" #include "common/array.h" +#include "common/callback.h" +#include "common/mutex.h" #include "common/stream.h" #include "common/str.h" -#include "common/callback.h" namespace Cloud { @@ -51,6 +52,7 @@ public: protected: /** Keeps track of running requests. */ uint32 _runningRequestsCount; + Common::Mutex _runningRequestsMutex; /** Returns default error callback (printErrorResponse). */ virtual Networking::ErrorCallback getErrorPrintingCallback(); -- cgit v1.2.3 From da3b7bd8d9f3d3828b8cea6dff60e5f43e7ad4b1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 3 Jun 2016 15:14:12 +0600 Subject: CLOUD: Add GoogleDriveStorage It has its own GoogleDriveTokenRefresher and knows how to do info(). This commit also contains JSON int -> long long int fix and CurlJsonRequest '\n' -> ' ' fix. --- backends/cloud/cloudmanager.cpp | 15 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 4 +- backends/cloud/googledrive/googledrivestorage.cpp | 331 +++++++++++++++++++++ backends/cloud/googledrive/googledrivestorage.h | 131 ++++++++ .../googledrive/googledrivetokenrefresher.cpp | 121 ++++++++ .../cloud/googledrive/googledrivetokenrefresher.h | 52 ++++ 6 files changed, 648 insertions(+), 6 deletions(-) create mode 100644 backends/cloud/googledrive/googledrivestorage.cpp create mode 100644 backends/cloud/googledrive/googledrivestorage.h create mode 100644 backends/cloud/googledrive/googledrivetokenrefresher.cpp create mode 100644 backends/cloud/googledrive/googledrivetokenrefresher.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index d18bb6ff9a..92e45e8811 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -23,6 +23,7 @@ #include "backends/cloud/cloudmanager.h" #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/onedrive/onedrivestorage.h" +#include "backends/cloud/googledrive/googledrivestorage.h" #include "common/config-manager.h" #include "common/debug.h" @@ -45,7 +46,8 @@ CloudManager::~CloudManager() { void CloudManager::init() { bool offerDropbox = false; - bool offerOneDrive = true; + bool offerOneDrive = false; + bool offerGoogleDrive = true; if (ConfMan.hasKey("storages_number", "cloud")) { int storages = ConfMan.getInt("storages_number", "cloud"); @@ -55,9 +57,10 @@ void CloudManager::init() { if (ConfMan.hasKey(keyPrefix + "type", "cloud")) { Common::String storageType = ConfMan.get(keyPrefix + "type", "cloud"); if (storageType == "Dropbox") loaded = Dropbox::DropboxStorage::loadFromConfig(keyPrefix); - else if (storageType == "OneDrive") { - loaded = OneDrive::OneDriveStorage::loadFromConfig(keyPrefix); - offerOneDrive = false; + else if (storageType == "OneDrive") loaded = OneDrive::OneDriveStorage::loadFromConfig(keyPrefix); + else if (storageType == "Google Drive") { + loaded = GoogleDrive::GoogleDriveStorage::loadFromConfig(keyPrefix); + offerGoogleDrive = false; } else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); } else { warning("Cloud storage #%d (out of %d) is missing.", i, storages); @@ -82,6 +85,9 @@ void CloudManager::init() { } else if (offerOneDrive) { //OneDrive time OneDrive::OneDriveStorage::authThroughConsole(); + } else if (offerGoogleDrive) { + GoogleDrive::GoogleDriveStorage::authThroughConsole(); + _currentStorageIndex = 100; } } @@ -117,6 +123,7 @@ void CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCa void CloudManager::testFeature() { Storage *storage = getCurrentStorage(); + if (storage) storage->info(nullptr, nullptr); } } // End of namespace Common diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index 50a1b8a612..bf8e43d7cb 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -79,7 +79,7 @@ void DropboxUploadRequest::uploadNextPart() { url += "finish"; Common::JSONObject jsonCursor, jsonCommit; jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId)); - jsonCursor.setVal("offset", new Common::JSONValue(_contentsStream->pos())); + jsonCursor.setVal("offset", new Common::JSONValue((long long int)_contentsStream->pos())); jsonCommit.setVal("path", new Common::JSONValue(_savePath)); jsonCommit.setVal("mode", new Common::JSONValue("overwrite")); jsonCommit.setVal("autorename", new Common::JSONValue(false)); @@ -90,7 +90,7 @@ void DropboxUploadRequest::uploadNextPart() { url += "append_v2"; Common::JSONObject jsonCursor; jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId)); - jsonCursor.setVal("offset", new Common::JSONValue(_contentsStream->pos())); + jsonCursor.setVal("offset", new Common::JSONValue((long long int)_contentsStream->pos())); jsonRequestParameters.setVal("cursor", new Common::JSONValue(jsonCursor)); jsonRequestParameters.setVal("close", new Common::JSONValue(false)); } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp new file mode 100644 index 0000000000..eef7f1f28d --- /dev/null +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -0,0 +1,331 @@ +/* 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. +* +*/ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/googledrive/googledrivestorage.h" +#include "backends/cloud/cloudmanager.h" +#include "backends/cloud/googledrive/googledrivetokenrefresher.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/curljsonrequest.h" +#include "backends/networking/curl/networkreadstream.h" +#include "common/config-manager.h" +#include "common/debug.h" +#include "common/json.h" +#include + +namespace Cloud { +namespace GoogleDrive { + +char *GoogleDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth +char *GoogleDriveStorage::SECRET; //TODO: hide these secrets somehow + +void GoogleDriveStorage::loadKeyAndSecret() { + Common::String k = ConfMan.get("GOOGLE_DRIVE_KEY", "cloud"); + KEY = new char[k.size() + 1]; + memcpy(KEY, k.c_str(), k.size()); + KEY[k.size()] = 0; + + k = ConfMan.get("GOOGLE_DRIVE_SECRET", "cloud"); + SECRET = new char[k.size() + 1]; + memcpy(SECRET, k.c_str(), k.size()); + SECRET[k.size()] = 0; +} + +GoogleDriveStorage::GoogleDriveStorage(Common::String accessToken, Common::String refreshToken): + _token(accessToken), _refreshToken(refreshToken) {} + +GoogleDriveStorage::GoogleDriveStorage(Common::String code) { + getAccessToken(new Common::Callback(this, &GoogleDriveStorage::codeFlowComplete), code); +} + +GoogleDriveStorage::~GoogleDriveStorage() {} + +void GoogleDriveStorage::getAccessToken(BoolCallback callback, Common::String code) { + bool codeFlow = (code != ""); + + if (!codeFlow && _refreshToken == "") { + warning("GoogleDriveStorage: no refresh token available to get new access token."); + if (callback) (*callback)(BoolResponse(nullptr, false)); + return; + } + + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::tokenRefreshed, callback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, getErrorPrintingCallback(), "https://accounts.google.com/o/oauth2/token"); //TODO + if (codeFlow) { + request->addPostField("code=" + code); + request->addPostField("grant_type=authorization_code"); + } else { + request->addPostField("refresh_token=" + _refreshToken); + request->addPostField("grant_type=refresh_token"); + } + request->addPostField("client_id=" + Common::String(KEY)); + request->addPostField("client_secret=" + Common::String(SECRET)); + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost"); + addRequest(request); +} + +void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("GoogleDriveStorage: got NULL instead of JSON"); + if (callback) (*callback)(BoolResponse(nullptr, false)); + return; + } + + Common::JSONObject result = json->asObject(); + if (!result.contains("access_token")) { + warning("Bad response, no token passed"); + debug("%s", json->stringify().c_str()); + if (callback) (*callback)(BoolResponse(nullptr, false)); + } else { + _token = result.getVal("access_token")->asString(); + if (!result.contains("refresh_token")) + warning("No refresh_token passed"); + else + _refreshToken = result.getVal("refresh_token")->asString(); + CloudMan.save(); //ask CloudManager to save our new refreshToken + if (callback) (*callback)(BoolResponse(nullptr, true)); + } + delete json; +} + +void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { + if (!response.value) { + warning("GoogleDriveStorage: failed to get access token through code flow"); + return; + } + + ConfMan.removeKey("googledrive_code", "cloud"); + CloudMan.addStorage(this); + ConfMan.flushToDisk(); + debug("Done! You can use Google Drive now! Look:"); + CloudMan.testFeature(); +} + +void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { + ConfMan.set(keyPrefix + "type", "Google Drive", "cloud"); + ConfMan.set(keyPrefix + "access_token", _token, "cloud"); + ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); +} + +namespace { +uint64 atoull(Common::String s) { + uint64 result = 0; + for (uint32 i = 0; i < s.size(); ++i) { + if (s[i] < '0' || s[i] > '9') break; + result = result * 10L + (s[i] - '0'); + } + return result; +} +} + +void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("NULL passed instead of JSON"); + delete outerCallback; + return; + } + + if (outerCallback) { + Common::JSONObject info = json->asObject(); + + Common::String uid, name, email; + uint64 quotaUsed = 0, quotaAllocated = 0; + + if (info.contains("user") && info.getVal("user")->isObject()) { + //"me":true, "kind":"drive#user","photoLink": "", + //"displayName":"Alexander Tkachev","emailAddress":"alexander@tkachov.ru","permissionId":"" + Common::JSONObject user = info.getVal("user")->asObject(); + uid = user.getVal("permissionId")->asString(); //not sure it's user's id, but who cares anyway? + name = user.getVal("displayName")->asString(); + email = user.getVal("emailAddress")->asString(); + } + + if (info.contains("storageQuota") && info.getVal("storageQuota")->isObject()) { + //"usageInDrive":"6332462","limit":"18253611008","usage":"6332462","usageInDriveTrash":"0" + Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); + Common::String usage = storageQuota.getVal("usage")->asString(); + Common::String limit = storageQuota.getVal("limit")->asString(); + quotaUsed = atoull(usage); + quotaAllocated = atoull(limit); + } + + (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); + delete outerCallback; + } + + delete json; +} + +void GoogleDriveStorage::printJson(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("printJson: NULL"); + return; + } + + debug("%s", json->stringify().c_str()); + delete json; +} + +void GoogleDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { + if (!response.value) { + warning("fileInfoCallback: NULL"); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); + return; + } + + Common::JSONObject result = response.value->asObject(); + if (result.contains("@content.downloadUrl")) { + const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); + if (outerCallback) + (*outerCallback)(Networking::NetworkReadStreamResponse( + response.request, + new Networking::NetworkReadStream(url, 0, "") + )); + } else { + warning("downloadUrl not found in passed JSON"); + debug("%s", response.value->stringify().c_str()); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); + } + delete response.value; +} + +Networking::Request *GoogleDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + //return addRequest(new GoogleDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); + return nullptr; //TODO +} + +Networking::Request *GoogleDriveStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { + //return addRequest(new GoogleDriveUploadRequest(this, path, contents, callback, errorCallback)); + return nullptr; //TODO +} + +Networking::Request *GoogleDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { + /* + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path; + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::fileInfoCallback, outerCallback); + Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _token); + return addRequest(request); + */ + return nullptr; //TODO +} + +void GoogleDriveStorage::fileDownloaded(BoolResponse response) { + if (response.value) debug("file downloaded!"); + else debug("download failed!"); +} + +void GoogleDriveStorage::printFiles(FileArrayResponse response) { + debug("files:"); + Common::Array &files = response.value; + for (uint32 i = 0; i < files.size(); ++i) + debug("\t%s", files[i].path().c_str()); +} + +void GoogleDriveStorage::printBool(BoolResponse response) { + debug("bool: %s", response.value ? "true" : "false"); +} + +void GoogleDriveStorage::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 GoogleDriveStorage::printInfo(StorageInfoResponse response) { + debug("\nuser info:"); + debug("\tname: %s", response.value.name().c_str()); + debug("\temail: %s", response.value.email().c_str()); + debug("\tdisk usage: %llu/%llu", response.value.used(), response.value.available()); +} + +Networking::Request *GoogleDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + //return addRequest(new GoogleDriveCreateDirectoryRequest(this, path, callback, errorCallback)); + return nullptr; //TODO +} + +Networking::Request *GoogleDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { + if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printInfo); + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::infoInnerCallback, callback); + Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, "https://www.googleapis.com/drive/v3/about?fields=storageQuota,user"); + request->addHeader("Authorization: Bearer " + _token); + return addRequest(request); +} + +Common::String GoogleDriveStorage::savesDirectoryPath() { return "saves/"; } + +GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) { + loadKeyAndSecret(); + + if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { + warning("No access_token found"); + return 0; + } + + if (!ConfMan.hasKey(keyPrefix + "refresh_token", "cloud")) { + warning("No refresh_token found"); + return 0; + } + + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud"); + Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", "cloud"); + return new GoogleDriveStorage(accessToken, refreshToken); +} + +Common::String GoogleDriveStorage::getAuthLink() { + Common::String url = "https://accounts.google.com/o/oauth2/auth"; + url += "?response_type=code"; + url += "&redirect_uri=http://localhost"; //that's for copy-pasting + //url += "&redirect_uri=http%3A%2F%2Flocalhost"; //that's "http://localhost" for automatic opening + url += "&client_id="; url += KEY; + url += "&scope=https://www.googleapis.com/auth/drive.appfolder"; //for copy-pasting + return url; +} + +void GoogleDriveStorage::authThroughConsole() { + if (!ConfMan.hasKey("GOOGLE_DRIVE_KEY", "cloud") || !ConfMan.hasKey("GOOGLE_DRIVE_SECRET", "cloud")) { + warning("No Google Drive keys available, cannot do auth"); + return; + } + + loadKeyAndSecret(); + + if (ConfMan.hasKey("googledrive_code", "cloud")) { + //phase 2: get access_token using specified code + new GoogleDriveStorage(ConfMan.get("googledrive_code", "cloud")); + return; + } + + debug("Navigate to this URL and press \"Allow\":"); + debug("%s\n", getAuthLink().c_str()); + debug("Then, add googledrive_code key in [cloud] section of configuration file. You should copy the value from URL and put it as value for that key.\n"); + debug("Navigate to this URL to get more information on ScummVM's configuration files:"); + debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h new file mode 100644 index 0000000000..8a82a54533 --- /dev/null +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -0,0 +1,131 @@ +/* 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_GOOGLEDRIVE_GOOGLEDRIVESTORAGE_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVESTORAGE_H + +#include "backends/cloud/storage.h" +#include "common/callback.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace GoogleDrive { + +class GoogleDriveStorage: public Cloud::Storage { + static char *KEY, *SECRET; + + static void loadKeyAndSecret(); + + Common::String _token, _refreshToken; + + /** This private constructor is called from loadFromConfig(). */ + GoogleDriveStorage(Common::String token, Common::String refreshToken); + + /** + * This private constructor is called from authThroughConsole() (phase 2). + * It uses OAuth code flow to get tokens. + */ + GoogleDriveStorage(Common::String code); + + void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); + void codeFlowComplete(BoolResponse response); + + /** Constructs StorageInfo based on JSON response from cloud. */ + void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); + + void printJson(Networking::JsonResponse response); + void fileDownloaded(BoolResponse response); + void printFiles(FileArrayResponse response); + void printBool(BoolResponse response); + void printFile(UploadResponse response); + void printInfo(StorageInfoResponse response); + + void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); +public: + virtual ~GoogleDriveStorage(); + + /** + * Storage methods, which are used by CloudManager to save + * storage in configuration file. + */ + + /** + * Save storage data using ConfMan. + * @param keyPrefix all saved keys must start with this prefix. + * @note every Storage must write keyPrefix + "type" key + * with common value (e.g. "Dropbox"). + */ + virtual void saveConfig(Common::String keyPrefix); + + /** Public Cloud API comes down there. */ + + /** Returns ListDirectoryStatus struct with list of files. */ + virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + + /** Returns UploadStatus struct with info about uploaded file. */ + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns pointer to Networking::NetworkReadStream. */ + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); + + /** Calls the callback when finished. */ + virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + + /** Calls the callback when finished. */ + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns the StorageInfo struct. */ + virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns storage's saves directory path with the trailing slash. */ + virtual Common::String savesDirectoryPath(); + + /** + * Load token and user id from configs and return GoogleDriveStorage for those. + * @return pointer to the newly created GoogleDriveStorage or 0 if some problem occured. + */ + static GoogleDriveStorage *loadFromConfig(Common::String keyPrefix); + + /** + * Returns GoogleDrive auth link. + */ + static Common::String getAuthLink(); + + /** + * Show message with GoogleDrive auth instructions. (Temporary) + */ + static void authThroughConsole(); + + /** + * Gets new access_token. If passed is "", refresh_token is used. + * Use "" in order to refresh token and pass a callback, so you could + * continue your work when new token is available. + */ + void getAccessToken(BoolCallback callback, Common::String code = ""); + + Common::String accessToken() { return _token; } +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp new file mode 100644 index 0000000000..3fae830105 --- /dev/null +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -0,0 +1,121 @@ +/* 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. +* +*/ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/googledrive/googledrivetokenrefresher.h" +#include "backends/cloud/googledrive/googledrivestorage.h" +#include "backends/networking/curl/networkreadstream.h" +#include "common/debug.h" +#include "common/json.h" +#include + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveTokenRefresher::GoogleDriveTokenRefresher(GoogleDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url): + CurlJsonRequest(callback, ecb, url), _parentStorage(parent) {} + +GoogleDriveTokenRefresher::~GoogleDriveTokenRefresher() {} + +void GoogleDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { + if (!response.value) { + //failed to refresh token, notify user with NULL in original callback + warning("GoogleDriveTokenRefresher: failed to refresh token"); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; + } + + //update headers: first change header with token, then pass those to request + for (uint32 i = 0; i < _headers.size(); ++i) { + if (_headers[i].contains("Authorization")) { + _headers[i] = "Authorization: Bearer " + _parentStorage->accessToken(); + } + } + setHeaders(_headers); + + //successfully received refreshed token, can restart the original request now + retry(0); +} + +void GoogleDriveTokenRefresher::finishSuccess(Common::JSONValue *json) { + if (!json) { + //that's probably not an error (200 OK) + CurlJsonRequest::finishSuccess(nullptr); + return; + } + + Common::JSONObject result = json->asObject(); + if (result.contains("error")) { + //new token needed => request token & then retry original request + if (_stream) { + debug("code %ld", _stream->httpResponseCode()); + } + + Common::JSONObject error = result.getVal("error")->asObject(); + bool irrecoverable = true; + + uint32 code = -1; + Common::String message; + if (error.contains("code") && error.getVal("code")->isIntegerNumber()) { + code = error.getVal("code")->asIntegerNumber(); + debug("code = %u", code); + } + + if (error.contains("message")) { + message = error.getVal("message")->asString(); + debug("message = %s", message.c_str()); + } + + if (code == 401 || message == "Invalid Credentials") + irrecoverable = false; + + if (irrecoverable) { + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode + delete json; + return; + } + + pause(); + delete json; + _parentStorage->getAccessToken(new Common::Callback(this, &GoogleDriveTokenRefresher::tokenRefreshed)); + return; + } + + //notify user of success + CurlJsonRequest::finishSuccess(json); +} + +void GoogleDriveTokenRefresher::setHeaders(Common::Array &headers) { + _headers = headers; + curl_slist_free_all(_headersList); + _headersList = 0; + for (uint32 i = 0; i < headers.size(); ++i) + CurlJsonRequest::addHeader(headers[i]); +} + +void GoogleDriveTokenRefresher::addHeader(Common::String header) { + _headers.push_back(header); + CurlJsonRequest::addHeader(header); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.h b/backends/cloud/googledrive/googledrivetokenrefresher.h new file mode 100644 index 0000000000..3dcb56bde6 --- /dev/null +++ b/backends/cloud/googledrive/googledrivetokenrefresher.h @@ -0,0 +1,52 @@ +/* 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_GOOGLEDRIVE_GOOGLEDRIVETOKENREFRESHER_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVETOKENREFRESHER_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace GoogleDrive { + +class GoogleDriveStorage; + +class GoogleDriveTokenRefresher: public Networking::CurlJsonRequest { + GoogleDriveStorage *_parentStorage; + Common::Array _headers; + + void tokenRefreshed(Storage::BoolResponse response); + + virtual void finishSuccess(Common::JSONValue *json); +public: + GoogleDriveTokenRefresher(GoogleDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); + virtual ~GoogleDriveTokenRefresher(); + + virtual void setHeaders(Common::Array &headers); + virtual void addHeader(Common::String header); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From 1c823b6c1d465bd894f7f37a963165ee009f35ea Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 3 Jun 2016 17:38:35 +0600 Subject: CLOUD: Fix SavesSyncRequest Now it would finish with error if spawned Request is nullptr. --- backends/cloud/savessyncrequest.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index d5cb6f6f76..86dc83abf8 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -66,6 +66,7 @@ void SavesSyncRequest::start() { new Common::Callback(this, &SavesSyncRequest::directoryListedCallback), new Common::Callback(this, &SavesSyncRequest::directoryListedErrorCallback) ); + if (!_workingRequest) finishError(Networking::ErrorResponse(this)); } void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse response) { @@ -172,6 +173,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er new Common::Callback(this, &SavesSyncRequest::directoryCreatedCallback), new Common::Callback(this, &SavesSyncRequest::directoryCreatedErrorCallback) ); + if (!_workingRequest) finishError(Networking::ErrorResponse(this)); } void SavesSyncRequest::directoryCreatedCallback(Storage::BoolResponse response) { @@ -213,6 +215,7 @@ void SavesSyncRequest::downloadNextFile() { new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), new Common::Callback(this, &SavesSyncRequest::fileDownloadedErrorCallback) ); + if (!_workingRequest) finishError(Networking::ErrorResponse(this)); } void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse response) { @@ -256,6 +259,7 @@ void SavesSyncRequest::uploadNextFile() { new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) ); + if (!_workingRequest) finishError(Networking::ErrorResponse(this)); } void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse response) { -- cgit v1.2.3 From e98b0b12adc9ac6440ec4940d595095115f00d23 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 00:06:36 +0600 Subject: CLOUD: Extend Storage & SavesSyncRequest Now one can learn whether SavesSyncRequest is running, its progress and which files are being synced. --- backends/cloud/savessyncrequest.cpp | 22 +++++++++++++++++++-- backends/cloud/savessyncrequest.h | 9 ++++++++- backends/cloud/storage.cpp | 39 +++++++++++++++++++++++++++++++++++-- backends/cloud/storage.h | 12 ++++++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 86dc83abf8..c7572c78f9 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -53,6 +53,7 @@ void SavesSyncRequest::start() { _filesToDownload.clear(); _filesToUpload.clear(); _localFilesTimestamps.clear(); + _totalFilesToHandle = 0; _ignoreCallback = false; //load timestamps @@ -120,6 +121,7 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re for (uint32 i = 0; i < _filesToUpload.size(); ++i) { debug("%s", _filesToUpload[i].c_str()); } + _totalFilesToHandle = _filesToDownload.size() + _filesToUpload.size(); /////// //start downloading files @@ -209,7 +211,7 @@ void SavesSyncRequest::downloadNextFile() { _filesToDownload.pop_back(); /////// - debug("downloading %s", _currentDownloadingFile.name().c_str()); + debug("downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); /////// _workingRequest = _storage->download(_currentDownloadingFile.path(), concatWithSavesPath(_currentDownloadingFile.name()), new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), @@ -253,7 +255,7 @@ void SavesSyncRequest::uploadNextFile() { _filesToUpload.pop_back(); /////// - debug("uploading %s", _currentUploadingFile.c_str()); + debug("uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress()*100)); /////// _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), @@ -285,6 +287,22 @@ void SavesSyncRequest::handle() {} void SavesSyncRequest::restart() { start(); } +double SavesSyncRequest::getProgress() { + if (_totalFilesToHandle == 0) { + if (_state == Networking::FINISHED) return 1; //nothing to upload and download => Request ends soon + return 0; //directory not listed yet + } + + return (double)(_totalFilesToHandle - _filesToDownload.size() - _filesToUpload.size()) / (double)(_totalFilesToHandle); +} + +Common::Array SavesSyncRequest::getFilesToUpload() { + Common::Array result = _filesToUpload; + if (_currentUploadingFile != "") + result.push_back(_currentUploadingFile); + return result; +} + void SavesSyncRequest::finishError(Networking::ErrorResponse error) { debug("SavesSync::finishError"); diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 0e20159845..ad656107c9 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -43,6 +43,7 @@ class SavesSyncRequest: public Networking::Request { Common::String _currentUploadingFile; Request *_workingRequest; bool _ignoreCallback; + uint32 _totalFilesToHandle; void start(); void directoryListedCallback(Storage::ListDirectoryResponse response); @@ -65,7 +66,13 @@ public: virtual ~SavesSyncRequest(); virtual void handle(); - virtual void restart(); + virtual void restart(); + + /** Returns a number in range [0, 1], where 1 is "complete". */ + double getProgress(); + + /** Returns an array of saves names which are not uploaded yet. */ + Common::Array getFilesToUpload(); }; } // End of namespace Cloud diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index f035c93368..95786c2cba 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -30,7 +30,7 @@ namespace Cloud { -Storage::Storage(): _runningRequestsCount(0) {} +Storage::Storage(): _runningRequestsCount(0), _savesSyncRequest(nullptr) {} Storage::~Storage() {} @@ -53,6 +53,8 @@ Networking::Request *Storage::addRequest(Networking::Request *request) { void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer) { _runningRequestsMutex.lock(); + if (invalidRequestPointer == _savesSyncRequest) + _savesSyncRequest = nullptr; --_runningRequestsCount; if (_runningRequestsCount == 0) debug("Storage is not working now"); _runningRequestsMutex.unlock(); @@ -96,8 +98,16 @@ Networking::Request *Storage::downloadFolder(Common::String remotePath, Common:: } Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { + _runningRequestsMutex.lock(); + if (_savesSyncRequest) { + warning("Storage::syncSaves: there is a sync in progress already"); + _runningRequestsMutex.unlock(); + return _savesSyncRequest; + } if (!errorCallback) errorCallback = getErrorPrintingCallback(); - return addRequest(new SavesSyncRequest(this, callback, errorCallback)); + _savesSyncRequest = new SavesSyncRequest(this, callback, errorCallback); + _runningRequestsMutex.unlock(); + return addRequest(_savesSyncRequest); } bool Storage::isWorking() { @@ -107,5 +117,30 @@ bool Storage::isWorking() { return working; } +bool Storage::isSyncing() { + _runningRequestsMutex.lock(); + bool syncing = _savesSyncRequest != nullptr; + _runningRequestsMutex.unlock(); + return syncing; +} + +double Storage::getSyncProgress() { + double result = 1; + _runningRequestsMutex.lock(); + if (_savesSyncRequest) + result = _savesSyncRequest->getProgress(); + _runningRequestsMutex.unlock(); + return result; +} + +Common::Array Storage::getSyncingFiles() { + Common::Array result; + _runningRequestsMutex.lock(); + if (_savesSyncRequest) + result = _savesSyncRequest->getFilesToUpload(); + _runningRequestsMutex.unlock(); + return result; +} + } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 1276b81827..0f518de5cd 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -35,6 +35,8 @@ namespace Cloud { +class SavesSyncRequest; + class Storage { public: typedef Networking::Response&> FileArrayResponse; @@ -53,6 +55,7 @@ protected: /** Keeps track of running requests. */ uint32 _runningRequestsCount; Common::Mutex _runningRequestsMutex; + SavesSyncRequest *_savesSyncRequest; /** Returns default error callback (printErrorResponse). */ virtual Networking::ErrorCallback getErrorPrintingCallback(); @@ -134,6 +137,15 @@ public: /** Returns whether there are any requests running. */ virtual bool isWorking(); + + /** Returns whether there is a SavesSyncRequest running. */ + virtual bool isSyncing(); + + /** Returns a number in [0, 1] range which represents current sync progress (1 = complete). */ + virtual double getSyncProgress(); + + /** Returns an array of saves names which are not yet synced (thus cannot be used). */ + virtual Common::Array getSyncingFiles(); }; } // End of namespace Cloud -- cgit v1.2.3 From 5a695040d8cbd4e840e7c21e415d2225f9318ea2 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 00:13:33 +0600 Subject: CLOUD: Fix SavesSyncRequest to return right files Files we need are files to be downloaded, because that's what blocks us from reading/writing in those. --- backends/cloud/savessyncrequest.cpp | 10 ++++++---- backends/cloud/savessyncrequest.h | 4 ++-- backends/cloud/storage.cpp | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index c7572c78f9..b952681bff 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -296,10 +296,12 @@ double SavesSyncRequest::getProgress() { return (double)(_totalFilesToHandle - _filesToDownload.size() - _filesToUpload.size()) / (double)(_totalFilesToHandle); } -Common::Array SavesSyncRequest::getFilesToUpload() { - Common::Array result = _filesToUpload; - if (_currentUploadingFile != "") - result.push_back(_currentUploadingFile); +Common::Array SavesSyncRequest::getFilesToDownload() { + Common::Array result; + for (uint32 i = 0; i < _filesToDownload.size(); ++i) + result.push_back(_filesToDownload[i].name()); + if (_currentDownloadingFile.name() != "") + result.push_back(_currentDownloadingFile.name()); return result; } diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index ad656107c9..6e74688493 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -71,8 +71,8 @@ public: /** Returns a number in range [0, 1], where 1 is "complete". */ double getProgress(); - /** Returns an array of saves names which are not uploaded yet. */ - Common::Array getFilesToUpload(); + /** Returns an array of saves names which are not downloaded yet. */ + Common::Array getFilesToDownload(); }; } // End of namespace Cloud diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 95786c2cba..c1719d97b1 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -137,7 +137,7 @@ Common::Array Storage::getSyncingFiles() { Common::Array result; _runningRequestsMutex.lock(); if (_savesSyncRequest) - result = _savesSyncRequest->getFilesToUpload(); + result = _savesSyncRequest->getFilesToDownload(); _runningRequestsMutex.unlock(); return result; } -- cgit v1.2.3 From 69aed03c4f6b23302836315502cd9abbb395415e Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 11:35:18 +0600 Subject: CLOUD: Add new CloudManager shortcuts CloudIcon can easily use CloudMan.isWorking() --- backends/cloud/cloudmanager.cpp | 24 ++++++++++++++++++++++++ backends/cloud/cloudmanager.h | 12 ++++++++++++ 2 files changed, 36 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 92e45e8811..20d75726af 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -126,4 +126,28 @@ void CloudManager::testFeature() { if (storage) storage->info(nullptr, nullptr); } +bool CloudManager::isWorking() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->isWorking(); + return false; +} + +bool CloudManager::isSyncing() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->isSyncing(); + return false; +} + +double CloudManager::getSyncProgress() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getSyncProgress(); + return 1; +} + +Common::Array CloudManager::getSyncingFiles() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getSyncingFiles(); + return Common::Array(); +} + } // End of namespace Common diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index a13eeebb94..fa3a87de8b 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -77,6 +77,18 @@ public: * Starts feature testing (the one I'm working on currently). (Temporary) */ void testFeature(); + + /** Returns whether there are any requests running. */ + bool isWorking(); + + /** Returns whether there is a SavesSyncRequest running. */ + bool isSyncing(); + + /** Returns a number in [0, 1] range which represents current sync progress (1 = complete). */ + double getSyncProgress(); + + /** Returns an array of saves names which are not yet synced (thus cannot be used). */ + Common::Array getSyncingFiles(); }; /** Shortcut for accessing the connection manager. */ -- cgit v1.2.3 From 8de2862eaa6513c43502bea86f53967015298884 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 15:22:26 +0600 Subject: CLOUD: Update syncSaves() to return SavesSyncRequest * So other classes could use that information without casting. --- backends/cloud/cloudmanager.cpp | 5 +++-- backends/cloud/cloudmanager.h | 2 +- backends/cloud/storage.cpp | 6 +++--- backends/cloud/storage.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 20d75726af..b4598d7a97 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -116,9 +116,10 @@ void CloudManager::printBool(Storage::BoolResponse response) const { debug("bool = %s", (response.value ? "true" : "false")); } -void CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { +SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); - if (storage) storage->syncSaves(callback, errorCallback); + if (storage) return storage->syncSaves(callback, errorCallback); + return nullptr; } void CloudManager::testFeature() { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index fa3a87de8b..a02dc90008 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -71,7 +71,7 @@ public: /** * Starts saves syncing process in currently active storage if there is any. */ - void syncSaves(Cloud::Storage::BoolCallback callback = nullptr, Networking::ErrorCallback errorCallback = nullptr); + SavesSyncRequest *syncSaves(Cloud::Storage::BoolCallback callback = nullptr, Networking::ErrorCallback errorCallback = nullptr); /** * Starts feature testing (the one I'm working on currently). (Temporary) diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index c1719d97b1..19f0845c47 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -97,7 +97,7 @@ Networking::Request *Storage::downloadFolder(Common::String remotePath, Common:: return addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); } -Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { +SavesSyncRequest *Storage::syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback) { _runningRequestsMutex.lock(); if (_savesSyncRequest) { warning("Storage::syncSaves: there is a sync in progress already"); @@ -106,8 +106,8 @@ Networking::Request *Storage::syncSaves(BoolCallback callback, Networking::Error } if (!errorCallback) errorCallback = getErrorPrintingCallback(); _savesSyncRequest = new SavesSyncRequest(this, callback, errorCallback); - _runningRequestsMutex.unlock(); - return addRequest(_savesSyncRequest); + _runningRequestsMutex.unlock(); + return (SavesSyncRequest *)addRequest(_savesSyncRequest); //who knows what that ConnMan could return in the future } bool Storage::isWorking() { diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 0f518de5cd..5941fe4a32 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -124,7 +124,7 @@ public: virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ - virtual Networking::Request *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); + virtual SavesSyncRequest *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; -- cgit v1.2.3 From e7763700e2e2016f4573e3feb77b5fab69268683 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 15:44:05 +0600 Subject: CLOUD: Make Save/Load dialog start saves sync It also shows a "sync disabled" icon in case it has a savepath override. --- backends/cloud/savessyncrequest.cpp | 2 +- backends/cloud/savessyncrequest.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index b952681bff..a99c229925 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -33,7 +33,7 @@ namespace Cloud { const char *SavesSyncRequest::TIMESTAMPS_FILENAME = "timestamps"; SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb): - Request(nullptr, ecb), _storage(storage), _boolCallback(callback), + Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _boolCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { start(); } diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 6e74688493..397a8cbcac 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -27,10 +27,11 @@ #include "backends/cloud/storage.h" #include "common/hashmap.h" #include "common/hash-str.h" +#include "gui/object.h" namespace Cloud { -class SavesSyncRequest: public Networking::Request { +class SavesSyncRequest: public Networking::Request, public GUI::CommandSender { const uint32 INVALID_TIMESTAMP = UINT_MAX; static const char *TIMESTAMPS_FILENAME; -- cgit v1.2.3 From e9721976aa4fc604810cf1daf6d60b206197cd9a Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 20:20:22 +0600 Subject: GUI: Add SaveLoadCloudSyncProgressDialog It's shown by SaveLoadChooserDialog when files are downloaded and some save slots are locked. One can hide that dialog to interact with non-locked slots or cancel saves sync completely. Dialog's label shows current sync progress. Dialog automatically hides itself when all files are downloaded. WARNING: right now that results in a crash! --- backends/cloud/cloudmanager.cpp | 10 ++++++++++ backends/cloud/cloudmanager.h | 12 ++++++++++++ backends/cloud/savessyncrequest.cpp | 10 +++++++++- backends/cloud/storage.cpp | 14 ++++++++++++++ backends/cloud/storage.h | 12 ++++++++++++ 5 files changed, 57 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index b4598d7a97..f5d60e025c 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -151,4 +151,14 @@ Common::Array CloudManager::getSyncingFiles() { return Common::Array(); } +void CloudManager::cancelSync() { + Storage *storage = getCurrentStorage(); + if (storage) storage->cancelSync(); +} + +void CloudManager::setSyncTarget(GUI::CommandReceiver *target) { + Storage *storage = getCurrentStorage(); + if (storage) storage->setSyncTarget(target); +} + } // End of namespace Common diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index a02dc90008..c7351dab2e 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -27,6 +27,12 @@ #include "common/array.h" #include "common/singleton.h" +namespace GUI { + +class CommandReceiver; + +} + namespace Cloud { class CloudManager : public Common::Singleton { @@ -89,6 +95,12 @@ public: /** Returns an array of saves names which are not yet synced (thus cannot be used). */ Common::Array getSyncingFiles(); + + /** Cancels running sync. */ + void cancelSync(); + + /** Sets SavesSyncRequest's target to given CommandReceiver. */ + void setSyncTarget(GUI::CommandReceiver *target); }; /** Shortcut for accessing the connection manager. */ diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index a99c229925..e066c53a92 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -24,14 +24,19 @@ #include "common/config-manager.h" #include "common/debug.h" #include "common/file.h" +#include "common/json.h" #include "common/savefile.h" #include "common/system.h" -#include namespace Cloud { const char *SavesSyncRequest::TIMESTAMPS_FILENAME = "timestamps"; +enum { + kSavesSyncProgressCmd = 'SSPR', + kSavesSyncEndedCmd = 'SSEN' +}; + SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb): Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _boolCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { @@ -203,10 +208,13 @@ void SavesSyncRequest::directoryCreatedErrorCallback(Networking::ErrorResponse e void SavesSyncRequest::downloadNextFile() { if (_filesToDownload.empty()) { + sendCommand(kSavesSyncEndedCmd, 0); uploadNextFile(); return; } + sendCommand(kSavesSyncProgressCmd, (int)(getProgress() * 100)); + _currentDownloadingFile = _filesToDownload.back(); _filesToDownload.pop_back(); diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 19f0845c47..c98310d3dd 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -142,5 +142,19 @@ Common::Array Storage::getSyncingFiles() { return result; } +void Storage::cancelSync() { + _runningRequestsMutex.lock(); + if (_savesSyncRequest) + _savesSyncRequest->finish(); + _runningRequestsMutex.unlock(); +} + +void Storage::setSyncTarget(GUI::CommandReceiver *target) { + _runningRequestsMutex.lock(); + if (_savesSyncRequest) + _savesSyncRequest->setTarget(target); + _runningRequestsMutex.unlock(); +} + } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 5941fe4a32..40ea14a3a1 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -33,6 +33,12 @@ #include "common/stream.h" #include "common/str.h" +namespace GUI { + +class CommandReceiver; + +} + namespace Cloud { class SavesSyncRequest; @@ -146,6 +152,12 @@ public: /** Returns an array of saves names which are not yet synced (thus cannot be used). */ virtual Common::Array getSyncingFiles(); + + /** Cancels running sync. */ + virtual void cancelSync(); + + /** Sets SavesSyncRequest's target to given CommandReceiver. */ + virtual void setSyncTarget(GUI::CommandReceiver *target); }; } // End of namespace Cloud -- cgit v1.2.3 From 0ce7be17d3fec380f726c1ff16c559344b3e24c1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 21:07:55 +0600 Subject: CLOUD: Make ProgressDialog display downloading progress --- backends/cloud/cloudmanager.cpp | 6 ++++++ backends/cloud/cloudmanager.h | 3 +++ backends/cloud/savessyncrequest.cpp | 16 +++++++++++++++- backends/cloud/savessyncrequest.h | 3 +++ backends/cloud/storage.cpp | 9 +++++++++ backends/cloud/storage.h | 3 +++ 6 files changed, 39 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index f5d60e025c..4230c1453b 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -139,6 +139,12 @@ bool CloudManager::isSyncing() { return false; } +double CloudManager::getSyncDownloadingProgress() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getSyncDownloadingProgress(); + return 1; +} + double CloudManager::getSyncProgress() { Storage *storage = getCurrentStorage(); if (storage) return storage->getSyncProgress(); diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index c7351dab2e..dbff0184eb 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -90,6 +90,9 @@ public: /** Returns whether there is a SavesSyncRequest running. */ bool isSyncing(); + /** Returns a number in [0, 1] range which represents current sync downloading progress (1 = complete). */ + double getSyncDownloadingProgress(); + /** Returns a number in [0, 1] range which represents current sync progress (1 = complete). */ double getSyncProgress(); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index e066c53a92..072685773e 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -208,12 +208,13 @@ void SavesSyncRequest::directoryCreatedErrorCallback(Networking::ErrorResponse e void SavesSyncRequest::downloadNextFile() { if (_filesToDownload.empty()) { + _currentDownloadingFile = StorageFile("", 0, 0, false); //so getFilesToDownload() would return an empty array sendCommand(kSavesSyncEndedCmd, 0); uploadNextFile(); return; } - sendCommand(kSavesSyncProgressCmd, (int)(getProgress() * 100)); + sendCommand(kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); _currentDownloadingFile = _filesToDownload.back(); _filesToDownload.pop_back(); @@ -295,6 +296,19 @@ void SavesSyncRequest::handle() {} void SavesSyncRequest::restart() { start(); } +double SavesSyncRequest::getDownloadingProgress() { + if (_totalFilesToHandle == 0) { + if (_state == Networking::FINISHED) return 1; //nothing to upload and download => Request ends soon + return 0; //directory not listed yet + } + + if (_totalFilesToHandle == _filesToUpload.size()) return 1; //nothing to download => download complete + + uint32 totalFilesToDownload = _totalFilesToHandle - _filesToUpload.size(); + uint32 filesLeftToDownload = _filesToDownload.size() + (_currentDownloadingFile.name() != "" ? 1 : 0); + return (double)(totalFilesToDownload - filesLeftToDownload) / (double)(totalFilesToDownload); +} + double SavesSyncRequest::getProgress() { if (_totalFilesToHandle == 0) { if (_state == Networking::FINISHED) return 1; //nothing to upload and download => Request ends soon diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 397a8cbcac..569feb4e45 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -69,6 +69,9 @@ public: virtual void handle(); virtual void restart(); + /** Returns a number in range [0, 1], where 1 is "complete". */ + double getDownloadingProgress(); + /** Returns a number in range [0, 1], where 1 is "complete". */ double getProgress(); diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index c98310d3dd..5458276e39 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -124,6 +124,15 @@ bool Storage::isSyncing() { return syncing; } +double Storage::getSyncDownloadingProgress() { + double result = 1; + _runningRequestsMutex.lock(); + if (_savesSyncRequest) + result = _savesSyncRequest->getDownloadingProgress(); + _runningRequestsMutex.unlock(); + return result; +} + double Storage::getSyncProgress() { double result = 1; _runningRequestsMutex.lock(); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 40ea14a3a1..058e831e5d 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -147,6 +147,9 @@ public: /** Returns whether there is a SavesSyncRequest running. */ virtual bool isSyncing(); + /** Returns a number in [0, 1] range which represents current sync progress (1 = complete). */ + virtual double getSyncDownloadingProgress(); + /** Returns a number in [0, 1] range which represents current sync progress (1 = complete). */ virtual double getSyncProgress(); -- cgit v1.2.3 From 9eb4aad7fdea54fd99ad4a9aa4ab78bf64f81794 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 5 Jun 2016 22:26:51 +0600 Subject: CLOUD: Make DefaultSaveFileManager ignore syncing files MetaEngines don't get "locked" files in the list, so won't try to open these. Save/Load dialog updates save list every time SavesSyncRequest tells it to. --- backends/cloud/savessyncrequest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 072685773e..d983a0fcae 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -214,11 +214,11 @@ void SavesSyncRequest::downloadNextFile() { return; } - sendCommand(kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); - _currentDownloadingFile = _filesToDownload.back(); _filesToDownload.pop_back(); + sendCommand(kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); + /////// debug("downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); /////// -- cgit v1.2.3 From 6c5a8f34eaf5fe6af0d885cb162b5ebf193030f8 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 6 Jun 2016 10:25:49 +0600 Subject: CLOUD: Add SaveLoadCloudSyncProgress enum It's common for Save/Load dialogs and SavesSyncRequest. --- backends/cloud/savessyncrequest.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index d983a0fcae..f07d1d000f 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -27,16 +27,12 @@ #include "common/json.h" #include "common/savefile.h" #include "common/system.h" +#include "gui/saveload-dialog.h" namespace Cloud { const char *SavesSyncRequest::TIMESTAMPS_FILENAME = "timestamps"; -enum { - kSavesSyncProgressCmd = 'SSPR', - kSavesSyncEndedCmd = 'SSEN' -}; - SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb): Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _boolCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { @@ -209,7 +205,7 @@ void SavesSyncRequest::directoryCreatedErrorCallback(Networking::ErrorResponse e void SavesSyncRequest::downloadNextFile() { if (_filesToDownload.empty()) { _currentDownloadingFile = StorageFile("", 0, 0, false); //so getFilesToDownload() would return an empty array - sendCommand(kSavesSyncEndedCmd, 0); + sendCommand(GUI::kSavesSyncEndedCmd, 0); uploadNextFile(); return; } @@ -217,7 +213,7 @@ void SavesSyncRequest::downloadNextFile() { _currentDownloadingFile = _filesToDownload.back(); _filesToDownload.pop_back(); - sendCommand(kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); + sendCommand(GUI::kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); /////// debug("downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); -- cgit v1.2.3 From b614869de80759991c50827f0f1f35c13ef87f0d Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 6 Jun 2016 13:37:51 +0600 Subject: CLOUD: Minor fixes --- backends/cloud/dropbox/dropboxuploadrequest.cpp | 5 +++++ backends/cloud/savessyncrequest.cpp | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index bf8e43d7cb..5765892a70 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -48,6 +48,11 @@ DropboxUploadRequest::~DropboxUploadRequest() { void DropboxUploadRequest::start() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); + if (!_contentsStream) { + warning("DropboxUploadRequest: cannot start because stream is invalid"); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; + } if (!_contentsStream->seek(0)) { warning("DropboxUploadRequest: cannot restart because stream couldn't seek(0)"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index f07d1d000f..3c41c005e4 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -342,7 +342,11 @@ void SavesSyncRequest::finishSuccess(bool success) { } void SavesSyncRequest::loadTimestamps() { - //start with listing all the files in saves/ directory and setting invalid timestamp to them + //refresh the files list + Common::Array files; + g_system->getSavefileManager()->updateSavefilesList(files); + + //start with listing all the files in saves/ directory and setting invalid timestamp to them Common::StringArray localFiles = g_system->getSavefileManager()->listSavefiles("*"); for (uint32 i = 0; i < localFiles.size(); ++i) _localFilesTimestamps[localFiles[i]] = INVALID_TIMESTAMP; -- cgit v1.2.3 From bb207ae513ef02bfaf8e76374af40419a20742fe Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 6 Jun 2016 20:04:13 +0600 Subject: CLOUD: Add GoogleDriveResolveIdRequest GoogleDriveResolveIdRequest gets a lowercase path and searches for the specified file's id. To do that it lists path's subdirectories one by one with GoogleDriveListDirectoryByIdRequest. GoogleDriveListDirectoryByIdRequest gets a Google Drive id and lists that directory (not recursively). --- backends/cloud/cloudmanager.cpp | 9 +- .../googledrivelistdirectorybyidrequest.cpp | 144 +++++++++++++++++++++ .../googledrivelistdirectorybyidrequest.h | 61 +++++++++ .../googledrive/googledriveresolveidrequest.cpp | 128 ++++++++++++++++++ .../googledrive/googledriveresolveidrequest.h | 61 +++++++++ backends/cloud/googledrive/googledrivestorage.cpp | 68 +++++++++- backends/cloud/googledrive/googledrivestorage.h | 16 ++- backends/cloud/storagefile.cpp | 8 ++ backends/cloud/storagefile.h | 3 + 9 files changed, 493 insertions(+), 5 deletions(-) create mode 100644 backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp create mode 100644 backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h create mode 100644 backends/cloud/googledrive/googledriveresolveidrequest.cpp create mode 100644 backends/cloud/googledrive/googledriveresolveidrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 4230c1453b..03cc8f264b 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -124,7 +124,14 @@ SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networ void CloudManager::testFeature() { Storage *storage = getCurrentStorage(); - if (storage) storage->info(nullptr, nullptr); + //if (storage) storage->info(nullptr, nullptr); + GoogleDrive::GoogleDriveStorage *gd = dynamic_cast(storage); + if (gd) gd->resolveFileId("firstfolder/subfolder", nullptr, nullptr); + //gd->listDirectoryById("appDataFolder", nullptr, nullptr); + //gd->listDirectoryById("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", nullptr, nullptr); + //gd->createDirectoryWithParentId("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", "subfolder", nullptr, nullptr); + //gd->createDirectoryWithParentId("appDataFolder", "firstfolder", nullptr, nullptr); + else debug("FAILURE"); } bool CloudManager::isWorking() { diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp new file mode 100644 index 0000000000..0915b623f3 --- /dev/null +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -0,0 +1,144 @@ +/* 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/googledrive/googledrivelistdirectorybyidrequest.h" +#include "backends/cloud/googledrive/googledrivestorage.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 "googledrivetokenrefresher.h" + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveListDirectoryByIdRequest::GoogleDriveListDirectoryByIdRequest(GoogleDriveStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _requestedId(id), _storage(storage), _listDirectoryCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +GoogleDriveListDirectoryByIdRequest::~GoogleDriveListDirectoryByIdRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _listDirectoryCallback; +} + +void GoogleDriveListDirectoryByIdRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _files.clear(); + _ignoreCallback = false; + + makeRequest(""); +} + +void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) { + Common::String url = "https://www.googleapis.com/drive/v3/files?spaces=appDataFolder"; + if (pageToken != "") url += "&pageToken=" + pageToken; + url += "&q=%27" + _requestedId + "%27+in+parents"; + + Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveListDirectoryByIdRequest::responseCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveListDirectoryByIdRequest::errorCallback); + Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); + _workingRequest = ConnMan.addRequest(request); +} + +void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Networking::ErrorResponse error(this); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + if (rq && rq->getNetworkReadStream()) + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + + Common::JSONValue *json = response.value; + if (json) { + Common::JSONObject responseObject = json->asObject(); + + ///debug("%s", json->stringify(true).c_str()); + + if (responseObject.contains("error") || responseObject.contains("error_summary")) { + warning("GoogleDrive returned error: %s", responseObject.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 (responseObject.contains("files") && responseObject.getVal("files")->isArray()) { + Common::JSONArray items = responseObject.getVal("files")->asArray(); + for (uint32 i = 0; i < items.size(); ++i) { + Common::JSONObject item = items[i]->asObject(); + Common::String path = item.getVal("id")->asString(); + Common::String name = item.getVal("name")->asString(); + bool isDirectory = (item.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); + uint32 size = 0, timestamp = 0; + if (!isDirectory) { + size = item.getVal("size")->asIntegerNumber(); + timestamp = ISO8601::convertToTimestamp(item.getVal("modifiedTime")->asString()); + } + _files.push_back(StorageFile(path, name, size, timestamp, isDirectory)); + } + } + + bool hasMore = (responseObject.contains("nextPageToken")); + + if (hasMore) { + Common::String token = responseObject.getVal("nextPageToken")->asString(); + makeRequest(token); + } else { + finishSuccess(_files); + } + } else { + warning("null, not json"); + error.failed = true; + finishError(error); + } + + delete json; +} + +void GoogleDriveListDirectoryByIdRequest::errorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveListDirectoryByIdRequest::handle() {} + +void GoogleDriveListDirectoryByIdRequest::restart() { start(); } + +void GoogleDriveListDirectoryByIdRequest::finishSuccess(Common::Array &files) { + Request::finishSuccess(); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h new file mode 100644 index 0000000000..569984520a --- /dev/null +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h @@ -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_GOOGLEDRIVE_GOOGLEDRIVELISTDIRECTORYBYIDREQUEST_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVELISTDIRECTORYBYIDREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace GoogleDrive { + +class GoogleDriveStorage; + +class GoogleDriveListDirectoryByIdRequest: public Networking::Request { + Common::String _requestedId; + GoogleDriveStorage *_storage; + + Storage::ListDirectoryCallback _listDirectoryCallback; + Common::Array _files; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void makeRequest(Common::String pageToken); + void responseCallback(Networking::JsonResponse response); + void errorCallback(Networking::ErrorResponse error); + void finishSuccess(Common::Array &files); +public: + GoogleDriveListDirectoryByIdRequest(GoogleDriveStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb); + virtual ~GoogleDriveListDirectoryByIdRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp new file mode 100644 index 0000000000..bde17b4533 --- /dev/null +++ b/backends/cloud/googledrive/googledriveresolveidrequest.cpp @@ -0,0 +1,128 @@ +/* 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/googledrive/googledriveresolveidrequest.h" +#include "backends/cloud/googledrive/googledrivestorage.h" +#include "backends/cloud/googledrive/googledrivetokenrefresher.h" +#include "backends/cloud/iso8601.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/networkreadstream.h" +#include "common/json.h" + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveResolveIdRequest::GoogleDriveResolveIdRequest(GoogleDriveStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), + _requestedPath(path), _storage(storage), _uploadCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +GoogleDriveResolveIdRequest::~GoogleDriveResolveIdRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _uploadCallback; +} + +void GoogleDriveResolveIdRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _currentDirectory = ""; + _currentDirectoryId = "appDataFolder"; + _ignoreCallback = false; + + listNextDirectory(StorageFile("", 0, 0, false)); +} + +void GoogleDriveResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { + if (_currentDirectory == _requestedPath) { + finishFile(fileToReturn); + return; + } + + Storage::FileArrayCallback callback = new Common::Callback(this, &GoogleDriveResolveIdRequest::listedDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveResolveIdRequest::listedDirectoryErrorCallback); + _workingRequest = _storage->listDirectoryById(_currentDirectoryId, callback, failureCallback); +} + +void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Common::String currentLevelName = _requestedPath; + ///debug("'%s'", currentLevelName.c_str()); + if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); + if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) currentLevelName.erase(0, 1); + ///debug("'%s'", currentLevelName.c_str()); + for (uint32 i = 0; i < currentLevelName.size(); ++i) { + if (currentLevelName[i] == '/' || currentLevelName[i] == '\\') { + currentLevelName.erase(i); + ///debug("'%s'", currentLevelName.c_str()); + break; + } + } + + ///debug("so, searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); + + Common::Array &files = response.value; + bool found = false; + for (uint32 i = 0; i < files.size(); ++i) { + if (files[i].isDirectory() && files[i].name() == currentLevelName) { + if (_currentDirectory != "") _currentDirectory += "/"; + _currentDirectory += files[i].name(); + _currentDirectoryId = files[i].path(); + ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); + listNextDirectory(files[i]); + found = true; + break; + } + } + + if (!found) { + Common::String path = _currentDirectory; + if (path != "") path += "/"; + path += currentLevelName; + if (path == _requestedPath) finishError(Networking::ErrorResponse(this, false, true, "no such file found in its parent directory", 404)); + else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); + } +} + +void GoogleDriveResolveIdRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveResolveIdRequest::handle() {} + +void GoogleDriveResolveIdRequest::restart() { start(); } + +void GoogleDriveResolveIdRequest::finishFile(StorageFile file) { + Request::finishSuccess(); + if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.h b/backends/cloud/googledrive/googledriveresolveidrequest.h new file mode 100644 index 0000000000..cd6f244a94 --- /dev/null +++ b/backends/cloud/googledrive/googledriveresolveidrequest.h @@ -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_GOOGLEDRIVE_GOOGLEDRIVERESOLVEIDREQUEST_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVERESOLVEIDREQUEST_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 GoogleDrive { + +class GoogleDriveStorage; + +class GoogleDriveResolveIdRequest: public Networking::Request { + Common::String _requestedPath; + GoogleDriveStorage *_storage; + Storage::UploadCallback _uploadCallback; + Common::String _currentDirectory; + Common::String _currentDirectoryId; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void listNextDirectory(StorageFile fileToReturn); + void listedDirectoryCallback(Storage::FileArrayResponse response); + void listedDirectoryErrorCallback(Networking::ErrorResponse error); + void finishFile(StorageFile file); +public: + GoogleDriveResolveIdRequest(GoogleDriveStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive = false); //TODO: why upload? + virtual ~GoogleDriveResolveIdRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index eef7f1f28d..b0c0d47ecf 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -31,6 +31,8 @@ #include "common/debug.h" #include "common/json.h" #include +#include "googledrivelistdirectorybyidrequest.h" +#include "googledriveresolveidrequest.h" namespace Cloud { namespace GoogleDrive { @@ -177,6 +179,25 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne delete json; } +void GoogleDriveStorage::createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("NULL passed instead of JSON"); + delete outerCallback; + return; + } + + debug("%s", json->stringify(true).c_str()); + + if (outerCallback) { + Common::JSONObject info = json->asObject(); + ///(*outerCallback)(BoolResponse(nullptr, true); + delete outerCallback; + } + + delete json; +} + void GoogleDriveStorage::printJson(Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { @@ -211,11 +232,23 @@ void GoogleDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback delete response.value; } +Networking::Request *GoogleDriveStorage::resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFile); + return addRequest(new GoogleDriveResolveIdRequest(this, path, callback, errorCallback)); +} + Networking::Request *GoogleDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { //return addRequest(new GoogleDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); return nullptr; //TODO } +Networking::Request *GoogleDriveStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFiles); + return addRequest(new GoogleDriveListDirectoryByIdRequest(this, id, callback, errorCallback)); +} + Networking::Request *GoogleDriveStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { //return addRequest(new GoogleDriveUploadRequest(this, path, contents, callback, errorCallback)); return nullptr; //TODO @@ -240,8 +273,11 @@ void GoogleDriveStorage::fileDownloaded(BoolResponse response) { void GoogleDriveStorage::printFiles(FileArrayResponse response) { debug("files:"); Common::Array &files = response.value; - for (uint32 i = 0; i < files.size(); ++i) + for (uint32 i = 0; i < files.size(); ++i) { + debug("\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); debug("\t%s", files[i].path().c_str()); + debug(""); + } } void GoogleDriveStorage::printBool(BoolResponse response) { @@ -250,7 +286,8 @@ void GoogleDriveStorage::printBool(BoolResponse response) { void GoogleDriveStorage::printFile(UploadResponse response) { debug("\nuploaded file info:"); - debug("\tpath: %s", response.value.path().c_str()); + debug("\tid: %s", response.value.path().c_str()); + debug("\tname: %s", response.value.name().c_str()); debug("\tsize: %u", response.value.size()); debug("\ttimestamp: %u", response.value.timestamp()); } @@ -268,6 +305,33 @@ Networking::Request *GoogleDriveStorage::createDirectory(Common::String path, Bo return nullptr; //TODO } +Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + //return addRequest(new GoogleDriveCreateDirectoryRequest(this, path, callback, errorCallback)); + Common::String url = "https://www.googleapis.com/drive/v3/files"; + //Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveListDirectoryByIdRequest::responseCallback); + //Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveListDirectoryByIdRequest::errorCallback); + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::createDirectoryInnerCallback, callback); + Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + accessToken()); + request->addHeader("Content-Type: application/json"); + + Common::JSONArray parentsArray; + parentsArray.push_back(new Common::JSONValue(parentId)); + + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("mimeType", new Common::JSONValue("application/vnd.google-apps.folder")); + jsonRequestParameters.setVal("name", new Common::JSONValue(name)); + jsonRequestParameters.setVal("parents", new Common::JSONValue(parentsArray)); + //jsonRequestParameters.setVal("include_deleted", new Common::JSONValue(false)); + + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + return addRequest(request); + return nullptr; //TODO +} + Networking::Request *GoogleDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printInfo); Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::infoInnerCallback, callback); diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 8a82a54533..274bc78401 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -52,6 +52,9 @@ class GoogleDriveStorage: public Cloud::Storage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); + /** Returns bool based on JSON response from cloud. */ + void createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse json); + void printJson(Networking::JsonResponse response); void fileDownloaded(BoolResponse response); void printFiles(FileArrayResponse response); @@ -59,7 +62,7 @@ class GoogleDriveStorage: public Cloud::Storage { void printFile(UploadResponse response); void printInfo(StorageInfoResponse response); - void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); + void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); public: virtual ~GoogleDriveStorage(); @@ -78,9 +81,15 @@ public: /** Public Cloud API comes down there. */ - /** Returns ListDirectoryStatus struct with list of files. */ + /** Returns StorageFile with the resolved file's id. */ + virtual Networking::Request *resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns Array - the list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + /** Returns Array - the list of files. */ + virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback); + /** Returns UploadStatus struct with info about uploaded file. */ virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); @@ -93,6 +102,9 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); + /** Calls the callback when finished. */ + virtual Networking::Request *createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback); + /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp index b37b5e0d53..452cce3cf3 100644 --- a/backends/cloud/storagefile.cpp +++ b/backends/cloud/storagefile.cpp @@ -53,4 +53,12 @@ StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { _isDirectory = dir; } +StorageFile::StorageFile(Common::String id, Common::String name, uint32 sz, uint32 ts, bool dir) { + _path = id; + _name = name; + _size = sz; + _timestamp = ts; + _isDirectory = dir; +} + } // End of namespace Cloud diff --git a/backends/cloud/storagefile.h b/backends/cloud/storagefile.h index 704a03867f..7503653d6b 100644 --- a/backends/cloud/storagefile.h +++ b/backends/cloud/storagefile.h @@ -41,6 +41,9 @@ public: StorageFile(); //invalid empty file StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir); + /** In this constructor is used to storage (in Google Drive, for example) */ + StorageFile(Common::String id, Common::String name, uint32 sz, uint32 ts, bool dir); + Common::String path() const { return _path; } Common::String name() const { return _name; } uint32 size() const { return _size; } -- cgit v1.2.3 From b4b6ee0186750d6f2e8143313fc059c20512c306 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 6 Jun 2016 21:24:53 +0600 Subject: CLOUD: Add GoogleDriveCreateDirectory Now we can create directories in Google Drive by path, not parent id + directory name! --- backends/cloud/cloudmanager.cpp | 33 +++++- .../googledrivecreatedirectoryrequest.cpp | 114 +++++++++++++++++++++ .../googledrivecreatedirectoryrequest.h | 62 +++++++++++ .../googledrive/googledriveresolveidrequest.cpp | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 37 ++++--- 5 files changed, 233 insertions(+), 15 deletions(-) create mode 100644 backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp create mode 100644 backends/cloud/googledrive/googledrivecreatedirectoryrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 03cc8f264b..0be52cd886 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -126,7 +126,38 @@ void CloudManager::testFeature() { Storage *storage = getCurrentStorage(); //if (storage) storage->info(nullptr, nullptr); GoogleDrive::GoogleDriveStorage *gd = dynamic_cast(storage); - if (gd) gd->resolveFileId("firstfolder/subfolder", nullptr, nullptr); + if (gd) { + //new folder in root: + + //gd->createDirectory("newfolder1", nullptr, nullptr); + + //check it's there: + + //gd->listDirectoryById("appDataFolder", nullptr, nullptr); + + //new folder in firstfolder: + + //gd->createDirectory("firstfolder/newfolder2", nullptr, nullptr); + + //check it's there: + + //gd->listDirectoryById("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", nullptr, nullptr); + + //create existing folder in firstfolder: + + //gd->createDirectory("firstfolder/subfolder", nullptr, nullptr); + + //check no new folder there: + + //gd->listDirectoryById("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", nullptr, nullptr); + + //create folder in subfolder: + + //gd->createDirectory("firstfolder/subfolder/newfolder3", nullptr, nullptr); + + //check it's there: + + //gd->listDirectoryById("1OysvorQlmGl2ObMGb1c-JnjfC5yFL-Zj7AsQQhNNBnrk", nullptr, nullptr); + + //one more time: + + //gd->createDirectory("firstfolder/subfolder/newfolder3/megafolder", nullptr, nullptr); + + //check it's there: + + gd->listDirectoryById("1OXWPtfNgnmR_1K7SDm2v5J923bbAWrTdVDj-zRppLZDw", nullptr, nullptr); + } + //gd->resolveFileId("firstfolder/subfolder", nullptr, nullptr); //gd->listDirectoryById("appDataFolder", nullptr, nullptr); //gd->listDirectoryById("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", nullptr, nullptr); //gd->createDirectoryWithParentId("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", "subfolder", nullptr, nullptr); diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp new file mode 100644 index 0000000000..213f030c26 --- /dev/null +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.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/googledrive/googledrivecreatedirectoryrequest.h" +#include "backends/cloud/googledrive/googledrivestorage.h" +#include "common/debug.h" + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveCreateDirectoryRequest::GoogleDriveCreateDirectoryRequest(GoogleDriveStorage *storage, Common::String parentPath, Common::String directoryName, Storage::BoolCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), + _requestedParentPath(parentPath), _requestedDirectoryName(directoryName), _storage(storage), _boolCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +GoogleDriveCreateDirectoryRequest::~GoogleDriveCreateDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; +} + +void GoogleDriveCreateDirectoryRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _currentDirectory = ""; + _currentDirectoryId = "appDataFolder"; + _ignoreCallback = false; + + //find out the parent id + Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::idResolveFailedCallback); + Common::String path = _requestedParentPath; + path += "/"; + path += _requestedDirectoryName; + _workingRequest = _storage->resolveFileId(path, innerCallback, innerErrorCallback); +} + +void GoogleDriveCreateDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //resolved => folder already exists + finishSuccess(false); +} + +void GoogleDriveCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //not resolved => folder not exists + if (error.response.contains("no such file found in its parent directory")) { + //parent's id after the '\n' + Common::String parentId = error.response; + for (uint32 i = 0; i < parentId.size(); ++i) + if (parentId[i] == '\n') { + parentId.erase(0, i+1); + break; + } + + Storage::BoolCallback callback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdDirectoryErrorCallback); + _workingRequest = _storage->createDirectoryWithParentId(parentId, _requestedDirectoryName, callback, failureCallback); + return; + } + + finishError(error); +} + +void GoogleDriveCreateDirectoryRequest::createdDirectoryCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishSuccess(response.value); +} + +void GoogleDriveCreateDirectoryRequest::createdDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveCreateDirectoryRequest::handle() {} + +void GoogleDriveCreateDirectoryRequest::restart() { start(); } + +void GoogleDriveCreateDirectoryRequest::finishSuccess(bool success) { + Request::finishSuccess(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h new file mode 100644 index 0000000000..0ac178e8a6 --- /dev/null +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h @@ -0,0 +1,62 @@ +/* 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_GOOGLEDRIVE_GOOGLEDRIVECREATEDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVECREATEDIRECTORYREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace GoogleDrive { + +class GoogleDriveStorage; + +class GoogleDriveCreateDirectoryRequest: public Networking::Request { + Common::String _requestedParentPath; + Common::String _requestedDirectoryName; + GoogleDriveStorage *_storage; + Storage::BoolCallback _boolCallback; + Common::String _currentDirectory; + Common::String _currentDirectoryId; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void createdDirectoryCallback(Storage::BoolResponse response); + void createdDirectoryErrorCallback(Networking::ErrorResponse error); + void finishSuccess(bool success); +public: + GoogleDriveCreateDirectoryRequest(GoogleDriveStorage *storage, Common::String parentPath, Common::String directoryName, Storage::BoolCallback cb, Networking::ErrorCallback ecb); + virtual ~GoogleDriveCreateDirectoryRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp index bde17b4533..5dcb5c6e11 100644 --- a/backends/cloud/googledrive/googledriveresolveidrequest.cpp +++ b/backends/cloud/googledrive/googledriveresolveidrequest.cpp @@ -104,7 +104,7 @@ void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResp Common::String path = _currentDirectory; if (path != "") path += "/"; path += currentLevelName; - if (path == _requestedPath) finishError(Networking::ErrorResponse(this, false, true, "no such file found in its parent directory", 404)); + if (path == _requestedPath) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); } } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index b0c0d47ecf..1750dc9646 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -33,6 +33,7 @@ #include #include "googledrivelistdirectorybyidrequest.h" #include "googledriveresolveidrequest.h" +#include "googledrivecreatedirectoryrequest.h" namespace Cloud { namespace GoogleDrive { @@ -187,11 +188,9 @@ void GoogleDriveStorage::createDirectoryInnerCallback(BoolCallback outerCallback return; } - debug("%s", json->stringify(true).c_str()); - if (outerCallback) { - Common::JSONObject info = json->asObject(); - ///(*outerCallback)(BoolResponse(nullptr, true); + Common::JSONObject info = json->asObject(); + (*outerCallback)(BoolResponse(nullptr, info.contains("id"))); delete outerCallback; } @@ -240,7 +239,7 @@ Networking::Request *GoogleDriveStorage::resolveFileId(Common::String path, Uplo Networking::Request *GoogleDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { //return addRequest(new GoogleDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); - return nullptr; //TODO + return nullptr; } Networking::Request *GoogleDriveStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { @@ -301,16 +300,30 @@ void GoogleDriveStorage::printInfo(StorageInfoResponse response) { Networking::Request *GoogleDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - //return addRequest(new GoogleDriveCreateDirectoryRequest(this, path, callback, errorCallback)); - return nullptr; //TODO + if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printBool); + + //find out the parent path and directory name + Common::String parentPath = "", directoryName = path; + for (uint32 i = path.size(); i > 0; --i) { + if (path[i-1] == '/' || path[i-1] == '\\') { + parentPath = path; + parentPath.erase(i-1); + directoryName.erase(0, i); + break; + } + } + + if (parentPath == "") { + return createDirectoryWithParentId("appDataFolder", directoryName, callback, errorCallback); + } + + return addRequest(new GoogleDriveCreateDirectoryRequest(this, parentPath, directoryName, callback, errorCallback)); } Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - //return addRequest(new GoogleDriveCreateDirectoryRequest(this, path, callback, errorCallback)); - Common::String url = "https://www.googleapis.com/drive/v3/files"; - //Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveListDirectoryByIdRequest::responseCallback); - //Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveListDirectoryByIdRequest::errorCallback); + + Common::String url = "https://www.googleapis.com/drive/v3/files"; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::createDirectoryInnerCallback, callback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + accessToken()); @@ -323,13 +336,11 @@ Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::Str jsonRequestParameters.setVal("mimeType", new Common::JSONValue("application/vnd.google-apps.folder")); jsonRequestParameters.setVal("name", new Common::JSONValue(name)); jsonRequestParameters.setVal("parents", new Common::JSONValue(parentsArray)); - //jsonRequestParameters.setVal("include_deleted", new Common::JSONValue(false)); Common::JSONValue value(jsonRequestParameters); request->addPostField(Common::JSON::stringify(&value)); return addRequest(request); - return nullptr; //TODO } Networking::Request *GoogleDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { -- cgit v1.2.3 From d1d71afb0724c372143d2c303c70291ba43d2d68 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 7 Jun 2016 13:07:46 +0600 Subject: CLOUD: Add GoogleDriveListDirectoryRequest When listing directories, you get a list of StorageFiles, which path() is actually Google Drive id. Thus, if you list a directory recursively, you won't be able to determine whether all files are within one directory or have some hierarchy. I'd fix that as soon as it would be needed. --- backends/cloud/cloudmanager.cpp | 6 +- .../googledrivelistdirectoryrequest.cpp | 117 +++++++++++++++++++++ .../googledrive/googledrivelistdirectoryrequest.h | 65 ++++++++++++ .../googledrive/googledriveresolveidrequest.cpp | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 6 +- 5 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp create mode 100644 backends/cloud/googledrive/googledrivelistdirectoryrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 0be52cd886..64fa19ceb9 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -155,7 +155,11 @@ void CloudManager::testFeature() { //gd->createDirectory("firstfolder/subfolder/newfolder3/megafolder", nullptr, nullptr); //check it's there: + - gd->listDirectoryById("1OXWPtfNgnmR_1K7SDm2v5J923bbAWrTdVDj-zRppLZDw", nullptr, nullptr); + //gd->listDirectoryById("1OXWPtfNgnmR_1K7SDm2v5J923bbAWrTdVDj-zRppLZDw", nullptr, nullptr); + + //gd->listDirectory("", nullptr, nullptr); + //gd->listDirectory("firstfolder", nullptr, nullptr); + gd->listDirectory("firstfolder/subfolder", nullptr, nullptr, true); } //gd->resolveFileId("firstfolder/subfolder", nullptr, nullptr); //gd->listDirectoryById("appDataFolder", nullptr, nullptr); diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp new file mode 100644 index 0000000000..803682b684 --- /dev/null +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp @@ -0,0 +1,117 @@ +/* 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/googledrive/googledrivelistdirectoryrequest.h" +#include "backends/cloud/googledrive/googledrivestorage.h" + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveListDirectoryRequest::GoogleDriveListDirectoryRequest(GoogleDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), + _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +GoogleDriveListDirectoryRequest::~GoogleDriveListDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _listDirectoryCallback; +} + +void GoogleDriveListDirectoryRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _files.clear(); + _directoriesQueue.clear(); + _currentDirectory = ""; + _ignoreCallback = false; + + //find out that directory's id + Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::idResolveErrorCallback); + _workingRequest = _storage->resolveFileId(_requestedPath, innerCallback, innerErrorCallback); +} + +void GoogleDriveListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + _directoriesQueue.push_back(response.value.path()); + listNextDirectory(); +} + +void GoogleDriveListDirectoryRequest::idResolveErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveListDirectoryRequest::listNextDirectory() { + if (_directoriesQueue.empty()) { + finishSuccess(_files); + return; + } + + _currentDirectory = _directoriesQueue.back(); + _directoriesQueue.pop_back(); + + Storage::FileArrayCallback callback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::listedDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::listedDirectoryErrorCallback); + _workingRequest = _storage->listDirectoryById(_currentDirectory, callback, failureCallback); +} + +void GoogleDriveListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + for (uint32 i = 0; i < response.value.size(); ++i) { + StorageFile &file = response.value[i]; + _files.push_back(file); + if (_requestedRecursive && file.isDirectory()) { + _directoriesQueue.push_back(file.path()); + } + } + + listNextDirectory(); +} + +void GoogleDriveListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveListDirectoryRequest::handle() {} + +void GoogleDriveListDirectoryRequest::restart() { start(); } + +void GoogleDriveListDirectoryRequest::finishSuccess(Common::Array &files) { + Request::finishSuccess(); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h new file mode 100644 index 0000000000..3eee83fed1 --- /dev/null +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h @@ -0,0 +1,65 @@ +/* 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_GOOGLEDRIVE_GOOGLEDRIVELISTDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVELISTDIRECTORYREQUEST_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 GoogleDrive { + +class GoogleDriveStorage; + +class GoogleDriveListDirectoryRequest: public Networking::Request { + Common::String _requestedPath; + bool _requestedRecursive; + GoogleDriveStorage *_storage; + Storage::ListDirectoryCallback _listDirectoryCallback; + Common::Array _files; + Common::Array _directoriesQueue; + Common::String _currentDirectory; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveErrorCallback(Networking::ErrorResponse error); + void listNextDirectory(); + void listedDirectoryCallback(Storage::FileArrayResponse response); + void listedDirectoryErrorCallback(Networking::ErrorResponse error); + void finishSuccess(Common::Array &files); +public: + GoogleDriveListDirectoryRequest(GoogleDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); + virtual ~GoogleDriveListDirectoryRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp index 5dcb5c6e11..0ef0cd982f 100644 --- a/backends/cloud/googledrive/googledriveresolveidrequest.cpp +++ b/backends/cloud/googledrive/googledriveresolveidrequest.cpp @@ -53,7 +53,7 @@ void GoogleDriveResolveIdRequest::start() { _currentDirectoryId = "appDataFolder"; _ignoreCallback = false; - listNextDirectory(StorageFile("", 0, 0, false)); + listNextDirectory(StorageFile(_currentDirectoryId, 0, 0, true)); } void GoogleDriveResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 1750dc9646..3c85b1f074 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -34,6 +34,7 @@ #include "googledrivelistdirectorybyidrequest.h" #include "googledriveresolveidrequest.h" #include "googledrivecreatedirectoryrequest.h" +#include "googledrivelistdirectoryrequest.h" namespace Cloud { namespace GoogleDrive { @@ -238,8 +239,9 @@ Networking::Request *GoogleDriveStorage::resolveFileId(Common::String path, Uplo } Networking::Request *GoogleDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - //return addRequest(new GoogleDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); - return nullptr; + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFiles); + return addRequest(new GoogleDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); } Networking::Request *GoogleDriveStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { -- cgit v1.2.3 From 505d3764cb9c873b1dbefcb0d7b2cc7b587c6a42 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 7 Jun 2016 13:49:26 +0600 Subject: CLOUD: Fix GoogleDriveStorage to work with root folder Now it needs another scope and uses "root" instead of "appDataFolder". --- backends/cloud/cloudmanager.cpp | 33 ---------------------- .../googledrivecreatedirectoryrequest.cpp | 2 -- .../googledrivecreatedirectoryrequest.h | 2 -- .../googledrivelistdirectorybyidrequest.cpp | 20 ++++++++++--- .../googledrive/googledriveresolveidrequest.cpp | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 4 +-- 6 files changed, 19 insertions(+), 44 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 64fa19ceb9..7613b2cbbf 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -127,39 +127,6 @@ void CloudManager::testFeature() { //if (storage) storage->info(nullptr, nullptr); GoogleDrive::GoogleDriveStorage *gd = dynamic_cast(storage); if (gd) { - //new folder in root: + - //gd->createDirectory("newfolder1", nullptr, nullptr); - - //check it's there: + - //gd->listDirectoryById("appDataFolder", nullptr, nullptr); - - //new folder in firstfolder: + - //gd->createDirectory("firstfolder/newfolder2", nullptr, nullptr); - - //check it's there: + - //gd->listDirectoryById("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", nullptr, nullptr); - - //create existing folder in firstfolder: + - //gd->createDirectory("firstfolder/subfolder", nullptr, nullptr); - - //check no new folder there: + - //gd->listDirectoryById("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", nullptr, nullptr); - - //create folder in subfolder: + - //gd->createDirectory("firstfolder/subfolder/newfolder3", nullptr, nullptr); - - //check it's there: + - //gd->listDirectoryById("1OysvorQlmGl2ObMGb1c-JnjfC5yFL-Zj7AsQQhNNBnrk", nullptr, nullptr); - - //one more time: + - //gd->createDirectory("firstfolder/subfolder/newfolder3/megafolder", nullptr, nullptr); - - //check it's there: + - //gd->listDirectoryById("1OXWPtfNgnmR_1K7SDm2v5J923bbAWrTdVDj-zRppLZDw", nullptr, nullptr); - - //gd->listDirectory("", nullptr, nullptr); - //gd->listDirectory("firstfolder", nullptr, nullptr); - gd->listDirectory("firstfolder/subfolder", nullptr, nullptr, true); } //gd->resolveFileId("firstfolder/subfolder", nullptr, nullptr); //gd->listDirectoryById("appDataFolder", nullptr, nullptr); diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp index 213f030c26..1554fef200 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp @@ -45,8 +45,6 @@ void GoogleDriveCreateDirectoryRequest::start() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); _workingRequest = nullptr; - _currentDirectory = ""; - _currentDirectoryId = "appDataFolder"; _ignoreCallback = false; //find out the parent id diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h index 0ac178e8a6..6c5ccddf6c 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h @@ -37,8 +37,6 @@ class GoogleDriveCreateDirectoryRequest: public Networking::Request { Common::String _requestedDirectoryName; GoogleDriveStorage *_storage; Storage::BoolCallback _boolCallback; - Common::String _currentDirectory; - Common::String _currentDirectoryId; Request *_workingRequest; bool _ignoreCallback; diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 0915b623f3..f7aa7a1c0c 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -55,7 +55,8 @@ void GoogleDriveListDirectoryByIdRequest::start() { } void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) { - Common::String url = "https://www.googleapis.com/drive/v3/files?spaces=appDataFolder"; + Common::String url = "https://www.googleapis.com/drive/v3/files?spaces=drive&fields=files%28id,mimeType,modifiedTime,name,size%29,nextPageToken"; + //files(id,mimeType,modifiedTime,name,size),nextPageToken if (pageToken != "") url += "&pageToken=" + pageToken; url += "&q=%27" + _requestedId + "%27+in+parents"; @@ -66,6 +67,17 @@ void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) _workingRequest = ConnMan.addRequest(request); } +namespace { +uint64 atoull(Common::String s) { + uint64 result = 0; + for (uint32 i = 0; i < s.size(); ++i) { + if (s[i] < '0' || s[i] > '9') break; + result = result * 10L + (s[i] - '0'); + } + return result; +} +} + void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; @@ -100,10 +112,10 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo Common::String name = item.getVal("name")->asString(); bool isDirectory = (item.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); uint32 size = 0, timestamp = 0; - if (!isDirectory) { - size = item.getVal("size")->asIntegerNumber(); + if (item.contains("size") && item.getVal("size")->isString()) + size = atoull(item.getVal("size")->asString()); + if (item.contains("modifiedTime") && item.getVal("modifiedTime")->isString()) timestamp = ISO8601::convertToTimestamp(item.getVal("modifiedTime")->asString()); - } _files.push_back(StorageFile(path, name, size, timestamp, isDirectory)); } } diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp index 0ef0cd982f..a9adb82969 100644 --- a/backends/cloud/googledrive/googledriveresolveidrequest.cpp +++ b/backends/cloud/googledrive/googledriveresolveidrequest.cpp @@ -50,7 +50,7 @@ void GoogleDriveResolveIdRequest::start() { if (_workingRequest) _workingRequest->finish(); _workingRequest = nullptr; _currentDirectory = ""; - _currentDirectoryId = "appDataFolder"; + _currentDirectoryId = "root"; _ignoreCallback = false; listNextDirectory(StorageFile(_currentDirectoryId, 0, 0, true)); diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 3c85b1f074..dce35b5904 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -316,7 +316,7 @@ Networking::Request *GoogleDriveStorage::createDirectory(Common::String path, Bo } if (parentPath == "") { - return createDirectoryWithParentId("appDataFolder", directoryName, callback, errorCallback); + return createDirectoryWithParentId("root", directoryName, callback, errorCallback); } return addRequest(new GoogleDriveCreateDirectoryRequest(this, parentPath, directoryName, callback, errorCallback)); @@ -379,7 +379,7 @@ Common::String GoogleDriveStorage::getAuthLink() { url += "&redirect_uri=http://localhost"; //that's for copy-pasting //url += "&redirect_uri=http%3A%2F%2Flocalhost"; //that's "http://localhost" for automatic opening url += "&client_id="; url += KEY; - url += "&scope=https://www.googleapis.com/auth/drive.appfolder"; //for copy-pasting + url += "&scope=https://www.googleapis.com/auth/drive"; //for copy-pasting return url; } -- cgit v1.2.3 From c968f0143c5e36cc9fc429832622eb180732caf8 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 7 Jun 2016 16:25:05 +0600 Subject: CLOUD: Make GoogleDriveResolveIdRequest case-insensitive --- backends/cloud/googledrive/googledriveresolveidrequest.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp index a9adb82969..9cd13a78a6 100644 --- a/backends/cloud/googledrive/googledriveresolveidrequest.cpp +++ b/backends/cloud/googledrive/googledriveresolveidrequest.cpp @@ -57,7 +57,7 @@ void GoogleDriveResolveIdRequest::start() { } void GoogleDriveResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { - if (_currentDirectory == _requestedPath) { + if (_currentDirectory.equalsIgnoreCase(_requestedPath)) { finishFile(fileToReturn); return; } @@ -89,7 +89,7 @@ void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResp Common::Array &files = response.value; bool found = false; for (uint32 i = 0; i < files.size(); ++i) { - if (files[i].isDirectory() && files[i].name() == currentLevelName) { + if (files[i].isDirectory() && files[i].name().equalsIgnoreCase(currentLevelName)) { if (_currentDirectory != "") _currentDirectory += "/"; _currentDirectory += files[i].name(); _currentDirectoryId = files[i].path(); @@ -104,7 +104,7 @@ void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResp Common::String path = _currentDirectory; if (path != "") path += "/"; path += currentLevelName; - if (path == _requestedPath) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); + if (path.equalsIgnoreCase(_requestedPath)) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); } } -- cgit v1.2.3 From bf71ba9a1c98b39647edb248e913322ee38a0af5 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 7 Jun 2016 16:27:04 +0600 Subject: CLOUD: Update GoogleDriveCreateDirectoryRequest Now it also creates the "base" ScummVM directory if there is no such directory yet. This way SavesSyncRequest works fine when no "ScummVM" or "ScummVM/Saves" folder exist in the Google Drive. --- .../googledrivecreatedirectoryrequest.cpp | 30 ++++++++++++++++++++-- .../googledrivecreatedirectoryrequest.h | 3 +++ backends/cloud/googledrive/googledrivestorage.cpp | 6 +---- backends/cloud/savessyncrequest.cpp | 9 +++++++ 4 files changed, 41 insertions(+), 7 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp index 1554fef200..54eff3d6ad 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp @@ -46,12 +46,38 @@ void GoogleDriveCreateDirectoryRequest::start() { if (_workingRequest) _workingRequest->finish(); _workingRequest = nullptr; _ignoreCallback = false; + + //the only exception when we create parent folder - is when it's ScummVM/ base folder + Common::String prefix = _requestedParentPath; + if (prefix.size() > 7) prefix.erase(7); + if (prefix.equalsIgnoreCase("ScummVM")) { + Storage::BoolCallback callback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdBaseDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdBaseDirectoryErrorCallback); + _workingRequest = _storage->createDirectory("ScummVM", callback, failureCallback); + return; + } - //find out the parent id + resolveId(); +} + +void GoogleDriveCreateDirectoryRequest::createdBaseDirectoryCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + resolveId(); +} + +void GoogleDriveCreateDirectoryRequest::createdBaseDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveCreateDirectoryRequest::resolveId() { + //check whether such folder already exists Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::idResolvedCallback); Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::idResolveFailedCallback); Common::String path = _requestedParentPath; - path += "/"; + if (_requestedParentPath != "") path += "/"; path += _requestedDirectoryName; _workingRequest = _storage->resolveFileId(path, innerCallback, innerErrorCallback); } diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h index 6c5ccddf6c..ede84277de 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h @@ -41,6 +41,9 @@ class GoogleDriveCreateDirectoryRequest: public Networking::Request { bool _ignoreCallback; void start(); + void createdBaseDirectoryCallback(Storage::BoolResponse response); + void createdBaseDirectoryErrorCallback(Networking::ErrorResponse error); + void resolveId(); void idResolvedCallback(Storage::UploadResponse response); void idResolveFailedCallback(Networking::ErrorResponse error); void createdDirectoryCallback(Storage::BoolResponse response); diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index dce35b5904..d7dbd529e5 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -315,10 +315,6 @@ Networking::Request *GoogleDriveStorage::createDirectory(Common::String path, Bo } } - if (parentPath == "") { - return createDirectoryWithParentId("root", directoryName, callback, errorCallback); - } - return addRequest(new GoogleDriveCreateDirectoryRequest(this, parentPath, directoryName, callback, errorCallback)); } @@ -353,7 +349,7 @@ Networking::Request *GoogleDriveStorage::info(StorageInfoCallback callback, Netw return addRequest(request); } -Common::String GoogleDriveStorage::savesDirectoryPath() { return "saves/"; } +Common::String GoogleDriveStorage::savesDirectoryPath() { return "scummvm/saves/"; } GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 3c41c005e4..1d4ec4c2ee 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -158,9 +158,18 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er } } } + + //TODO: Google Drive-related JSON error } delete value; } + + //Google Drive-related ScummVM-based error + if (error.response.contains("subdirectory not found")) { + irrecoverable = false; //base "/ScummVM/" folder not found + } else if (error.response.contains("no such file found in its parent directory")) { + irrecoverable = false; //"Saves" folder within "/ScummVM/" not found + } } if (irrecoverable) { -- cgit v1.2.3 From 7e6a89c141d621b5caf8c66a58ecbcf60b2d52c1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 8 Jun 2016 12:34:13 +0600 Subject: CLOUD: Update GoogleDriveStorage and StorageFile Because of the Google Drive StorageFile now contains yet another field, `id`. For other storages `id` == `path`, and thus all common Requests (such as SavesSyncRequest, DownloadFolderRequest, etc) must be using id() instead of path(). That way these Requests won't cause id resolving which could be quite slow (when you call it for all files in the folder, for example). --- .../googledrive/googledrivelistdirectorybyidrequest.cpp | 6 ++++-- .../googledrive/googledrivelistdirectoryrequest.cpp | 14 ++++++++++---- .../cloud/googledrive/googledrivelistdirectoryrequest.h | 4 ++-- .../cloud/googledrive/googledriveresolveidrequest.cpp | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 1 + backends/cloud/storagefile.cpp | 7 +++++-- backends/cloud/storagefile.h | 17 +++++++++++++---- 7 files changed, 36 insertions(+), 15 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index f7aa7a1c0c..f9af363254 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -108,7 +108,7 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo Common::JSONArray items = responseObject.getVal("files")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { Common::JSONObject item = items[i]->asObject(); - Common::String path = item.getVal("id")->asString(); + Common::String id = item.getVal("id")->asString(); Common::String name = item.getVal("name")->asString(); bool isDirectory = (item.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); uint32 size = 0, timestamp = 0; @@ -116,7 +116,9 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo size = atoull(item.getVal("size")->asString()); if (item.contains("modifiedTime") && item.getVal("modifiedTime")->isString()) timestamp = ISO8601::convertToTimestamp(item.getVal("modifiedTime")->asString()); - _files.push_back(StorageFile(path, name, size, timestamp, isDirectory)); + + //as we list directory by id, we can't determine full path for the file, so we leave it empty + _files.push_back(StorageFile(id, "", name, size, timestamp, isDirectory)); } } diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp index 803682b684..8811ffc938 100644 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp @@ -46,7 +46,7 @@ void GoogleDriveListDirectoryRequest::start() { _workingRequest = nullptr; _files.clear(); _directoriesQueue.clear(); - _currentDirectory = ""; + _currentDirectory = StorageFile(); _ignoreCallback = false; //find out that directory's id @@ -59,7 +59,9 @@ void GoogleDriveListDirectoryRequest::idResolvedCallback(Storage::UploadResponse _workingRequest = nullptr; if (_ignoreCallback) return; - _directoriesQueue.push_back(response.value.path()); + StorageFile directory = response.value; + directory.setPath(_requestedPath); + _directoriesQueue.push_back(directory); listNextDirectory(); } @@ -80,7 +82,7 @@ void GoogleDriveListDirectoryRequest::listNextDirectory() { Storage::FileArrayCallback callback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::listedDirectoryCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::listedDirectoryErrorCallback); - _workingRequest = _storage->listDirectoryById(_currentDirectory, callback, failureCallback); + _workingRequest = _storage->listDirectoryById(_currentDirectory.id(), callback, failureCallback); } void GoogleDriveListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { @@ -89,9 +91,13 @@ void GoogleDriveListDirectoryRequest::listedDirectoryCallback(Storage::FileArray for (uint32 i = 0; i < response.value.size(); ++i) { StorageFile &file = response.value[i]; + Common::String path = _currentDirectory.path(); + if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') path += '/'; + path += file.name(); + file.setPath(path); _files.push_back(file); if (_requestedRecursive && file.isDirectory()) { - _directoriesQueue.push_back(file.path()); + _directoriesQueue.push_back(file); } } diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h index 3eee83fed1..bea195f70a 100644 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h @@ -39,8 +39,8 @@ class GoogleDriveListDirectoryRequest: public Networking::Request { GoogleDriveStorage *_storage; Storage::ListDirectoryCallback _listDirectoryCallback; Common::Array _files; - Common::Array _directoriesQueue; - Common::String _currentDirectory; + Common::Array _directoriesQueue; + StorageFile _currentDirectory; Request *_workingRequest; bool _ignoreCallback; diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp index 9cd13a78a6..e3ab97ea6c 100644 --- a/backends/cloud/googledrive/googledriveresolveidrequest.cpp +++ b/backends/cloud/googledrive/googledriveresolveidrequest.cpp @@ -92,7 +92,7 @@ void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResp if (files[i].isDirectory() && files[i].name().equalsIgnoreCase(currentLevelName)) { if (_currentDirectory != "") _currentDirectory += "/"; _currentDirectory += files[i].name(); - _currentDirectoryId = files[i].path(); + _currentDirectoryId = files[i].id(); ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); listNextDirectory(files[i]); found = true; diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index d7dbd529e5..6b5c437fd7 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -277,6 +277,7 @@ void GoogleDriveStorage::printFiles(FileArrayResponse response) { for (uint32 i = 0; i < files.size(); ++i) { debug("\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); debug("\t%s", files[i].path().c_str()); + debug("\t%s", files[i].id().c_str()); debug(""); } } diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp index 452cce3cf3..4bee92edce 100644 --- a/backends/cloud/storagefile.cpp +++ b/backends/cloud/storagefile.cpp @@ -25,6 +25,7 @@ namespace Cloud { StorageFile::StorageFile() { + _id = ""; _path = ""; _name = ""; _size = 0; @@ -33,6 +34,7 @@ StorageFile::StorageFile() { } StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { + _id = pth; _path = pth; _name = pth; @@ -53,8 +55,9 @@ StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { _isDirectory = dir; } -StorageFile::StorageFile(Common::String id, Common::String name, uint32 sz, uint32 ts, bool dir) { - _path = id; +StorageFile::StorageFile(Common::String id, Common::String path, Common::String name, uint32 sz, uint32 ts, bool dir) { + _id = id; + _path = path; _name = name; _size = sz; _timestamp = ts; diff --git a/backends/cloud/storagefile.h b/backends/cloud/storagefile.h index 7503653d6b..1324cafc93 100644 --- a/backends/cloud/storagefile.h +++ b/backends/cloud/storagefile.h @@ -31,24 +31,33 @@ namespace Cloud { * StorageFile represents a file storaged on remote cloud storage. * It contains basic information about a file, and might be used * when listing directories or syncing files. + * + * Some storages (Google Drive, for example) don't have an actual + * path notation to address files. Instead, they are using ids. + * As resolving id by path is not a fast operation, it's required + * to use ids if they are known, but user-friendly paths are + * necessary too, because these are used by Requests. + * + * If storage supports path notation, id would actually contain path. */ class StorageFile { - Common::String _path, _name; + Common::String _id, _path, _name; uint32 _size, _timestamp; bool _isDirectory; public: StorageFile(); //invalid empty file StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir); + StorageFile(Common::String id, Common::String path, Common::String name, uint32 sz, uint32 ts, bool dir); - /** In this constructor is used to storage (in Google Drive, for example) */ - StorageFile(Common::String id, Common::String name, uint32 sz, uint32 ts, bool dir); - + Common::String id() const { return _id; } Common::String path() const { return _path; } Common::String name() const { return _name; } uint32 size() const { return _size; } uint32 timestamp() const { return _timestamp; } bool isDirectory() const { return _isDirectory; } + + void setPath(Common::String path) { _path = path; } }; } // End of namespace Cloud -- cgit v1.2.3 From 60add0df1b63dbd31b88edcabf0769eb675efab0 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 8 Jun 2016 12:45:58 +0600 Subject: CLOUD: Update Requests to use StorageFile::id() Only two places to update, as others still require id resolving. --- backends/cloud/folderdownloadrequest.cpp | 4 ++-- backends/cloud/savessyncrequest.cpp | 2 +- backends/cloud/storage.cpp | 5 +++++ backends/cloud/storage.h | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 19f6c6c9b7..905b0c79f4 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -109,8 +109,8 @@ void FolderDownloadRequest::downloadNextFile() { localPath = _localDirectoryPath + "/" + localPath; } debug("%s -> %s", remotePath.c_str(), localPath.c_str()); - _workingRequest = _storage->download( - remotePath, localPath, + _workingRequest = _storage->downloadById( + _currentFile.id(), localPath, new Common::Callback(this, &FolderDownloadRequest::fileDownloadedCallback), new Common::Callback(this, &FolderDownloadRequest::fileDownloadedErrorCallback) ); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 1d4ec4c2ee..cdf1dbac07 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -227,7 +227,7 @@ void SavesSyncRequest::downloadNextFile() { /////// debug("downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); /////// - _workingRequest = _storage->download(_currentDownloadingFile.path(), concatWithSavesPath(_currentDownloadingFile.name()), + _workingRequest = _storage->downloadById(_currentDownloadingFile.id(), concatWithSavesPath(_currentDownloadingFile.name()), new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), new Common::Callback(this, &SavesSyncRequest::fileDownloadedErrorCallback) ); diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 5458276e39..f0c1319846 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -92,6 +92,11 @@ Networking::Request *Storage::download(Common::String remotePath, Common::String return addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); } +Networking::Request *Storage::downloadById(Common::String remoteId, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { + //most Storages use paths instead of ids, so this should work + return download(remoteId, localPath, callback, errorCallback); +} + Networking::Request *Storage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); return addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 058e831e5d..3cf8fb55ff 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -122,6 +122,7 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *downloadById(Common::String remoteId, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Returns Common::Array with list of files, which were not downloaded. */ virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); -- cgit v1.2.3 From f0d61084daf7292d157e451c7bfc5485757eac43 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 8 Jun 2016 13:02:49 +0600 Subject: CLOUD: Update downloading in Storages Id should be used everywhere. --- backends/cloud/downloadrequest.cpp | 8 ++++---- backends/cloud/downloadrequest.h | 4 ++-- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 12 ++++++++++++ backends/cloud/googledrive/googledrivestorage.h | 4 ++++ backends/cloud/onedrive/onedrivestorage.cpp | 2 +- backends/cloud/onedrive/onedrivestorage.h | 2 +- backends/cloud/storage.cpp | 17 +++++++++++------ backends/cloud/storage.h | 3 ++- 10 files changed, 39 insertions(+), 17 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 7dde74f88d..307ea00aa2 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -27,8 +27,8 @@ namespace Cloud { -DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFile, Common::DumpFile *dumpFile): - Request(nullptr, ecb), _boolCallback(callback), _localFile(dumpFile), _remoteFileName(remoteFile), _storage(storage), +DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFileId, Common::DumpFile *dumpFile): + Request(nullptr, ecb), _boolCallback(callback), _localFile(dumpFile), _remoteFileId(remoteFileId), _storage(storage), _remoteFileStream(nullptr), _workingRequest(nullptr), _ignoreCallback(false) { start(); } @@ -47,8 +47,8 @@ void DownloadRequest::start() { //TODO: reopen DumpFile _ignoreCallback = false; - _workingRequest = _storage->streamFile( - _remoteFileName, + _workingRequest = _storage->streamFileById( + _remoteFileId, new Common::Callback(this, &DownloadRequest::streamCallback), new Common::Callback(this, &DownloadRequest::streamErrorCallback) ); diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index 9e3421d777..def69d47de 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -33,7 +33,7 @@ namespace Cloud { class DownloadRequest: public Networking::Request { Storage::BoolCallback _boolCallback; Common::DumpFile *_localFile; - Common::String _remoteFileName; + Common::String _remoteFileId; Storage *_storage; Networking::NetworkReadStream *_remoteFileStream; Request *_workingRequest; @@ -44,7 +44,7 @@ class DownloadRequest: public Networking::Request { void streamErrorCallback(Networking::ErrorResponse error); void finishSuccess(bool success); public: - DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFile, Common::DumpFile *dumpFile); + DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFileId, Common::DumpFile *dumpFile); virtual ~DownloadRequest(); virtual void handle(); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 861a58db4b..038a1683bf 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -117,7 +117,7 @@ Networking::Request *DropboxStorage::upload(Common::String path, Common::Seekabl return addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback)); } -Networking::Request *DropboxStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { +Networking::Request *DropboxStorage::streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("path", new Common::JSONValue(path)); Common::JSONValue value(jsonRequestParameters); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index c186d1e5d6..9ac0ffb166 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -74,7 +74,7 @@ public: virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 6b5c437fd7..c6e423e00d 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -263,6 +263,18 @@ Networking::Request *GoogleDriveStorage::streamFile(Common::String path, Network request->addHeader("Authorization: Bearer " + _token); return addRequest(request); */ + //TODO: resolve id + //TODO: then call streamFileById() + return nullptr; //TODO +} + +Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { + return nullptr; //TODO +} + +Networking::Request *GoogleDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { + //TODO: resolve id + //TODO: then call downloadById() return nullptr; //TODO } diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 274bc78401..a456030369 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -95,6 +95,10 @@ public: /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); + + /** Calls the callback when finished. */ + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index ca8a2346ad..c494f38a6c 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -204,7 +204,7 @@ Networking::Request *OneDriveStorage::upload(Common::String path, Common::Seekab return addRequest(new OneDriveUploadRequest(this, path, contents, callback, errorCallback)); } -Networking::Request *OneDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { +Networking::Request *OneDriveStorage::streamFileById(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index a09d68b6fd..8afdac8b0f 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -84,7 +84,7 @@ public: virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index f0c1319846..08ab9e9c90 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -76,7 +76,17 @@ Networking::Request *Storage::upload(Common::String remotePath, Common::String l return upload(remotePath, f, callback, errorCallback); } +Networking::Request *Storage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { + //most Storages use paths instead of ids, so this should work + return streamFile(path, callback, errorCallback); +} + Networking::Request *Storage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { + //most Storages use paths instead of ids, so this should work + return downloadById(remotePath, localPath, callback, errorCallback); +} + +Networking::Request *Storage::downloadById(Common::String remoteId, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); Common::DumpFile *f = new Common::DumpFile(); @@ -89,12 +99,7 @@ Networking::Request *Storage::download(Common::String remotePath, Common::String return nullptr; } - return addRequest(new DownloadRequest(this, callback, errorCallback, remotePath, f)); -} - -Networking::Request *Storage::downloadById(Common::String remoteId, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { - //most Storages use paths instead of ids, so this should work - return download(remoteId, localPath, callback, errorCallback); + return addRequest(new DownloadRequest(this, callback, errorCallback, remoteId, f)); } Networking::Request *Storage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 3cf8fb55ff..4a5e1236b7 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -118,7 +118,8 @@ public: virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback); /** 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); + virtual Networking::Request *streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Calls the callback when finished. */ virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); -- cgit v1.2.3 From e273e3d6e8dcca6f7e70d3e7c4e6dfc836832378 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 8 Jun 2016 14:17:35 +0600 Subject: CLOUD: Add GoogleDrive download-related requests GoogleDriveDownloadRequest, which resolves file id and then downloads it with GoogleDriveStorage::downloadById(). GoogleDriveStreamFileRequest, which resolves file id and then returns file stream with GoogleDriveStorage::streamFileById(). This commit also adds GoogleDriveStorage::streamFileById() itself. A minor GoogleDriveResolveIdRequest fix added. With these one can download files from Google Drive. --- .../googledrive/googledrivedownloadrequest.cpp | 91 ++++++++++++++++++++++ .../cloud/googledrive/googledrivedownloadrequest.h | 59 ++++++++++++++ .../googledrive/googledriveresolveidrequest.cpp | 12 +-- backends/cloud/googledrive/googledrivestorage.cpp | 53 ++++--------- backends/cloud/googledrive/googledrivestorage.h | 2 - .../googledrive/googledrivestreamfilerequest.cpp | 91 ++++++++++++++++++++++ .../googledrive/googledrivestreamfilerequest.h | 59 ++++++++++++++ 7 files changed, 322 insertions(+), 45 deletions(-) create mode 100644 backends/cloud/googledrive/googledrivedownloadrequest.cpp create mode 100644 backends/cloud/googledrive/googledrivedownloadrequest.h create mode 100644 backends/cloud/googledrive/googledrivestreamfilerequest.cpp create mode 100644 backends/cloud/googledrive/googledrivestreamfilerequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivedownloadrequest.cpp b/backends/cloud/googledrive/googledrivedownloadrequest.cpp new file mode 100644 index 0000000000..c885352fae --- /dev/null +++ b/backends/cloud/googledrive/googledrivedownloadrequest.cpp @@ -0,0 +1,91 @@ +/* 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/googledrive/googledrivedownloadrequest.h" +#include "backends/cloud/googledrive/googledrivestorage.h" + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveDownloadRequest::GoogleDriveDownloadRequest(GoogleDriveStorage *storage, Common::String remotePath, Common::String localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _requestedFile(remotePath), _requestedLocalFile(localPath), _storage(storage), _boolCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +GoogleDriveDownloadRequest::~GoogleDriveDownloadRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; +} + +void GoogleDriveDownloadRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _ignoreCallback = false; + + //find file's id + Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::idResolveFailedCallback); + _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); +} + +void GoogleDriveDownloadRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Storage::BoolCallback innerCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::downloadCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::downloadErrorCallback); + _workingRequest = _storage->downloadById(response.value.id(), _requestedLocalFile, innerCallback, innerErrorCallback); +} + +void GoogleDriveDownloadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveDownloadRequest::downloadCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishSuccess(response.value); +} + +void GoogleDriveDownloadRequest::downloadErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveDownloadRequest::handle() {} + +void GoogleDriveDownloadRequest::restart() { start(); } + +void GoogleDriveDownloadRequest::finishSuccess(bool success) { + Request::finishSuccess(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivedownloadrequest.h b/backends/cloud/googledrive/googledrivedownloadrequest.h new file mode 100644 index 0000000000..89bd313467 --- /dev/null +++ b/backends/cloud/googledrive/googledrivedownloadrequest.h @@ -0,0 +1,59 @@ +/* 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_GOOGLEDRIVE_GOOGLEDRIVEDOWNLOADREQUEST_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVEDOWNLOADREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace GoogleDrive { + +class GoogleDriveStorage; + +class GoogleDriveDownloadRequest: public Networking::Request { + Common::String _requestedFile, _requestedLocalFile; + GoogleDriveStorage *_storage; + Storage::BoolCallback _boolCallback; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void downloadCallback(Storage::BoolResponse response); + void downloadErrorCallback(Networking::ErrorResponse error); + void finishSuccess(bool success); +public: + GoogleDriveDownloadRequest(GoogleDriveStorage *storage, Common::String remotePath, Common::String localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb); + virtual ~GoogleDriveDownloadRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp index e3ab97ea6c..6d8da8383d 100644 --- a/backends/cloud/googledrive/googledriveresolveidrequest.cpp +++ b/backends/cloud/googledrive/googledriveresolveidrequest.cpp @@ -84,12 +84,17 @@ void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResp } } + Common::String path = _currentDirectory; + if (path != "") path += "/"; + path += currentLevelName; + bool lastLevel = (path.equalsIgnoreCase(_requestedPath)); + ///debug("so, searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); Common::Array &files = response.value; bool found = false; for (uint32 i = 0; i < files.size(); ++i) { - if (files[i].isDirectory() && files[i].name().equalsIgnoreCase(currentLevelName)) { + if ((files[i].isDirectory() || lastLevel) && files[i].name().equalsIgnoreCase(currentLevelName)) { if (_currentDirectory != "") _currentDirectory += "/"; _currentDirectory += files[i].name(); _currentDirectoryId = files[i].id(); @@ -101,10 +106,7 @@ void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResp } if (!found) { - Common::String path = _currentDirectory; - if (path != "") path += "/"; - path += currentLevelName; - if (path.equalsIgnoreCase(_requestedPath)) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); + if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); } } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index c6e423e00d..d9db4f7dd8 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -35,6 +35,8 @@ #include "googledriveresolveidrequest.h" #include "googledrivecreatedirectoryrequest.h" #include "googledrivelistdirectoryrequest.h" +#include "googledrivestreamfilerequest.h" +#include "googledrivedownloadrequest.h" namespace Cloud { namespace GoogleDrive { @@ -209,29 +211,6 @@ void GoogleDriveStorage::printJson(Networking::JsonResponse response) { delete json; } -void GoogleDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { - if (!response.value) { - warning("fileInfoCallback: NULL"); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); - return; - } - - Common::JSONObject result = response.value->asObject(); - if (result.contains("@content.downloadUrl")) { - const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); - if (outerCallback) - (*outerCallback)(Networking::NetworkReadStreamResponse( - response.request, - new Networking::NetworkReadStream(url, 0, "") - )); - } else { - warning("downloadUrl not found in passed JSON"); - debug("%s", response.value->stringify().c_str()); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); - } - delete response.value; -} - Networking::Request *GoogleDriveStorage::resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFile); @@ -255,27 +234,25 @@ Networking::Request *GoogleDriveStorage::upload(Common::String path, Common::See return nullptr; //TODO } -Networking::Request *GoogleDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { - /* - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + path; - Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::fileInfoCallback, outerCallback); - Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); - request->addHeader("Authorization: Bearer " + _token); - return addRequest(request); - */ - //TODO: resolve id - //TODO: then call streamFileById() - return nullptr; //TODO +Networking::Request *GoogleDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { + return addRequest(new GoogleDriveStreamFileRequest(this, path, outerCallback, errorCallback)); } Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { - return nullptr; //TODO + if (callback) { + Common::String url = "https://www.googleapis.com/drive/v3/files/" + id + "?alt=media"; + Common::String header = "Authorization: Bearer " + _token; + curl_slist *headersList = curl_slist_append(nullptr, header.c_str()); + Networking::NetworkReadStream *stream = new Networking::NetworkReadStream(url.c_str(), headersList, ""); + (*callback)(Networking::NetworkReadStreamResponse(nullptr, stream)); + } + delete callback; + delete errorCallback; + return nullptr; } Networking::Request *GoogleDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { - //TODO: resolve id - //TODO: then call downloadById() - return nullptr; //TODO + return addRequest(new GoogleDriveDownloadRequest(this, remotePath, localPath, callback, errorCallback)); } void GoogleDriveStorage::fileDownloaded(BoolResponse response) { diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index a456030369..2af1edea3c 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -61,8 +61,6 @@ class GoogleDriveStorage: public Cloud::Storage { void printBool(BoolResponse response); void printFile(UploadResponse response); void printInfo(StorageInfoResponse response); - - void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); public: virtual ~GoogleDriveStorage(); diff --git a/backends/cloud/googledrive/googledrivestreamfilerequest.cpp b/backends/cloud/googledrive/googledrivestreamfilerequest.cpp new file mode 100644 index 0000000000..424e52c6cb --- /dev/null +++ b/backends/cloud/googledrive/googledrivestreamfilerequest.cpp @@ -0,0 +1,91 @@ +/* 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/googledrive/googledrivestreamfilerequest.h" +#include "backends/cloud/googledrive/googledrivestorage.h" + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveStreamFileRequest::GoogleDriveStreamFileRequest(GoogleDriveStorage *storage, Common::String path, Networking::NetworkReadStreamCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _requestedFile(path), _storage(storage), _streamCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +GoogleDriveStreamFileRequest::~GoogleDriveStreamFileRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _streamCallback; +} + +void GoogleDriveStreamFileRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _ignoreCallback = false; + + //find file's id + Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::idResolveFailedCallback); + _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); +} + +void GoogleDriveStreamFileRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Networking::NetworkReadStreamCallback innerCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::streamFileCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::streamFileErrorCallback); + _workingRequest = _storage->streamFileById(response.value.id(), innerCallback, innerErrorCallback); +} + +void GoogleDriveStreamFileRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveStreamFileRequest::streamFileCallback(Networking::NetworkReadStreamResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishStream(response.value); +} + +void GoogleDriveStreamFileRequest::streamFileErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveStreamFileRequest::handle() {} + +void GoogleDriveStreamFileRequest::restart() { start(); } + +void GoogleDriveStreamFileRequest::finishStream(Networking::NetworkReadStream *stream) { + Request::finishSuccess(); + if (_streamCallback) (*_streamCallback)(Networking::NetworkReadStreamResponse(this, stream)); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivestreamfilerequest.h b/backends/cloud/googledrive/googledrivestreamfilerequest.h new file mode 100644 index 0000000000..aa5596154e --- /dev/null +++ b/backends/cloud/googledrive/googledrivestreamfilerequest.h @@ -0,0 +1,59 @@ +/* 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_GOOGLEDRIVE_GOOGLEDRIVESTREAMFILEREQUEST_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVESTREAMFILEREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace GoogleDrive { + +class GoogleDriveStorage; + +class GoogleDriveStreamFileRequest: public Networking::Request { + Common::String _requestedFile; + GoogleDriveStorage *_storage; + Networking::NetworkReadStreamCallback _streamCallback; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void streamFileCallback(Networking::NetworkReadStreamResponse response); + void streamFileErrorCallback(Networking::ErrorResponse error); + void finishStream(Networking::NetworkReadStream *stream); +public: + GoogleDriveStreamFileRequest(GoogleDriveStorage *storage, Common::String path, Networking::NetworkReadStreamCallback cb, Networking::ErrorCallback ecb); + virtual ~GoogleDriveStreamFileRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From b29497effe60eaec891ca1b5ce78f8dae69fd599 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 8 Jun 2016 16:46:18 +0600 Subject: CLOUD: Add GoogleDriveUploadRequest Includes NetworkReadStream PATCH method and Headers remembering feature. --- backends/cloud/googledrive/googledrivestorage.cpp | 4 +- .../cloud/googledrive/googledriveuploadrequest.cpp | 341 +++++++++++++++++++++ .../cloud/googledrive/googledriveuploadrequest.h | 70 +++++ 3 files changed, 413 insertions(+), 2 deletions(-) create mode 100644 backends/cloud/googledrive/googledriveuploadrequest.cpp create mode 100644 backends/cloud/googledrive/googledriveuploadrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index d9db4f7dd8..bb762a4d90 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -37,6 +37,7 @@ #include "googledrivelistdirectoryrequest.h" #include "googledrivestreamfilerequest.h" #include "googledrivedownloadrequest.h" +#include "googledriveuploadrequest.h" namespace Cloud { namespace GoogleDrive { @@ -230,8 +231,7 @@ Networking::Request *GoogleDriveStorage::listDirectoryById(Common::String id, Li } Networking::Request *GoogleDriveStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { - //return addRequest(new GoogleDriveUploadRequest(this, path, contents, callback, errorCallback)); - return nullptr; //TODO + return addRequest(new GoogleDriveUploadRequest(this, path, contents, callback, errorCallback)); } Networking::Request *GoogleDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp new file mode 100644 index 0000000000..7ab9f2e3c0 --- /dev/null +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -0,0 +1,341 @@ +/* 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/googledrive/googledriveuploadrequest.h" +#include "backends/cloud/googledrive/googledrivestorage.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 "googledrivetokenrefresher.h" + +namespace Cloud { +namespace GoogleDrive { + +GoogleDriveUploadRequest::GoogleDriveUploadRequest(GoogleDriveStorage *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(); +} + +GoogleDriveUploadRequest::~GoogleDriveUploadRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _contentsStream; + delete _uploadCallback; +} + +void GoogleDriveUploadRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + if (!_contentsStream->seek(0)) { + warning("GoogleDriveUploadRequest: cannot restart because stream couldn't seek(0)"); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); + } + _resolvedId = ""; //used to update file contents + _parentId = ""; //used to create file within parent directory + _serverReceivedBytes = 0; + _ignoreCallback = false; + + resolveId(); +} + +void GoogleDriveUploadRequest::resolveId() { + //check whether such file already exists + Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveUploadRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveUploadRequest::idResolveFailedCallback); + _workingRequest = _storage->resolveFileId(_savePath, innerCallback, innerErrorCallback); +} + +void GoogleDriveUploadRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + _resolvedId = response.value.id(); + startUpload(); +} + +void GoogleDriveUploadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //not resolved => error or no such file + if (error.response.contains("no such file found in its parent directory")) { + //parent's id after the '\n' + Common::String parentId = error.response; + for (uint32 i = 0; i < parentId.size(); ++i) + if (parentId[i] == '\n') { + parentId.erase(0, i + 1); + break; + } + + _parentId = parentId; + startUpload(); + return; + } + + finishError(error); +} + +void GoogleDriveUploadRequest::startUpload() { + Common::String name = _savePath; + for (uint32 i = name.size(); i > 0; --i) { + if (name[i - 1] == '/' || name[i - 1] == '\\') { + name.erase(0, i); + break; + } + } + + Common::String url = "https://www.googleapis.com/upload/drive/v3/files"; + if (_resolvedId != "") url += "/" + _resolvedId; + url += "?uploadType=resumable&fields=id,mimeType,modifiedTime,name,size"; + Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveUploadRequest::startUploadCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveUploadRequest::startUploadErrorCallback); + Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); + request->addHeader("Content-Type: application/json"); + if (_resolvedId != "") request->usePatch(); + + Common::JSONObject jsonRequestParameters; + if (_resolvedId != "") jsonRequestParameters.setVal("id", new Common::JSONValue(_resolvedId)); + else { + Common::JSONArray parentsArray; + parentsArray.push_back(new Common::JSONValue(_parentId)); + jsonRequestParameters.setVal("parents", new Common::JSONValue(parentsArray)); + } + jsonRequestParameters.setVal("name", new Common::JSONValue(name)); + + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + _workingRequest = ConnMan.addRequest(request); +} + +void GoogleDriveUploadRequest::startUploadCallback(Networking::JsonResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Networking::ErrorResponse error(this, false, true, "", -1); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + if (rq) { + const Networking::NetworkReadStream *stream = rq->getNetworkReadStream(); + if (stream) { + long code = stream->httpResponseCode(); + Common::String headers = stream->responseHeaders(); + if (code == 200) { + const char *cstr = headers.c_str(); + const char *position = strstr(cstr, "Location: "); + + if (position) { + Common::String result = ""; + char c; + for (const char *i = position + 10; c = *i, c != 0; ++i) { + if (c == '\n' || c == '\r') break; + result += c; + } + _uploadUrl = result; + uploadNextPart(); + return; + } + } + + error.httpResponseCode = code; + } + } + + Common::JSONValue *json = response.value; + delete json; + + finishError(error); +} + +void GoogleDriveUploadRequest::startUploadErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void GoogleDriveUploadRequest::uploadNextPart() { + const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; + Common::String url = _uploadUrl; + + Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveUploadRequest::partUploadedCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveUploadRequest::partUploadedErrorCallback); + Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); + request->usePut(); + + uint32 oldPos = _contentsStream->pos(); + if (oldPos != _serverReceivedBytes) { + if (!_contentsStream->seek(_serverReceivedBytes)) { + warning("GoogleDriveUploadRequest: cannot upload because stream couldn't seek(%u)", _serverReceivedBytes); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; + } + oldPos = _serverReceivedBytes; + } + + 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); +} + +namespace { +uint64 atoull(Common::String s) { + uint64 result = 0; + for (uint32 i = 0; i < s.size(); ++i) { + if (s[i] < '0' || s[i] > '9') break; + result = result * 10L + (s[i] - '0'); + } + return result; +} +} + +bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream *stream) { + //308 Resume Incomplete, with Range: X-Y header + if (!stream) return false; + if (stream->httpResponseCode() != 308) return false; //seriously + + Common::String headers = stream->responseHeaders(); + const char *cstr = headers.c_str(); + for (int rangeTry = 0; rangeTry < 2; ++rangeTry) { + const char *needle = (rangeTry==0 ? "Range: 0-" : "Range: bytes=0-"); + uint32 needleLength = (rangeTry == 0 ? 9 : 15); + + const char *position = strstr(cstr, needle); //if it lost the first part, I refuse to talk with it + + if (position) { + Common::String result = ""; + char c; + for (const char *i = position + needleLength; c = *i, c != 0; ++i) { + if (c == '\n' || c == '\r') break; + result += c; + } + _serverReceivedBytes = atoull(result) + 1; + uploadNextPart(); + return true; + } + } + + return false; +} + +void GoogleDriveUploadRequest::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) { + const Networking::NetworkReadStream *stream = rq->getNetworkReadStream(); + if (stream) { + long code = stream->httpResponseCode(); + error.httpResponseCode = code; + if (code == 308 && handleHttp308(stream)) { + delete (Common::JSONValue *)response.value; + return; + } + } + } + + Common::JSONValue *json = response.value; + if (json) { + debug("%s", json->stringify(true).c_str()); + if (json->isObject()) { + Common::JSONObject object = json->asObject(); + + if (object.contains("error")) { + warning("GoogleDrive 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 id = object.getVal("id")->asString(); + Common::String name = object.getVal("name")->asString(); + bool isDirectory = (object.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); + uint32 size = 0, timestamp = 0; + if (object.contains("size") && object.getVal("size")->isString()) + size = atoull(object.getVal("size")->asString()); + if (object.contains("modifiedTime") && object.getVal("modifiedTime")->isString()) + timestamp = ISO8601::convertToTimestamp(object.getVal("modifiedTime")->asString()); + + //as we list directory by id, we can't determine full path for the file, so we leave it empty + finishSuccess(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); + return; + } + } + + 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 GoogleDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)error.request; + if (rq) { + const Networking::NetworkReadStream *stream = rq->getNetworkReadStream(); + if (stream) { + long code = stream->httpResponseCode(); + if (code == 308 && handleHttp308(stream)) { + return; + } + } + } + + finishError(error); +} + +void GoogleDriveUploadRequest::handle() {} + +void GoogleDriveUploadRequest::restart() { start(); } + +void GoogleDriveUploadRequest::finishSuccess(StorageFile file) { + Request::finishSuccess(); + if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); +} + +} // End of namespace GoogleDrive +} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledriveuploadrequest.h b/backends/cloud/googledrive/googledriveuploadrequest.h new file mode 100644 index 0000000000..e417403542 --- /dev/null +++ b/backends/cloud/googledrive/googledriveuploadrequest.h @@ -0,0 +1,70 @@ +/* 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_GOOGLEDRIVE_GOOGLEDRIVEUPLOADREQUEST_H +#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVEUPLOADREQUEST_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 GoogleDrive { +class GoogleDriveStorage; + +class GoogleDriveUploadRequest: public Networking::Request { + GoogleDriveStorage *_storage; + Common::String _savePath; + Common::SeekableReadStream *_contentsStream; + Storage::UploadCallback _uploadCallback; + Request *_workingRequest; + bool _ignoreCallback; + Common::String _resolvedId, _parentId; + Common::String _uploadUrl; + uint64 _serverReceivedBytes; + + void start(); + void resolveId(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void startUpload(); + void startUploadCallback(Networking::JsonResponse response); + void startUploadErrorCallback(Networking::ErrorResponse error); + void uploadNextPart(); + void partUploadedCallback(Networking::JsonResponse response); + void partUploadedErrorCallback(Networking::ErrorResponse error); + bool handleHttp308(const Networking::NetworkReadStream *stream); + void finishSuccess(StorageFile status); + +public: + GoogleDriveUploadRequest(GoogleDriveStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb); + virtual ~GoogleDriveUploadRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace GoogleDrive +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From 1479d126520a9f3472797c1bb98b534f0b2a6b97 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 8 Jun 2016 16:54:29 +0600 Subject: CLOUD: Minor GoogleDriveUploadRequest fix Just checked that out on cloud sync: Google Drive is officially supported! --- backends/cloud/googledrive/googledriveuploadrequest.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index 7ab9f2e3c0..f5636ef8ba 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -267,7 +267,6 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res Common::JSONValue *json = response.value; if (json) { - debug("%s", json->stringify(true).c_str()); if (json->isObject()) { Common::JSONObject object = json->asObject(); -- cgit v1.2.3 From 870e96eb9ca6e69bea5f47a215d171fd58ab1265 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 8 Jun 2016 18:51:00 +0600 Subject: CLOUD: Update CloudManager and Storage * Storage::name(); * CloudManager::getStorageName(); * CloudManager::getStorageIndex(); * CloudManager::listStorages(); * CloudManager::switchStorage(). --- backends/cloud/cloudmanager.cpp | 38 ++++++++++++++++++++++- backends/cloud/cloudmanager.h | 31 +++++++++++++++++- backends/cloud/dropbox/dropboxstorage.cpp | 4 +++ backends/cloud/dropbox/dropboxstorage.h | 6 ++++ backends/cloud/googledrive/googledrivestorage.cpp | 4 +++ backends/cloud/googledrive/googledrivestorage.h | 6 ++++ backends/cloud/onedrive/onedrivestorage.cpp | 4 +++ backends/cloud/onedrive/onedrivestorage.h | 6 ++++ backends/cloud/storage.h | 6 ++++ 9 files changed, 103 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 7613b2cbbf..a9baac5d02 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -26,6 +26,7 @@ #include "backends/cloud/googledrive/googledrivestorage.h" #include "common/config-manager.h" #include "common/debug.h" +#include "common/translation.h" namespace Common { @@ -106,12 +107,47 @@ void CloudManager::addStorage(Storage *storage, bool makeCurrent, bool saveConfi if (saveConfig) save(); } -Storage *CloudManager::getCurrentStorage() { +Storage *CloudManager::getCurrentStorage() const { if (_currentStorageIndex < _storages.size()) return _storages[_currentStorageIndex]; return nullptr; } +Common::String CloudManager::getStorageName() const { + Storage *storage = getCurrentStorage(); + if (storage) return storage->name(); + return _("No active storage"); +} + +uint32 CloudManager::getStorageIndex() const { + return _currentStorageIndex; +} + +Common::StringArray CloudManager::listStorages() const { + Common::StringArray result; + for (uint32 i = 0; i < _storages.size(); ++i) { + result.push_back(_storages[i]->name()); + } + return result; +} + +bool CloudManager::switchStorage(uint32 index) { + if (index < 0 || index > _storages.size()) { + warning("CloudManager::switchStorage: invalid index passed"); + return false; + } + + Storage *storage = getCurrentStorage(); + if (storage && storage->isWorking()) { + warning("CloudManager::switchStorage: another storage is working now"); + return false; + } + + _currentStorageIndex = index; + save(); + return true; +} + void CloudManager::printBool(Storage::BoolResponse response) const { debug("bool = %s", (response.value ? "true" : "false")); } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index dbff0184eb..7e8cfd68a3 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -26,6 +26,7 @@ #include "backends/cloud/storage.h" #include "common/array.h" #include "common/singleton.h" +#include namespace GUI { @@ -72,7 +73,35 @@ public: * * @return active Cloud::Storage or null, if there is no active Storage. */ - Cloud::Storage *getCurrentStorage(); + Cloud::Storage *getCurrentStorage() const; + + /** + * Return active Storage's name. + * + * @return active Storage's or _("No active storage"), if there is no active Storage. + */ + Common::String getStorageName() const; + + /** + * Return active Storage's index. + * + * @return active Storage's index. + */ + uint32 getStorageIndex() const; + + /** + * Return Storages names as list. + * + * @return a list of Storages names. + */ + Common::StringArray listStorages() const; + + /** + * Changes the storage to the one with given index. + * + * @param new Storage's index. + */ + bool switchStorage(uint32 index); /** * Starts saves syncing process in currently active storage if there is any. diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 038a1683bf..d11d97da39 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -91,6 +91,10 @@ void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); } +Common::String DropboxStorage::name() const { + return "Dropbox"; +} + void DropboxStorage::printFiles(FileArrayResponse response) { debug("files:"); Common::Array &files = response.value; diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 9ac0ffb166..60a8075201 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -65,6 +65,12 @@ public: */ virtual void saveConfig(Common::String keyPrefix); + /** + * Return unique storage name. + * @returns some unique storage name (for example, "Dropbox (user@example.com)") + */ + virtual Common::String name() const; + /** Public Cloud API comes down there. */ /** Returns ListDirectoryStatus struct with list of files. */ diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index bb762a4d90..30ca1be7e6 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -134,6 +134,10 @@ void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } +Common::String GoogleDriveStorage::name() const { + return "Google Drive"; +} + namespace { uint64 atoull(Common::String s) { uint64 result = 0; diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 2af1edea3c..489260db09 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -77,6 +77,12 @@ public: */ virtual void saveConfig(Common::String keyPrefix); + /** + * Return unique storage name. + * @returns some unique storage name (for example, "Dropbox (user@example.com)") + */ + virtual Common::String name() const; + /** Public Cloud API comes down there. */ /** Returns StorageFile with the resolved file's id. */ diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index c494f38a6c..c391065396 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -128,6 +128,10 @@ void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } +Common::String OneDriveStorage::name() const { + return "OneDrive"; +} + void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 8afdac8b0f..3932d44aae 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -75,6 +75,12 @@ public: */ virtual void saveConfig(Common::String keyPrefix); + /** + * Return unique storage name. + * @returns some unique storage name (for example, "Dropbox (user@example.com)") + */ + virtual Common::String name() const; + /** Public Cloud API comes down there. */ /** Returns ListDirectoryStatus struct with list of files. */ diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 4a5e1236b7..11d8f6beb9 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -102,6 +102,12 @@ public: */ virtual void saveConfig(Common::String keyPrefix) = 0; + /** + * Return unique storage name. + * @returns some unique storage name (for example, "Dropbox (user@example.com)") + */ + virtual Common::String name() const = 0; + /** * Public Cloud API comes down there. * -- cgit v1.2.3 From 4ff1ed5fe9ba86ccf5d7ad72dab8286c70ab7af3 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 9 Jun 2016 12:41:51 +0600 Subject: GUI: Add Cloud tab information labels And corresponding stub implementations in CloudManager. --- backends/cloud/cloudmanager.cpp | 18 +++++++++++++++++- backends/cloud/cloudmanager.h | 26 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a9baac5d02..cb7e6f7cb3 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -132,7 +132,7 @@ Common::StringArray CloudManager::listStorages() const { } bool CloudManager::switchStorage(uint32 index) { - if (index < 0 || index > _storages.size()) { + if (index >= _storages.size()) { warning("CloudManager::switchStorage: invalid index passed"); return false; } @@ -148,6 +148,22 @@ bool CloudManager::switchStorage(uint32 index) { return true; } +Common::String CloudManager::getStorageUsername(uint32 index) { + if (index >= _storages.size()) return ""; + return _storages[index]->name(); //TODO +} + +uint64 CloudManager::getStorageUsedSpace(uint32 index) { + if (index >= _storages.size()) return 0; + return 0; //return _storages[index]->usedSpace(); //TODO +} + +Common::String CloudManager::getStorageLastSync(uint32 index) { + if (index >= _storages.size()) return ""; + if (_storages[index]->isSyncing()) return ""; + return _storages[index]->name(); //->lastSyncDate(); //TODO +} + void CloudManager::printBool(Storage::BoolResponse response) const { debug("bool = %s", (response.value ? "true" : "false")); } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 7e8cfd68a3..9956a92824 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -103,6 +103,32 @@ public: */ bool switchStorage(uint32 index); + /** + * Return username used by Storage. + * + * @param Storage's index. + * @returns username or "" if index is invalid (no such Storage). + */ + Common::String getStorageUsername(uint32 index); + + /** + * Return space used by Storage. + * + * @param Storage's index. + * @returns used space in bytes or 0 if index is invalid (no such Storage). + */ + uint64 getStorageUsedSpace(uint32 index); + + /** + * Return Storage's last sync date. + * + * @param Storage's index. + * @returns last sync date or "" if index is invalid (no such Storage). + It also returns "" if there never was any sync + or if storage is syncing right now. + */ + Common::String getStorageLastSync(uint32 index); + /** * Starts saves syncing process in currently active storage if there is any. */ -- cgit v1.2.3 From af9930482e17f4b55e46707fc017090e4c24a38e Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 9 Jun 2016 13:49:52 +0600 Subject: CLOUD: Update CloudManager It now supports only one storage of each type. Only one Storage could be loaded to the memory as well. Options' Cloud tab now changes the Storage only when user pressed OK button, giving the ability to look through the Storages without actually changing them. --- backends/cloud/cloudmanager.cpp | 155 ++++++++++++---------- backends/cloud/cloudmanager.h | 42 ++++-- backends/cloud/dropbox/dropboxstorage.cpp | 11 +- backends/cloud/googledrive/googledrivestorage.cpp | 7 +- backends/cloud/onedrive/onedrivestorage.cpp | 6 +- 5 files changed, 124 insertions(+), 97 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index cb7e6f7cb3..5c69e30520 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -36,87 +36,101 @@ DECLARE_SINGLETON(Cloud::CloudManager); namespace Cloud { -CloudManager::CloudManager() : _currentStorageIndex(0) {} +CloudManager::CloudManager() : _currentStorageIndex(0), _activeStorage(nullptr) {} CloudManager::~CloudManager() { //TODO: do we have to save storages on manager destruction? - for (uint32 i = 0; i < _storages.size(); ++i) - delete _storages[i]; - _storages.clear(); + delete _activeStorage; } -void CloudManager::init() { - bool offerDropbox = false; - bool offerOneDrive = false; - bool offerGoogleDrive = true; - - if (ConfMan.hasKey("storages_number", "cloud")) { - int storages = ConfMan.getInt("storages_number", "cloud"); - for (int i = 1; i <= storages; ++i) { - Storage *loaded = 0; - Common::String keyPrefix = Common::String::format("storage%d_", i); - if (ConfMan.hasKey(keyPrefix + "type", "cloud")) { - Common::String storageType = ConfMan.get(keyPrefix + "type", "cloud"); - if (storageType == "Dropbox") loaded = Dropbox::DropboxStorage::loadFromConfig(keyPrefix); - else if (storageType == "OneDrive") loaded = OneDrive::OneDriveStorage::loadFromConfig(keyPrefix); - else if (storageType == "Google Drive") { - loaded = GoogleDrive::GoogleDriveStorage::loadFromConfig(keyPrefix); - offerGoogleDrive = false; - } else warning("Unknown cloud storage type '%s' passed", storageType.c_str()); - } else { - warning("Cloud storage #%d (out of %d) is missing.", i, storages); - } - if (loaded) _storages.push_back(loaded); - } - - uint32 index = 0; - if (ConfMan.hasKey("current_storage", "cloud")) { - index = ConfMan.getInt("current_storage", "cloud") - 1; //count from 1, all for UX - } - if (index >= _storages.size()) index = 0; - _currentStorageIndex = index; - - if (_storages.size() == 0) offerDropbox = true; - } else { - offerDropbox = true; +namespace { +uint64 atoull(Common::String s) { + uint64 result = 0; + for (uint32 i = 0; i < s.size(); ++i) { + if (s[i] < '0' || s[i] > '9') break; + result = result * 10L + (s[i] - '0'); } - if (offerDropbox) { - //this is temporary console offer to auth with Dropbox - Dropbox::DropboxStorage::authThroughConsole(); - } else if (offerOneDrive) { - //OneDrive time - OneDrive::OneDriveStorage::authThroughConsole(); - } else if (offerGoogleDrive) { - GoogleDrive::GoogleDriveStorage::authThroughConsole(); - _currentStorageIndex = 100; + return result; +} +} + +Common::String CloudManager::getStorageConfigName(uint32 index) const { + switch (index) { + case kStorageNoneId: return ""; + case kStorageDropboxId: return "Dropbox"; + case kStorageOneDriveId: return "OneDrive"; + case kStorageGoogleDriveId: return "GoogleDrive"; + } + return "Unknown"; +} + +void CloudManager::loadStorage() { + switch (_currentStorageIndex) { + case kStorageDropboxId: + _activeStorage = Dropbox::DropboxStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); + break; + + case kStorageOneDriveId: + _activeStorage = OneDrive::OneDriveStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); + break; + + case kStorageGoogleDriveId: + _activeStorage = GoogleDrive::GoogleDriveStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); + break; + + default: + _activeStorage = nullptr; + } + + if (!_activeStorage) { + _currentStorageIndex = kStorageNoneId; } } +void CloudManager::init() { + //init configs structs + for (uint32 i = 0; i < kStorageTotal; ++i) { + Common::String name = getStorageConfigName(i); + StorageConfig config; + config.name = _(name); + config.username = ""; + config.lastSyncDate = ""; + config.usedBytes = 0; + if (ConfMan.hasKey("storage_" + name + "_username", "cloud")) + config.username = ConfMan.get("storage_" + name + "_username", "cloud"); + if (ConfMan.hasKey("storage_" + name + "_lastSync", "cloud")) + config.lastSyncDate = ConfMan.get("storage_" + name + "_lastSync", "cloud"); + if (ConfMan.hasKey("storage_" + name + "_usedBytes", "cloud")) + config.usedBytes = atoull(ConfMan.get("storage_" + name + "_usedBytes", "cloud")); + _storages.push_back(config); + } + + //load an active storage if there is any + _currentStorageIndex = kStorageNoneId; + if (ConfMan.hasKey("current_storage", "cloud")) + _currentStorageIndex = ConfMan.getInt("current_storage", "cloud"); + + loadStorage(); +} + void CloudManager::save() { - ConfMan.set("storages_number", Common::String::format("%d", _storages.size()), "cloud"); - ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex + 1), "cloud"); - for (uint32 i = 0; i < _storages.size(); ++i) - _storages[i]->saveConfig(Common::String::format("storage%d_", i + 1)); + ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex), "cloud"); + if (_activeStorage) + _activeStorage->saveConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); ConfMan.flushToDisk(); } -void CloudManager::addStorage(Storage *storage, bool makeCurrent, bool saveConfig) { - if (!storage) error("Cloud::CloudManager: NULL storage passed"); - _storages.push_back(storage); - if (makeCurrent) _currentStorageIndex = _storages.size() - 1; - if (saveConfig) save(); +void CloudManager::replaceStorage(Storage *storage, uint32 index) { + if (!storage) error("CloudManager::replaceStorage: NULL storage passed"); + if (index >= kStorageTotal) error("CloudManager::replaceStorage: invalid index passed"); + delete _activeStorage; + _activeStorage = storage; + _currentStorageIndex = index; + save(); } Storage *CloudManager::getCurrentStorage() const { - if (_currentStorageIndex < _storages.size()) - return _storages[_currentStorageIndex]; - return nullptr; -} - -Common::String CloudManager::getStorageName() const { - Storage *storage = getCurrentStorage(); - if (storage) return storage->name(); - return _("No active storage"); + return _activeStorage; } uint32 CloudManager::getStorageIndex() const { @@ -126,7 +140,7 @@ uint32 CloudManager::getStorageIndex() const { Common::StringArray CloudManager::listStorages() const { Common::StringArray result; for (uint32 i = 0; i < _storages.size(); ++i) { - result.push_back(_storages[i]->name()); + result.push_back(_storages[i].name); } return result; } @@ -144,24 +158,25 @@ bool CloudManager::switchStorage(uint32 index) { } _currentStorageIndex = index; + loadStorage(); save(); return true; } Common::String CloudManager::getStorageUsername(uint32 index) { if (index >= _storages.size()) return ""; - return _storages[index]->name(); //TODO + return _storages[index].username; } uint64 CloudManager::getStorageUsedSpace(uint32 index) { if (index >= _storages.size()) return 0; - return 0; //return _storages[index]->usedSpace(); //TODO + return _storages[index].usedBytes; } Common::String CloudManager::getStorageLastSync(uint32 index) { if (index >= _storages.size()) return ""; - if (_storages[index]->isSyncing()) return ""; - return _storages[index]->name(); //->lastSyncDate(); //TODO + if (index == _currentStorageIndex && isSyncing()) return ""; + return _storages[index].lastSyncDate; } void CloudManager::printBool(Storage::BoolResponse response) const { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 9956a92824..5e26ece088 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -36,12 +36,33 @@ class CommandReceiver; namespace Cloud { +//that's actual indexes in CloudManager's array +enum StorageIDs { + kStorageNoneId = 0, + kStorageDropboxId = 1, + kStorageOneDriveId = 2, + kStorageGoogleDriveId = 3, + + kStorageTotal +}; + class CloudManager : public Common::Singleton { - Common::Array _storages; - uint _currentStorageIndex; + struct StorageConfig { + Common::String name, username; + uint64 usedBytes; + Common::String lastSyncDate; + }; + + Common::Array _storages; + uint _currentStorageIndex; + Storage *_activeStorage; void printBool(Cloud::Storage::BoolResponse response) const; + void loadStorage(); + + Common::String getStorageConfigName(uint32 index) const; + public: CloudManager(); virtual ~CloudManager(); @@ -59,13 +80,13 @@ public: void save(); /** - * Adds new Storage into list. + * Replace active Storage. + * @note this method automatically saves the changes with ConfMan. * - * @param storage Cloud::Storage to add. - * @param makeCurrent whether added storage should be the new current storage. - * @param saveConfig whether save() should be called to update configuration file. + * @param storage Cloud::Storage to replace active storage with. + * @param index one of Cloud::StorageIDs enum values to indicate what storage type is replaced. */ - void addStorage(Cloud::Storage *storage, bool makeCurrent = true, bool saveConfig = true); + void replaceStorage(Storage *storage, uint32 index); /** * Returns active Storage, which could be used to interact @@ -75,13 +96,6 @@ public: */ Cloud::Storage *getCurrentStorage() const; - /** - * Return active Storage's name. - * - * @return active Storage's or _("No active storage"), if there is no active Storage. - */ - Common::String getStorageName() const; - /** * Return active Storage's index. * diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index d11d97da39..af73138a4f 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -61,11 +61,11 @@ static void saveAccessTokenCallback(Networking::JsonResponse pair) { warning("Bad response, no token/uid passed"); } else { //we suppose that's the first storage - ConfMan.set("storages_number", "1", "cloud"); + //TODO: update it to use CloudMan.replaceStorage() ConfMan.set("current_storage", "1", "cloud"); - ConfMan.set("storage1_type", "Dropbox", "cloud"); - ConfMan.set("storage1_access_token", result.getVal("access_token")->asString(), "cloud"); - ConfMan.set("storage1_user_id", result.getVal("uid")->asString(), "cloud"); + ConfMan.set("storage_Dropbox_type", "Dropbox", "cloud"); + ConfMan.set("storage_Dropbox_access_token", result.getVal("access_token")->asString(), "cloud"); + ConfMan.set("storage_Dropbox_user_id", result.getVal("uid")->asString(), "cloud"); ConfMan.removeKey("dropbox_code", "cloud"); ConfMan.flushToDisk(); debug("Now please restart ScummVM to apply the changes."); @@ -85,8 +85,7 @@ DropboxStorage::~DropboxStorage() { curl_global_cleanup(); } -void DropboxStorage::saveConfig(Common::String keyPrefix) { - ConfMan.set(keyPrefix + "type", "Dropbox", "cloud"); +void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, "cloud"); ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 30ca1be7e6..18ddca5e94 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -121,15 +121,14 @@ void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { return; } - ConfMan.removeKey("googledrive_code", "cloud"); - CloudMan.addStorage(this); + ConfMan.removeKey("googledrive_code", "cloud"); + CloudMan.replaceStorage(this, kStorageGoogleDriveId); ConfMan.flushToDisk(); debug("Done! You can use Google Drive now! Look:"); CloudMan.testFeature(); } -void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { - ConfMan.set(keyPrefix + "type", "Google Drive", "cloud"); +void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, "cloud"); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index c391065396..d73bcdbe34 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -115,14 +115,14 @@ void OneDriveStorage::codeFlowComplete(BoolResponse response) { return; } - CloudMan.addStorage(this); ConfMan.removeKey("onedrive_code", "cloud"); + CloudMan.replaceStorage(this, kStorageOneDriveId); + ConfMan.flushToDisk(); debug("Done! You can use OneDrive now! Look:"); CloudMan.syncSaves(); } -void OneDriveStorage::saveConfig(Common::String keyPrefix) { - ConfMan.set(keyPrefix + "type", "OneDrive", "cloud"); +void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, "cloud"); ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); -- cgit v1.2.3 From 9b15ec9989fc67a0537b1e70732d3dba48797165 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 9 Jun 2016 14:23:14 +0600 Subject: CLOUD: Update CloudManager It now has methods to update Storage's information. --- backends/cloud/cloudmanager.cpp | 31 ++++++++++++++++++++++- backends/cloud/cloudmanager.h | 27 ++++++++++++++++++++ backends/cloud/dropbox/dropboxstorage.cpp | 5 ++++ backends/cloud/googledrive/googledrivestorage.cpp | 3 +++ backends/cloud/onedrive/onedrivestorage.cpp | 2 ++ 5 files changed, 67 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 5c69e30520..a1b1ed1525 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -114,6 +114,14 @@ void CloudManager::init() { } void CloudManager::save() { + for (uint32 i = 0; i < _storages.size(); ++i) { + if (i == kStorageNoneId) continue; + Common::String name = getStorageConfigName(i); + ConfMan.set("storage_" + name + "_username", _storages[i].username, "cloud"); + ConfMan.set("storage_" + name + "_lastSync", _storages[i].lastSyncDate, "cloud"); + ConfMan.set("storage_" + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes), "cloud"); + } + ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex), "cloud"); if (_activeStorage) _activeStorage->saveConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); @@ -179,13 +187,34 @@ Common::String CloudManager::getStorageLastSync(uint32 index) { return _storages[index].lastSyncDate; } +void CloudManager::setStorageUsername(uint32 index, Common::String name) { + if (index >= _storages.size()) return; + _storages[index].username = name; + save(); +} + +void CloudManager::setStorageUsedSpace(uint32 index, uint64 used) { + if (index >= _storages.size()) return; + _storages[index].usedBytes = used; + save(); +} + +void CloudManager::setStorageLastSync(uint32 index, Common::String date) { + if (index >= _storages.size()) return; + _storages[index].lastSyncDate = date; + save(); +} + void CloudManager::printBool(Storage::BoolResponse response) const { debug("bool = %s", (response.value ? "true" : "false")); } SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); - if (storage) return storage->syncSaves(callback, errorCallback); + if (storage) { + setStorageLastSync(_currentStorageIndex, "???"); //TODO get the date + return storage->syncSaves(callback, errorCallback); + } return nullptr; } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 5e26ece088..7ce7e925da 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -143,6 +143,33 @@ public: */ Common::String getStorageLastSync(uint32 index); + /** + * Set Storage's username. + * Automatically saves changes to the config. + * + * @param index Storage's index. + * @param name username to set + */ + void setStorageUsername(uint32 index, Common::String name); + + /** + * Set Storage's used space field. + * Automatically saves changes to the config. + * + * @param index Storage's index. + * @param used value to set + */ + void setStorageUsedSpace(uint32 index, uint64 used); + + /** + * Set Storage's last sync date. + * Automatically saves changes to the config. + * + * @param index Storage's index. + * @param date date to set + */ + void setStorageLastSync(uint32 index, Common::String date); + /** * Starts saves syncing process in currently active storage if there is any. */ diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index af73138a4f..e59e19eef9 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -25,6 +25,7 @@ #include "backends/cloud/dropbox/dropboxcreatedirectoryrequest.h" #include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h" #include "backends/cloud/dropbox/dropboxuploadrequest.h" +#include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "common/config-manager.h" @@ -171,6 +172,10 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ uint64 quotaNormal = quota.getVal("normal")->asIntegerNumber(); uint64 quotaShared = quota.getVal("shared")->asIntegerNumber(); uint64 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); + + CloudMan.setStorageUsedSpace(kStorageDropboxId, quotaNormal + quotaShared); //TODO that's not ScummVM's actually + CloudMan.setStorageUsername(kStorageDropboxId, email); + (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 18ddca5e94..143b7ac52c 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -180,6 +180,9 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne quotaAllocated = atoull(limit); } + CloudMan.setStorageUsedSpace(kStorageGoogleDriveId, quotaUsed); //TODO that's not ScummVM's actually + CloudMan.setStorageUsername(kStorageGoogleDriveId, email); + (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index d73bcdbe34..82681756c4 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -159,6 +159,8 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo quotaUsed = info.getVal("size")->asIntegerNumber(); } + CloudMan.setStorageUsedSpace(kStorageOneDriveId, quotaUsed); //TODO that's not ScummVM's actually + CloudMan.setStorageUsername(kStorageOneDriveId, email); (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); delete outerCallback; } -- cgit v1.2.3 From e6242b0be8fc9f9abc4daf87f80675cca46df4d9 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 9 Jun 2016 18:49:17 +0600 Subject: GUI: Add Refresh button in Options Cloud tab Commit changes CloudManager and Storages so they would automatically refresh the fields when the could. --- backends/cloud/cloudmanager.cpp | 29 ++++++++++++++ backends/cloud/cloudmanager.h | 9 +++++ backends/cloud/dropbox/dropboxstorage.cpp | 27 ++++++------- backends/cloud/googledrive/googledrivestorage.cpp | 49 +++++++++++------------ backends/cloud/onedrive/onedrivestorage.cpp | 41 ++++++++++--------- backends/cloud/savessyncrequest.cpp | 5 +++ backends/cloud/storage.h | 10 ++++- 7 files changed, 110 insertions(+), 60 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a1b1ed1525..9456dd84a4 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -135,6 +135,7 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) { _activeStorage = storage; _currentStorageIndex = index; save(); + if (_activeStorage) _activeStorage->info(nullptr, nullptr); //automatically calls setStorageUsername() } Storage *CloudManager::getCurrentStorage() const { @@ -209,6 +210,34 @@ void CloudManager::printBool(Storage::BoolResponse response) const { debug("bool = %s", (response.value ? "true" : "false")); } +Networking::Request *CloudManager::listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + Storage *storage = getCurrentStorage(); + if (storage) storage->listDirectory(path, callback, errorCallback, recursive); + else { + delete callback; + delete errorCallback; + //TODO: should we call errorCallback? + } + return nullptr; +} + +Networking::Request *CloudManager::info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { + Storage *storage = getCurrentStorage(); + if (storage) storage->info(callback, errorCallback); + else { + delete callback; + delete errorCallback; + //TODO: should we call errorCallback? + } + return nullptr; +} + +Common::String CloudManager::savesDirectoryPath() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->savesDirectoryPath(); + return ""; +} + SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); if (storage) { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 7ce7e925da..fd130c5ee8 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -170,6 +170,15 @@ public: */ void setStorageLastSync(uint32 index, Common::String date); + /** Returns ListDirectoryResponse with list of files. */ + Networking::Request *listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + + /** Return the StorageInfo struct. */ + Networking::Request *info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns storage's saves directory path with the trailing slash. */ + Common::String savesDirectoryPath(); + /** * Starts saves syncing process in currently active storage if there is any. */ diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index e59e19eef9..faff10f1d9 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -162,20 +162,19 @@ void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networ return; } - if (outerCallback) { - //Dropbox documentation states there is no errors for this API method - Common::JSONObject info = json->asObject(); - Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asIntegerNumber()); - Common::String name = info.getVal("display_name")->asString(); - Common::String email = info.getVal("email")->asString(); - Common::JSONObject quota = info.getVal("quota_info")->asObject(); - uint64 quotaNormal = quota.getVal("normal")->asIntegerNumber(); - uint64 quotaShared = quota.getVal("shared")->asIntegerNumber(); - uint64 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); - - CloudMan.setStorageUsedSpace(kStorageDropboxId, quotaNormal + quotaShared); //TODO that's not ScummVM's actually - CloudMan.setStorageUsername(kStorageDropboxId, email); - + //Dropbox documentation states there is no errors for this API method + Common::JSONObject info = json->asObject(); + Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asIntegerNumber()); + Common::String name = info.getVal("display_name")->asString(); + Common::String email = info.getVal("email")->asString(); + Common::JSONObject quota = info.getVal("quota_info")->asObject(); + uint64 quotaNormal = quota.getVal("normal")->asIntegerNumber(); + uint64 quotaShared = quota.getVal("shared")->asIntegerNumber(); + uint64 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); + + CloudMan.setStorageUsername(kStorageDropboxId, email); + + if (outerCallback) { (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 143b7ac52c..3196cbe041 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -156,33 +156,32 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne return; } - if (outerCallback) { - Common::JSONObject info = json->asObject(); - - Common::String uid, name, email; - uint64 quotaUsed = 0, quotaAllocated = 0; - - if (info.contains("user") && info.getVal("user")->isObject()) { - //"me":true, "kind":"drive#user","photoLink": "", - //"displayName":"Alexander Tkachev","emailAddress":"alexander@tkachov.ru","permissionId":"" - Common::JSONObject user = info.getVal("user")->asObject(); - uid = user.getVal("permissionId")->asString(); //not sure it's user's id, but who cares anyway? - name = user.getVal("displayName")->asString(); - email = user.getVal("emailAddress")->asString(); - } - - if (info.contains("storageQuota") && info.getVal("storageQuota")->isObject()) { - //"usageInDrive":"6332462","limit":"18253611008","usage":"6332462","usageInDriveTrash":"0" - Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); - Common::String usage = storageQuota.getVal("usage")->asString(); - Common::String limit = storageQuota.getVal("limit")->asString(); - quotaUsed = atoull(usage); - quotaAllocated = atoull(limit); - } + Common::JSONObject info = json->asObject(); + + Common::String uid, name, email; + uint64 quotaUsed = 0, quotaAllocated = 0; + + if (info.contains("user") && info.getVal("user")->isObject()) { + //"me":true, "kind":"drive#user","photoLink": "", + //"displayName":"Alexander Tkachev","emailAddress":"alexander@tkachov.ru","permissionId":"" + Common::JSONObject user = info.getVal("user")->asObject(); + uid = user.getVal("permissionId")->asString(); //not sure it's user's id, but who cares anyway? + name = user.getVal("displayName")->asString(); + email = user.getVal("emailAddress")->asString(); + } - CloudMan.setStorageUsedSpace(kStorageGoogleDriveId, quotaUsed); //TODO that's not ScummVM's actually - CloudMan.setStorageUsername(kStorageGoogleDriveId, email); + if (info.contains("storageQuota") && info.getVal("storageQuota")->isObject()) { + //"usageInDrive":"6332462","limit":"18253611008","usage":"6332462","usageInDriveTrash":"0" + Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); + Common::String usage = storageQuota.getVal("usage")->asString(); + Common::String limit = storageQuota.getVal("limit")->asString(); + quotaUsed = atoull(usage); + quotaAllocated = atoull(limit); + } + + CloudMan.setStorageUsername(kStorageGoogleDriveId, email); + if (outerCallback) { (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 82681756c4..178d43c8be 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -139,28 +139,31 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo delete outerCallback; return; } - - if (outerCallback) { - Common::JSONObject info = json->asObject(); - - Common::String uid, name, email; - uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one - - if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { - Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); - if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { - Common::JSONObject user = createdBy.getVal("user")->asObject(); - uid = user.getVal("id")->asString(); - name = user.getVal("displayName")->asString(); - } + + Common::JSONObject info = json->asObject(); + + Common::String uid, name, email; + uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one + + if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { + Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); + if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { + Common::JSONObject user = createdBy.getVal("user")->asObject(); + uid = user.getVal("id")->asString(); + name = user.getVal("displayName")->asString(); } + } - if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { - quotaUsed = info.getVal("size")->asIntegerNumber(); - } + if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { + quotaUsed = info.getVal("size")->asIntegerNumber(); + } + + Common::String username = email; + if (username == "") username = name; + if (username == "") username = uid; + CloudMan.setStorageUsername(kStorageOneDriveId, username); - CloudMan.setStorageUsedSpace(kStorageOneDriveId, quotaUsed); //TODO that's not ScummVM's actually - CloudMan.setStorageUsername(kStorageOneDriveId, email); + if (outerCallback) { (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); delete outerCallback; } diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index cdf1dbac07..e1739f9693 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -21,6 +21,7 @@ */ #include "backends/cloud/savessyncrequest.h" +#include "backends/cloud/cloudmanager.h" #include "common/config-manager.h" #include "common/debug.h" #include "common/file.h" @@ -82,9 +83,11 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re //determine which files to download and which files to upload Common::Array &remoteFiles = response.value; + uint64 totalSize = 0; for (uint32 i = 0; i < remoteFiles.size(); ++i) { StorageFile &file = remoteFiles[i]; if (file.isDirectory()) continue; + totalSize += file.size(); if (file.name() == TIMESTAMPS_FILENAME) continue; Common::String name = file.name(); @@ -107,6 +110,8 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re } } + CloudMan.setStorageUsedSpace(CloudMan.getStorageIndex(), totalSize); + //upload files which are unavailable in cloud for (Common::HashMap::iterator i = localFileNotAvailableInCloud.begin(); i != localFileNotAvailableInCloud.end(); ++i) { if (i->_key == TIMESTAMPS_FILENAME) continue; diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 11d8f6beb9..a76f2169bc 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -116,7 +116,7 @@ public: * a callback, which is called, when request is complete. */ - /** Returns ListDirectoryStatus struct with list of files. */ + /** Returns ListDirectoryResponse with list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false) = 0; /** Returns UploadStatus struct with info about uploaded file. */ @@ -143,7 +143,13 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; - /** Returns the StorageInfo struct. */ + /** + * Return the StorageInfo struct via . + * Call the if failed to get information. + * + * @note on success Storage should also call + * CloudMan.setStorageUsername(). + */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) = 0; /** Returns storage's saves directory path with the trailing slash. */ -- cgit v1.2.3 From c99b24c16d1111a701d915832f24ac457aef697d Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 10 Jun 2016 14:06:06 +0600 Subject: COMMON: Add String::asUint64() Instead of all these atoull() I've added everywhere. --- backends/cloud/cloudmanager.cpp | 13 +------------ .../googledrive/googledrivelistdirectorybyidrequest.cpp | 13 +------------ backends/cloud/googledrive/googledrivestorage.cpp | 15 ++------------- backends/cloud/googledrive/googledriveuploadrequest.cpp | 15 ++------------- 4 files changed, 6 insertions(+), 50 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 9456dd84a4..fed35a9f38 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -43,17 +43,6 @@ CloudManager::~CloudManager() { delete _activeStorage; } -namespace { -uint64 atoull(Common::String s) { - uint64 result = 0; - for (uint32 i = 0; i < s.size(); ++i) { - if (s[i] < '0' || s[i] > '9') break; - result = result * 10L + (s[i] - '0'); - } - return result; -} -} - Common::String CloudManager::getStorageConfigName(uint32 index) const { switch (index) { case kStorageNoneId: return ""; @@ -101,7 +90,7 @@ void CloudManager::init() { if (ConfMan.hasKey("storage_" + name + "_lastSync", "cloud")) config.lastSyncDate = ConfMan.get("storage_" + name + "_lastSync", "cloud"); if (ConfMan.hasKey("storage_" + name + "_usedBytes", "cloud")) - config.usedBytes = atoull(ConfMan.get("storage_" + name + "_usedBytes", "cloud")); + config.usedBytes = ConfMan.get("storage_" + name + "_usedBytes", "cloud").asUint64(); _storages.push_back(config); } diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index f9af363254..86494e8c13 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -67,17 +67,6 @@ void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) _workingRequest = ConnMan.addRequest(request); } -namespace { -uint64 atoull(Common::String s) { - uint64 result = 0; - for (uint32 i = 0; i < s.size(); ++i) { - if (s[i] < '0' || s[i] > '9') break; - result = result * 10L + (s[i] - '0'); - } - return result; -} -} - void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; @@ -113,7 +102,7 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo bool isDirectory = (item.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); uint32 size = 0, timestamp = 0; if (item.contains("size") && item.getVal("size")->isString()) - size = atoull(item.getVal("size")->asString()); + size = item.getVal("size")->asString().asUint64(); if (item.contains("modifiedTime") && item.getVal("modifiedTime")->isString()) timestamp = ISO8601::convertToTimestamp(item.getVal("modifiedTime")->asString()); diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 3196cbe041..91d8c819e7 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -137,17 +137,6 @@ Common::String GoogleDriveStorage::name() const { return "Google Drive"; } -namespace { -uint64 atoull(Common::String s) { - uint64 result = 0; - for (uint32 i = 0; i < s.size(); ++i) { - if (s[i] < '0' || s[i] > '9') break; - result = result * 10L + (s[i] - '0'); - } - return result; -} -} - void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { @@ -175,8 +164,8 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); Common::String usage = storageQuota.getVal("usage")->asString(); Common::String limit = storageQuota.getVal("limit")->asString(); - quotaUsed = atoull(usage); - quotaAllocated = atoull(limit); + quotaUsed = usage.asUint64(); + quotaAllocated = limit.asUint64(); } CloudMan.setStorageUsername(kStorageGoogleDriveId, email); diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index f5636ef8ba..8dd8ffcc9a 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -207,17 +207,6 @@ void GoogleDriveUploadRequest::uploadNextPart() { _workingRequest = ConnMan.addRequest(request); } -namespace { -uint64 atoull(Common::String s) { - uint64 result = 0; - for (uint32 i = 0; i < s.size(); ++i) { - if (s[i] < '0' || s[i] > '9') break; - result = result * 10L + (s[i] - '0'); - } - return result; -} -} - bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream *stream) { //308 Resume Incomplete, with Range: X-Y header if (!stream) return false; @@ -238,7 +227,7 @@ bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream if (c == '\n' || c == '\r') break; result += c; } - _serverReceivedBytes = atoull(result) + 1; + _serverReceivedBytes = result.asUint64() + 1; uploadNextPart(); return true; } @@ -285,7 +274,7 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res bool isDirectory = (object.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); uint32 size = 0, timestamp = 0; if (object.contains("size") && object.getVal("size")->isString()) - size = atoull(object.getVal("size")->asString()); + size = object.getVal("size")->asString().asUint64(); if (object.contains("modifiedTime") && object.getVal("modifiedTime")->isString()) timestamp = ISO8601::convertToTimestamp(object.getVal("modifiedTime")->asString()); -- cgit v1.2.3 From 6a93e8dd09ae2eeab616d14189a58633fd928c07 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 10 Jun 2016 14:28:04 +0600 Subject: CLOUD: Add ConnMan::urlEncode() Tried to use it everywhere I should've use it. --- backends/cloud/googledrive/googledrivestorage.cpp | 2 +- backends/cloud/googledrive/googledriveuploadrequest.cpp | 2 +- backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp | 2 +- backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp | 5 +++-- backends/cloud/onedrive/onedrivestorage.cpp | 2 +- backends/cloud/onedrive/onedriveuploadrequest.cpp | 4 ++-- 6 files changed, 9 insertions(+), 8 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 91d8c819e7..5eab071599 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -234,7 +234,7 @@ Networking::Request *GoogleDriveStorage::streamFile(Common::String path, Network Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { if (callback) { - Common::String url = "https://www.googleapis.com/drive/v3/files/" + id + "?alt=media"; + Common::String url = "https://www.googleapis.com/drive/v3/files/" + ConnMan.urlEncode(id) + "?alt=media"; Common::String header = "Authorization: Bearer " + _token; curl_slist *headersList = curl_slist_append(nullptr, header.c_str()); Networking::NetworkReadStream *stream = new Networking::NetworkReadStream(url.c_str(), headersList, ""); diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index 8dd8ffcc9a..ce1fae2579 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -108,7 +108,7 @@ void GoogleDriveUploadRequest::startUpload() { } Common::String url = "https://www.googleapis.com/upload/drive/v3/files"; - if (_resolvedId != "") url += "/" + _resolvedId; + if (_resolvedId != "") url += "/" + ConnMan.urlEncode(_resolvedId); url += "?uploadType=resumable&fields=id,mimeType,modifiedTime,name,size"; Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveUploadRequest::startUploadCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveUploadRequest::startUploadErrorCallback); diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index c48ae1dfbe..fe1128bd5b 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -63,7 +63,7 @@ void OneDriveCreateDirectoryRequest::start() { } Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot"; - if (parent != "") url += ":/" + parent + ":"; + if (parent != "") url += ":/" + ConnMan.urlEncode(parent) + ":"; url += "/children"; Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::responseCallback); Networking::ErrorCallback errorCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::errorCallback); diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index e362600389..040ef153db 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -70,8 +70,9 @@ void OneDriveListDirectoryRequest::listNextDirectory() { if (_currentDirectory != "" && _currentDirectory.lastChar() != '/' && _currentDirectory.lastChar() != '\\') _currentDirectory += '/'; - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + _currentDirectory; - url.deleteLastChar(); + Common::String dir = _currentDirectory; + dir.deleteLastChar(); + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(dir); url += ":/children"; makeRequest(url); } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 178d43c8be..d1971f904a 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -214,7 +214,7 @@ Networking::Request *OneDriveStorage::upload(Common::String path, Common::Seekab } Networking::Request *OneDriveStorage::streamFileById(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:/" + ConnMan.urlEncode(path); Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _token); diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 752907f333..bc54a811a9 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -63,7 +63,7 @@ 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 + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+ConnMan.urlEncode(_savePath)+":/upload.createSession"; //folder must exist Networking::JsonCallback callback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedErrorCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); @@ -75,7 +75,7 @@ void OneDriveUploadRequest::uploadNextPart() { Common::String url; if (_uploadUrl == "") { - url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+_savePath+":/content"; + url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+ConnMan.urlEncode(_savePath)+":/content"; } else { url = _uploadUrl; } -- 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/dropboxcreatedirectoryrequest.cpp | 4 ++++ backends/cloud/dropbox/dropboxcreatedirectoryrequest.h | 2 ++ backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 5 +++++ backends/cloud/dropbox/dropboxlistdirectoryrequest.h | 2 ++ backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp | 8 ++++++++ backends/cloud/googledrive/googledrivecreatedirectoryrequest.h | 2 ++ .../cloud/googledrive/googledrivelistdirectorybyidrequest.cpp | 4 ++++ backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h | 2 ++ backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp | 6 ++++++ backends/cloud/googledrive/googledrivelistdirectoryrequest.h | 2 ++ backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp | 4 ++++ backends/cloud/onedrive/onedrivecreatedirectoryrequest.h | 2 ++ backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp | 5 +++++ backends/cloud/onedrive/onedrivelistdirectoryrequest.h | 2 ++ backends/cloud/savessyncrequest.cpp | 5 +++++ backends/cloud/savessyncrequest.h | 1 + 16 files changed, 56 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index c077d8df11..61cc9ddfcd 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -68,6 +68,7 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re delete json; return; } + if (response.request) _date = response.request->date(); Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -93,6 +94,7 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re void DropboxCreateDirectoryRequest::errorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -100,6 +102,8 @@ void DropboxCreateDirectoryRequest::handle() {} void DropboxCreateDirectoryRequest::restart() { start(); } +Common::String DropboxCreateDirectoryRequest::date() const { return _date; } + void DropboxCreateDirectoryRequest::finishSuccess(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h index ea3175bb50..e8599c7df9 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h @@ -36,6 +36,7 @@ class DropboxCreateDirectoryRequest: public Networking::Request { Storage::BoolCallback _boolCallback; Request *_workingRequest; bool _ignoreCallback; + Common::String _date; void start(); void responseCallback(Networking::JsonResponse response); @@ -47,6 +48,7 @@ public: virtual void handle(); virtual void restart(); + virtual Common::String date() const; }; } // End of namespace Dropbox 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)); diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 3a83af06aa..0d96edd1e6 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -40,6 +40,7 @@ class DropboxListDirectoryRequest: public Networking::Request { Common::Array _files; Request *_workingRequest; bool _ignoreCallback; + Common::String _date; void start(); void responseCallback(Networking::JsonResponse response); @@ -51,6 +52,7 @@ public: virtual void handle(); virtual void restart(); + virtual Common::String date() const; }; } // End of namespace Dropbox diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp index 54eff3d6ad..2b7a805bb9 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp @@ -63,12 +63,14 @@ void GoogleDriveCreateDirectoryRequest::start() { void GoogleDriveCreateDirectoryRequest::createdBaseDirectoryCallback(Storage::BoolResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); resolveId(); } void GoogleDriveCreateDirectoryRequest::createdBaseDirectoryErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -85,6 +87,7 @@ void GoogleDriveCreateDirectoryRequest::resolveId() { void GoogleDriveCreateDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); //resolved => folder already exists finishSuccess(false); @@ -93,6 +96,7 @@ void GoogleDriveCreateDirectoryRequest::idResolvedCallback(Storage::UploadRespon void GoogleDriveCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); //not resolved => folder not exists if (error.response.contains("no such file found in its parent directory")) { @@ -116,12 +120,14 @@ void GoogleDriveCreateDirectoryRequest::idResolveFailedCallback(Networking::Erro void GoogleDriveCreateDirectoryRequest::createdDirectoryCallback(Storage::BoolResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); finishSuccess(response.value); } void GoogleDriveCreateDirectoryRequest::createdDirectoryErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -129,6 +135,8 @@ void GoogleDriveCreateDirectoryRequest::handle() {} void GoogleDriveCreateDirectoryRequest::restart() { start(); } +Common::String GoogleDriveCreateDirectoryRequest::date() const { return _date; } + void GoogleDriveCreateDirectoryRequest::finishSuccess(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h index ede84277de..f71afeb888 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h @@ -39,6 +39,7 @@ class GoogleDriveCreateDirectoryRequest: public Networking::Request { Storage::BoolCallback _boolCallback; Request *_workingRequest; bool _ignoreCallback; + Common::String _date; void start(); void createdBaseDirectoryCallback(Storage::BoolResponse response); @@ -55,6 +56,7 @@ public: virtual void handle(); virtual void restart(); + virtual Common::String date() const; }; } // End of namespace GoogleDrive diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 86494e8c13..2530bab557 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -70,6 +70,7 @@ void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -131,6 +132,7 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo void GoogleDriveListDirectoryByIdRequest::errorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -138,6 +140,8 @@ void GoogleDriveListDirectoryByIdRequest::handle() {} void GoogleDriveListDirectoryByIdRequest::restart() { start(); } +Common::String GoogleDriveListDirectoryByIdRequest::date() const { return _date; } + void GoogleDriveListDirectoryByIdRequest::finishSuccess(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h index 569984520a..ceb533e635 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h @@ -41,6 +41,7 @@ class GoogleDriveListDirectoryByIdRequest: public Networking::Request { Common::Array _files; Request *_workingRequest; bool _ignoreCallback; + Common::String _date; void start(); void makeRequest(Common::String pageToken); @@ -53,6 +54,7 @@ public: virtual void handle(); virtual void restart(); + virtual Common::String date() const; }; } // End of namespace GoogleDrive diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp index 8811ffc938..3387b43418 100644 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp @@ -58,6 +58,7 @@ void GoogleDriveListDirectoryRequest::start() { void GoogleDriveListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); StorageFile directory = response.value; directory.setPath(_requestedPath); @@ -68,6 +69,7 @@ void GoogleDriveListDirectoryRequest::idResolvedCallback(Storage::UploadResponse void GoogleDriveListDirectoryRequest::idResolveErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -88,6 +90,7 @@ void GoogleDriveListDirectoryRequest::listNextDirectory() { void GoogleDriveListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); for (uint32 i = 0; i < response.value.size(); ++i) { StorageFile &file = response.value[i]; @@ -107,6 +110,7 @@ void GoogleDriveListDirectoryRequest::listedDirectoryCallback(Storage::FileArray void GoogleDriveListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -114,6 +118,8 @@ void GoogleDriveListDirectoryRequest::handle() {} void GoogleDriveListDirectoryRequest::restart() { start(); } +Common::String GoogleDriveListDirectoryRequest::date() const { return _date; } + void GoogleDriveListDirectoryRequest::finishSuccess(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h index bea195f70a..b3d8ff6c93 100644 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h @@ -43,6 +43,7 @@ class GoogleDriveListDirectoryRequest: public Networking::Request { StorageFile _currentDirectory; Request *_workingRequest; bool _ignoreCallback; + Common::String _date; void start(); void idResolvedCallback(Storage::UploadResponse response); @@ -57,6 +58,7 @@ public: virtual void handle(); virtual void restart(); + virtual Common::String date() const; }; } // End of namespace GoogleDrive diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index fe1128bd5b..2c644c42c5 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -87,6 +87,7 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r delete json; return; } + if (response.request) _date = response.request->date(); Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -112,6 +113,7 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r void OneDriveCreateDirectoryRequest::errorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -119,6 +121,8 @@ void OneDriveCreateDirectoryRequest::handle() {} void OneDriveCreateDirectoryRequest::restart() { start(); } +Common::String OneDriveCreateDirectoryRequest::date() const { return _date; } + void OneDriveCreateDirectoryRequest::finishSuccess(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h index 4bf0d9ef36..880e94e8db 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h @@ -38,6 +38,7 @@ class OneDriveCreateDirectoryRequest: public Networking::Request { Storage::BoolCallback _boolCallback; Request *_workingRequest; bool _ignoreCallback; + Common::String _date; void start(); void responseCallback(Networking::JsonResponse response); @@ -49,6 +50,7 @@ public: virtual void handle(); virtual void restart(); + virtual Common::String date() const; }; } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index 040ef153db..be6fcb70e7 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -94,6 +94,8 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo return; } + if (response.request) _date = response.request->date(); + Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq && rq->getNetworkReadStream()) @@ -138,6 +140,7 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo void OneDriveListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); finishError(error); } @@ -145,6 +148,8 @@ void OneDriveListDirectoryRequest::handle() {} void OneDriveListDirectoryRequest::restart() { start(); } +Common::String OneDriveListDirectoryRequest::date() const { return _date; } + void OneDriveListDirectoryRequest::finishSuccess(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h index b8adfe7ef0..5e80f4f561 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h @@ -43,6 +43,7 @@ class OneDriveListDirectoryRequest: public Networking::Request { Common::String _currentDirectory; Request *_workingRequest; bool _ignoreCallback; + Common::String _date; void start(); void listNextDirectory(); @@ -56,6 +57,7 @@ public: virtual void handle(); virtual void restart(); + virtual Common::String date() const; }; } // End of namespace OneDrive diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index e1739f9693..f059e29a8d 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -76,6 +76,8 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re _workingRequest = nullptr; if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + Common::HashMap localFileNotAvailableInCloud; for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { localFileNotAvailableInCloud[i->_key] = true; @@ -352,6 +354,9 @@ void SavesSyncRequest::finishSuccess(bool success) { //save updated timestamps (even if Request failed, there would be only valid timestamps) saveTimestamps(); + //update last successful sync date + CloudMan.setStorageLastSync(CloudMan.getStorageIndex(), _date); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 569feb4e45..1a615e80a1 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -45,6 +45,7 @@ class SavesSyncRequest: public Networking::Request, public GUI::CommandSender { Request *_workingRequest; bool _ignoreCallback; uint32 _totalFilesToHandle; + Common::String _date; void start(); void directoryListedCallback(Storage::ListDirectoryResponse response); -- cgit v1.2.3 From 9ee2eb4e60a34948797620a0f80ae0a80037efc0 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 10 Jun 2016 16:35:23 +0600 Subject: GUI: Add EditText in StorageWizardDialog One can enter the code, press 'Connect' button and get a working Storage! --- backends/cloud/cloudmanager.cpp | 10 +++ backends/cloud/cloudmanager.h | 99 ++++++++++++++----------- backends/cloud/dropbox/dropboxstorage.cpp | 80 +++++++------------- backends/cloud/dropbox/dropboxstorage.h | 12 ++- backends/cloud/googledrive/googledrivestorage.h | 10 +-- backends/cloud/onedrive/onedrivestorage.h | 8 +- 6 files changed, 101 insertions(+), 118 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index fed35a9f38..adfebdca88 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -195,6 +195,16 @@ void CloudManager::setStorageLastSync(uint32 index, Common::String date) { save(); } +void CloudManager::connectStorage(uint32 index, Common::String code) { + Storage *storage = nullptr; + switch (index) { + case kStorageDropboxId: storage = new Dropbox::DropboxStorage(code); break; + case kStorageOneDriveId: storage = new OneDrive::OneDriveStorage(code); break; + case kStorageGoogleDriveId: storage = new GoogleDrive::GoogleDriveStorage(code); break; + } + //these would automatically request replaceStorage() when they receive the token +} + void CloudManager::printBool(Storage::BoolResponse response) const { debug("bool = %s", (response.value ? "true" : "false")); } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index fd130c5ee8..9f4882d772 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -97,79 +97,88 @@ public: Cloud::Storage *getCurrentStorage() const; /** - * Return active Storage's index. - * - * @return active Storage's index. - */ + * Return active Storage's index. + * + * @return active Storage's index. + */ uint32 getStorageIndex() const; /** - * Return Storages names as list. - * - * @return a list of Storages names. - */ + * Return Storages names as list. + * + * @return a list of Storages names. + */ Common::StringArray listStorages() const; /** - * Changes the storage to the one with given index. - * - * @param new Storage's index. - */ + * Changes the storage to the one with given index. + * + * @param new Storage's index. + */ bool switchStorage(uint32 index); /** - * Return username used by Storage. - * - * @param Storage's index. - * @returns username or "" if index is invalid (no such Storage). - */ + * Return username used by Storage. + * + * @param Storage's index. + * @returns username or "" if index is invalid (no such Storage). + */ Common::String getStorageUsername(uint32 index); /** - * Return space used by Storage. - * - * @param Storage's index. - * @returns used space in bytes or 0 if index is invalid (no such Storage). - */ + * Return space used by Storage. + * + * @param Storage's index. + * @returns used space in bytes or 0 if index is invalid (no such Storage). + */ uint64 getStorageUsedSpace(uint32 index); /** - * Return Storage's last sync date. - * - * @param Storage's index. - * @returns last sync date or "" if index is invalid (no such Storage). + * Return Storage's last sync date. + * + * @param Storage's index. + * @returns last sync date or "" if index is invalid (no such Storage). It also returns "" if there never was any sync or if storage is syncing right now. - */ + */ Common::String getStorageLastSync(uint32 index); /** - * Set Storage's username. - * Automatically saves changes to the config. - * - * @param index Storage's index. - * @param name username to set - */ + * Set Storage's username. + * Automatically saves changes to the config. + * + * @param index Storage's index. + * @param name username to set + */ void setStorageUsername(uint32 index, Common::String name); /** - * Set Storage's used space field. - * Automatically saves changes to the config. - * - * @param index Storage's index. - * @param used value to set - */ + * Set Storage's used space field. + * Automatically saves changes to the config. + * + * @param index Storage's index. + * @param used value to set + */ void setStorageUsedSpace(uint32 index, uint64 used); /** - * Set Storage's last sync date. - * Automatically saves changes to the config. - * - * @param index Storage's index. - * @param date date to set - */ + * Set Storage's last sync date. + * Automatically saves changes to the config. + * + * @param index Storage's index. + * @param date date to set + */ void setStorageLastSync(uint32 index, Common::String date); + /** + * Replace Storage which has given index with a + * storage created with given code. + * + * @param index Storage's index + * @param code OAuth2 code received from user + */ + void connectStorage(uint32 index, Common::String code); + /** Returns ListDirectoryResponse with list of files. */ Networking::Request *listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index faff10f1d9..180b40c3d5 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -51,41 +51,47 @@ void DropboxStorage::loadKeyAndSecret() { SECRET[k.size()] = 0; } -static void saveAccessTokenCallback(Networking::JsonResponse pair) { - Common::JSONValue *json = (Common::JSONValue *)pair.value; - if (json) { - debug("saveAccessTokenCallback:"); - debug("%s", json->stringify(true).c_str()); +DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) {} + +DropboxStorage::DropboxStorage(Common::String code) { + getAccessToken(code); +} + +DropboxStorage::~DropboxStorage() {} + +void DropboxStorage::getAccessToken(Common::String code) { + Networking::JsonCallback callback = new Common::Callback(this, &DropboxStorage::codeFlowComplete); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, nullptr, "https://api.dropboxapi.com/1/oauth2/token"); + request->addPostField("code=" + code); + request->addPostField("grant_type=authorization_code"); + request->addPostField("client_id=" + Common::String(KEY)); + request->addPostField("client_secret=" + Common::String(SECRET)); + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); + addRequest(request); +} +void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { + Common::JSONValue *json = (Common::JSONValue *)response.value; + if (json) { Common::JSONObject result = json->asObject(); if (!result.contains("access_token") || !result.contains("uid")) { warning("Bad response, no token/uid passed"); } else { - //we suppose that's the first storage - //TODO: update it to use CloudMan.replaceStorage() - ConfMan.set("current_storage", "1", "cloud"); - ConfMan.set("storage_Dropbox_type", "Dropbox", "cloud"); - ConfMan.set("storage_Dropbox_access_token", result.getVal("access_token")->asString(), "cloud"); - ConfMan.set("storage_Dropbox_user_id", result.getVal("uid")->asString(), "cloud"); + _token = result.getVal("access_token")->asString(); + _uid = result.getVal("user_id")->asString(); ConfMan.removeKey("dropbox_code", "cloud"); + CloudMan.replaceStorage(this, kStorageDropboxId); ConfMan.flushToDisk(); - debug("Now please restart ScummVM to apply the changes."); + debug("Done! You can use Dropbox now! Look:"); + CloudMan.testFeature(); } delete json; } else { - debug("saveAccessTokenCallback: got NULL instead of JSON!"); + debug("DropboxStorage::codeFlowComplete: got NULL instead of JSON!"); } } -DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) { - curl_global_init(CURL_GLOBAL_ALL); -} - -DropboxStorage::~DropboxStorage() { - curl_global_cleanup(); -} - void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, "cloud"); ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); @@ -216,37 +222,5 @@ Common::String DropboxStorage::getAuthLink() { return url; } -void DropboxStorage::authThroughConsole() { - if (!ConfMan.hasKey("DROPBOX_KEY", "cloud") || !ConfMan.hasKey("DROPBOX_SECRET", "cloud")) { - warning("No Dropbox keys available, cannot do auth"); - return; - } - - loadKeyAndSecret(); - - if (ConfMan.hasKey("dropbox_code", "cloud")) { - //phase 2: get access_token using specified code - getAccessToken(ConfMan.get("dropbox_code", "cloud")); - return; - } - - debug("Navigate to this URL and press \"Allow\":"); - debug("%s\n", getAuthLink().c_str()); - debug("Then, add dropbox_code key in [cloud] section of configuration file. You should copy the value from URL and put it as value for that key.\n"); - debug("Navigate to this URL to get more information on ScummVM's configuration files:"); - debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); -} - -void DropboxStorage::getAccessToken(Common::String code) { - Networking::JsonCallback callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, nullptr, "https://api.dropboxapi.com/1/oauth2/token"); //TODO - request->addPostField("code=" + code); - request->addPostField("grant_type=authorization_code"); - request->addPostField("client_id=" + Common::String(KEY)); - request->addPostField("client_secret=" + Common::String(SECRET)); - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); - ConnMan.addRequest(request); -} - } // End of namespace Dropbox } // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 60a8075201..d256e0562b 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -40,7 +40,8 @@ class DropboxStorage: public Cloud::Storage { /** This private constructor is called from loadFromConfig(). */ DropboxStorage(Common::String token, Common::String uid); - static void getAccessToken(Common::String code); + void getAccessToken(Common::String code); + void codeFlowComplete(Networking::JsonResponse response); /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); @@ -49,7 +50,9 @@ class DropboxStorage: public Cloud::Storage { void printBool(BoolResponse response); void printStorageFile(UploadResponse response); -public: +public: + /** This constructor uses OAuth code flow to get tokens. */ + DropboxStorage(Common::String code); virtual ~DropboxStorage(); /** @@ -107,11 +110,6 @@ public: * Returns Dropbox auth link. */ static Common::String getAuthLink(); - - /** - * Show message with Dropbox auth instructions. (Temporary) - */ - static void authThroughConsole(); }; } // End of namespace Dropbox diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 489260db09..8093ef1938 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -40,12 +40,6 @@ class GoogleDriveStorage: public Cloud::Storage { /** This private constructor is called from loadFromConfig(). */ GoogleDriveStorage(Common::String token, Common::String refreshToken); - /** - * This private constructor is called from authThroughConsole() (phase 2). - * It uses OAuth code flow to get tokens. - */ - GoogleDriveStorage(Common::String code); - void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); void codeFlowComplete(BoolResponse response); @@ -61,7 +55,9 @@ class GoogleDriveStorage: public Cloud::Storage { void printBool(BoolResponse response); void printFile(UploadResponse response); void printInfo(StorageInfoResponse response); -public: +public: + /** This constructor uses OAuth code flow to get tokens. */ + GoogleDriveStorage(Common::String code); virtual ~GoogleDriveStorage(); /** diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 3932d44aae..061d0fa172 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -40,12 +40,6 @@ class OneDriveStorage: public Cloud::Storage { /** This private constructor is called from loadFromConfig(). */ OneDriveStorage(Common::String token, Common::String uid, Common::String refreshToken); - /** - * This private constructor is called from authThroughConsole() (phase 2). - * It uses OAuth code flow to get tokens. - */ - OneDriveStorage(Common::String code); - void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); void codeFlowComplete(BoolResponse response); @@ -60,6 +54,8 @@ class OneDriveStorage: public Cloud::Storage { void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); public: + /** This constructor uses OAuth code flow to get tokens. */ + OneDriveStorage(Common::String code); virtual ~OneDriveStorage(); /** -- cgit v1.2.3 From a966de42a97dff932b6292f5021b7eb278310d1d Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sat, 11 Jun 2016 11:18:13 +0200 Subject: CLOUD: Fix compilation error in savesyncrequest.h "savessyncrequest.h:35:35: error: use of undeclared identifier 'UINT_MAX'" --- backends/cloud/savessyncrequest.h | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 1a615e80a1..105d7f7f65 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -28,6 +28,7 @@ #include "common/hashmap.h" #include "common/hash-str.h" #include "gui/object.h" +#include namespace Cloud { -- cgit v1.2.3 From 2a2beaebc53ff6ef580a12b986d17147df3f15bc Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sat, 11 Jun 2016 21:38:20 +0200 Subject: Fix DropboxStorage::codeFlowComplete() --- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 180b40c3d5..b8851b05ec 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -78,7 +78,7 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { warning("Bad response, no token/uid passed"); } else { _token = result.getVal("access_token")->asString(); - _uid = result.getVal("user_id")->asString(); + _uid = result.getVal("uid")->asString(); ConfMan.removeKey("dropbox_code", "cloud"); CloudMan.replaceStorage(this, kStorageDropboxId); ConfMan.flushToDisk(); -- cgit v1.2.3 From dbafbf25693f13a9a3105379dd2b964095712fce Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 12 Jun 2016 11:47:52 +0600 Subject: CLOUD: Fix getAccessToken() KEY and SECRET should now load before getAccessToken() uses them, so it should work now. --- backends/cloud/dropbox/dropboxstorage.cpp | 7 ++++--- backends/cloud/googledrive/googledrivestorage.cpp | 5 +++-- backends/cloud/onedrive/onedrivestorage.cpp | 5 +++-- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index b8851b05ec..bcafcf5264 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -36,8 +36,8 @@ namespace Cloud { namespace Dropbox { -char *DropboxStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth -char *DropboxStorage::SECRET; //TODO: hide these secrets somehow +char *DropboxStorage::KEY = nullptr; //can't use ConfMan there yet, loading it on instance creation/auth +char *DropboxStorage::SECRET = nullptr; //TODO: hide these secrets somehow void DropboxStorage::loadKeyAndSecret() { Common::String k = ConfMan.get("DROPBOX_KEY", "cloud"); @@ -59,7 +59,8 @@ DropboxStorage::DropboxStorage(Common::String code) { DropboxStorage::~DropboxStorage() {} -void DropboxStorage::getAccessToken(Common::String code) { +void DropboxStorage::getAccessToken(Common::String code) { + if (!KEY || !SECRET) loadKeyAndSecret(); Networking::JsonCallback callback = new Common::Callback(this, &DropboxStorage::codeFlowComplete); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, nullptr, "https://api.dropboxapi.com/1/oauth2/token"); request->addPostField("code=" + code); diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 5eab071599..76ff1dd7fc 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -42,8 +42,8 @@ namespace Cloud { namespace GoogleDrive { -char *GoogleDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth -char *GoogleDriveStorage::SECRET; //TODO: hide these secrets somehow +char *GoogleDriveStorage::KEY = nullptr; //can't use ConfMan there yet, loading it on instance creation/auth +char *GoogleDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void GoogleDriveStorage::loadKeyAndSecret() { Common::String k = ConfMan.get("GOOGLE_DRIVE_KEY", "cloud"); @@ -67,6 +67,7 @@ GoogleDriveStorage::GoogleDriveStorage(Common::String code) { GoogleDriveStorage::~GoogleDriveStorage() {} void GoogleDriveStorage::getAccessToken(BoolCallback callback, Common::String code) { + if (!KEY || !SECRET) loadKeyAndSecret(); bool codeFlow = (code != ""); if (!codeFlow && _refreshToken == "") { diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index d1971f904a..6ae5cb0b16 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -38,8 +38,8 @@ namespace Cloud { namespace OneDrive { -char *OneDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth -char *OneDriveStorage::SECRET; //TODO: hide these secrets somehow +char *OneDriveStorage::KEY = nullptr; //can't use ConfMan there yet, loading it on instance creation/auth +char *OneDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void OneDriveStorage::loadKeyAndSecret() { Common::String k = ConfMan.get("ONEDRIVE_KEY", "cloud"); @@ -63,6 +63,7 @@ OneDriveStorage::OneDriveStorage(Common::String code) { OneDriveStorage::~OneDriveStorage() {} void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) { + if (!KEY || !SECRET) loadKeyAndSecret(); bool codeFlow = (code != ""); if (!codeFlow && _refreshToken == "") { -- cgit v1.2.3 From c068b74f303484819a8432379890b637d7bba029 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sun, 12 Jun 2016 21:28:16 +0200 Subject: CLOUD: Force handling of all StorageIDs values in CloudManager::getStorageConfigName() --- backends/cloud/cloudmanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index adfebdca88..0c087be7be 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -50,7 +50,8 @@ Common::String CloudManager::getStorageConfigName(uint32 index) const { case kStorageOneDriveId: return "OneDrive"; case kStorageGoogleDriveId: return "GoogleDrive"; } - return "Unknown"; + assert(false); // Unhandled StorageIDs value + return ""; } void CloudManager::loadStorage() { -- cgit v1.2.3 From 1403cf006c5ebfd4a6101b89f4ff1d8760bb0ea4 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sun, 12 Jun 2016 21:32:29 +0200 Subject: CLOUD: Make enum StorageIDs' name singular --- backends/cloud/cloudmanager.cpp | 2 +- backends/cloud/cloudmanager.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 0c087be7be..4a87098f50 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -50,7 +50,7 @@ Common::String CloudManager::getStorageConfigName(uint32 index) const { case kStorageOneDriveId: return "OneDrive"; case kStorageGoogleDriveId: return "GoogleDrive"; } - assert(false); // Unhandled StorageIDs value + assert(false); // Unhandled StorageID value return ""; } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 9f4882d772..48182dcde0 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -36,8 +36,8 @@ class CommandReceiver; namespace Cloud { -//that's actual indexes in CloudManager's array -enum StorageIDs { +// The actual indexes in CloudManager's array +enum StorageID { kStorageNoneId = 0, kStorageDropboxId = 1, kStorageOneDriveId = 2, @@ -84,7 +84,7 @@ public: * @note this method automatically saves the changes with ConfMan. * * @param storage Cloud::Storage to replace active storage with. - * @param index one of Cloud::StorageIDs enum values to indicate what storage type is replaced. + * @param index one of Cloud::StorageID enum values to indicate what storage type is replaced. */ void replaceStorage(Storage *storage, uint32 index); -- cgit v1.2.3 From 98788a5e7d0879d9f64e11e3d2308af2b03bc1de Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sun, 12 Jun 2016 21:36:58 +0200 Subject: CLOUD: Remove unnecessary blank lines in switch statement --- backends/cloud/cloudmanager.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 4a87098f50..8d12c0ff3a 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -59,15 +59,12 @@ void CloudManager::loadStorage() { case kStorageDropboxId: _activeStorage = Dropbox::DropboxStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); break; - case kStorageOneDriveId: _activeStorage = OneDrive::OneDriveStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); break; - case kStorageGoogleDriveId: _activeStorage = GoogleDrive::GoogleDriveStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); break; - default: _activeStorage = nullptr; } -- cgit v1.2.3 From fc3e7dec1a786c5990e37bd963838c235fba098b Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sun, 12 Jun 2016 22:12:15 +0200 Subject: CLOUD: Introduce kStoragePrefix in CloudManager --- backends/cloud/cloudmanager.cpp | 28 +++++++++++++++------------- backends/cloud/cloudmanager.h | 2 ++ 2 files changed, 17 insertions(+), 13 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 8d12c0ff3a..83b06d9405 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -36,6 +36,8 @@ DECLARE_SINGLETON(Cloud::CloudManager); namespace Cloud { +const char *const CloudManager::kStoragePrefix = "storage_"; + CloudManager::CloudManager() : _currentStorageIndex(0), _activeStorage(nullptr) {} CloudManager::~CloudManager() { @@ -57,13 +59,13 @@ Common::String CloudManager::getStorageConfigName(uint32 index) const { void CloudManager::loadStorage() { switch (_currentStorageIndex) { case kStorageDropboxId: - _activeStorage = Dropbox::DropboxStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); + _activeStorage = Dropbox::DropboxStorage::loadFromConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); break; case kStorageOneDriveId: - _activeStorage = OneDrive::OneDriveStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); + _activeStorage = OneDrive::OneDriveStorage::loadFromConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); break; case kStorageGoogleDriveId: - _activeStorage = GoogleDrive::GoogleDriveStorage::loadFromConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); + _activeStorage = GoogleDrive::GoogleDriveStorage::loadFromConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); break; default: _activeStorage = nullptr; @@ -83,12 +85,12 @@ void CloudManager::init() { config.username = ""; config.lastSyncDate = ""; config.usedBytes = 0; - if (ConfMan.hasKey("storage_" + name + "_username", "cloud")) - config.username = ConfMan.get("storage_" + name + "_username", "cloud"); - if (ConfMan.hasKey("storage_" + name + "_lastSync", "cloud")) - config.lastSyncDate = ConfMan.get("storage_" + name + "_lastSync", "cloud"); - if (ConfMan.hasKey("storage_" + name + "_usedBytes", "cloud")) - config.usedBytes = ConfMan.get("storage_" + name + "_usedBytes", "cloud").asUint64(); + if (ConfMan.hasKey(kStoragePrefix + name + "_username", "cloud")) + config.username = ConfMan.get(kStoragePrefix + name + "_username", "cloud"); + if (ConfMan.hasKey(kStoragePrefix + name + "_lastSync", "cloud")) + config.lastSyncDate = ConfMan.get(kStoragePrefix + name + "_lastSync", "cloud"); + if (ConfMan.hasKey(kStoragePrefix + name + "_usedBytes", "cloud")) + config.usedBytes = ConfMan.get(kStoragePrefix + name + "_usedBytes", "cloud").asUint64(); _storages.push_back(config); } @@ -104,14 +106,14 @@ void CloudManager::save() { for (uint32 i = 0; i < _storages.size(); ++i) { if (i == kStorageNoneId) continue; Common::String name = getStorageConfigName(i); - ConfMan.set("storage_" + name + "_username", _storages[i].username, "cloud"); - ConfMan.set("storage_" + name + "_lastSync", _storages[i].lastSyncDate, "cloud"); - ConfMan.set("storage_" + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes), "cloud"); + ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username, "cloud"); + ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate, "cloud"); + ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes), "cloud"); } ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex), "cloud"); if (_activeStorage) - _activeStorage->saveConfig("storage_" + getStorageConfigName(_currentStorageIndex) + "_"); + _activeStorage->saveConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); ConfMan.flushToDisk(); } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 48182dcde0..8e4c60eb4b 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -47,6 +47,8 @@ enum StorageID { }; class CloudManager : public Common::Singleton { + static const char *const kStoragePrefix; + struct StorageConfig { Common::String name, username; uint64 usedBytes; -- cgit v1.2.3 From fd6be018a34f315969371d9183311a56e3a9eaa2 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sun, 12 Jun 2016 22:24:14 +0200 Subject: CLOUD: Fix include in CloudManager --- backends/cloud/cloudmanager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 8e4c60eb4b..70b32f0758 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -26,7 +26,7 @@ #include "backends/cloud/storage.h" #include "common/array.h" #include "common/singleton.h" -#include +#include "common/str-array.h" namespace GUI { -- cgit v1.2.3 From bfc5cab9e88a2f70ac4a60c441c91a8b141ce113 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sun, 12 Jun 2016 22:29:23 +0200 Subject: CLOUD: Fix end of namespace comment in CloudManager --- backends/cloud/cloudmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 83b06d9405..77152d24ec 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -300,4 +300,4 @@ void CloudManager::setSyncTarget(GUI::CommandReceiver *target) { if (storage) storage->setSyncTarget(target); } -} // End of namespace Common +} // End of namespace Cloud -- cgit v1.2.3 From 219e565c32d81e375677b62f6e82e48fae75f26f Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Sun, 12 Jun 2016 23:02:32 +0200 Subject: CLOUD: Introduce CloudConfigHelper --- backends/cloud/cloudconfighelper.cpp | 58 +++++++++++++++++++++++ backends/cloud/cloudconfighelper.h | 49 +++++++++++++++++++ backends/cloud/cloudmanager.cpp | 28 +++++------ backends/cloud/dropbox/dropboxstorage.cpp | 24 +++++----- backends/cloud/googledrive/googledrivestorage.cpp | 30 ++++++------ backends/cloud/onedrive/onedrivestorage.cpp | 36 +++++++------- 6 files changed, 166 insertions(+), 59 deletions(-) create mode 100644 backends/cloud/cloudconfighelper.cpp create mode 100644 backends/cloud/cloudconfighelper.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudconfighelper.cpp b/backends/cloud/cloudconfighelper.cpp new file mode 100644 index 0000000000..8c31b1c770 --- /dev/null +++ b/backends/cloud/cloudconfighelper.cpp @@ -0,0 +1,58 @@ +/* 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/cloudconfighelper.h" +#include "common/config-manager.h" + +namespace Common { + +DECLARE_SINGLETON(Cloud::CloudConfigHelper); + +} + +namespace Cloud { + +bool CloudConfigHelper::hasKey(const Common::String &key) const { + return ConfMan.hasKey(key, ConfMan.kCloudDomain); +} + +void CloudConfigHelper::removeKey(const Common::String &key) { + ConfMan.removeKey(key, ConfMan.kCloudDomain); +} + +const Common::String &CloudConfigHelper::get(const Common::String &key) const { + return ConfMan.get(key, ConfMan.kCloudDomain); +} + +int CloudConfigHelper::getInt(const Common::String &key) const { + return ConfMan.getInt(key, ConfMan.kCloudDomain); +} + +void CloudConfigHelper::set(const Common::String &key, const Common::String &value) { + ConfMan.set(key, value, ConfMan.kCloudDomain); +} + +void CloudConfigHelper::flushToDisk() { + ConfMan.flushToDisk(); +} + +} // End of namespace Cloud diff --git a/backends/cloud/cloudconfighelper.h b/backends/cloud/cloudconfighelper.h new file mode 100644 index 0000000000..efa8792190 --- /dev/null +++ b/backends/cloud/cloudconfighelper.h @@ -0,0 +1,49 @@ +/* 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 CLOUD_CLOUDCONFIGHELPER_H +#define CLOUD_CLOUDCONFIGHELPER_H + +#include "common/singleton.h" +#include "common/str.h" + +namespace Cloud { + +/** + * Convenience wrapper around ConfMan for the cloud backend. + */ +class CloudConfigHelper : public Common::Singleton { +public: + bool hasKey(const Common::String &key) const; + void removeKey(const Common::String &key); + const Common::String &get(const Common::String &key) const; + int getInt(const Common::String &key) const; + void set(const Common::String &key, const Common::String &value); + void flushToDisk(); +}; + +/** Shortcut for accessing the cloud configuration helper. */ +#define CloudConfig Cloud::CloudConfigHelper::instance() + +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 77152d24ec..38b740216b 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -24,9 +24,9 @@ #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/onedrive/onedrivestorage.h" #include "backends/cloud/googledrive/googledrivestorage.h" -#include "common/config-manager.h" #include "common/debug.h" #include "common/translation.h" +#include "backends/cloud/cloudconfighelper.h" namespace Common { @@ -85,19 +85,19 @@ void CloudManager::init() { config.username = ""; config.lastSyncDate = ""; config.usedBytes = 0; - if (ConfMan.hasKey(kStoragePrefix + name + "_username", "cloud")) - config.username = ConfMan.get(kStoragePrefix + name + "_username", "cloud"); - if (ConfMan.hasKey(kStoragePrefix + name + "_lastSync", "cloud")) - config.lastSyncDate = ConfMan.get(kStoragePrefix + name + "_lastSync", "cloud"); - if (ConfMan.hasKey(kStoragePrefix + name + "_usedBytes", "cloud")) - config.usedBytes = ConfMan.get(kStoragePrefix + name + "_usedBytes", "cloud").asUint64(); + if (CloudConfig.hasKey(kStoragePrefix + name + "_username")) + config.username = CloudConfig.get(kStoragePrefix + name + "_username"); + if (CloudConfig.hasKey(kStoragePrefix + name + "_lastSync")) + config.lastSyncDate = CloudConfig.get(kStoragePrefix + name + "_lastSync"); + if (CloudConfig.hasKey(kStoragePrefix + name + "_usedBytes")) + config.usedBytes = CloudConfig.get(kStoragePrefix + name + "_usedBytes").asUint64(); _storages.push_back(config); } //load an active storage if there is any _currentStorageIndex = kStorageNoneId; - if (ConfMan.hasKey("current_storage", "cloud")) - _currentStorageIndex = ConfMan.getInt("current_storage", "cloud"); + if (CloudConfig.hasKey("current_storage")) + _currentStorageIndex = CloudConfig.getInt("current_storage"); loadStorage(); } @@ -106,15 +106,15 @@ void CloudManager::save() { for (uint32 i = 0; i < _storages.size(); ++i) { if (i == kStorageNoneId) continue; Common::String name = getStorageConfigName(i); - ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username, "cloud"); - ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate, "cloud"); - ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes), "cloud"); + CloudConfig.set(kStoragePrefix + name + "_username", _storages[i].username); + CloudConfig.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate); + CloudConfig.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes)); } - ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex), "cloud"); + CloudConfig.set("current_storage", Common::String::format("%d", _currentStorageIndex)); if (_activeStorage) _activeStorage->saveConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); - ConfMan.flushToDisk(); + CloudConfig.flushToDisk(); } void CloudManager::replaceStorage(Storage *storage, uint32 index) { diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index bcafcf5264..b677b56ff9 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -28,24 +28,24 @@ #include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" -#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include +#include "backends/cloud/cloudconfighelper.h" namespace Cloud { namespace Dropbox { -char *DropboxStorage::KEY = nullptr; //can't use ConfMan there yet, loading it on instance creation/auth +char *DropboxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth char *DropboxStorage::SECRET = nullptr; //TODO: hide these secrets somehow void DropboxStorage::loadKeyAndSecret() { - Common::String k = ConfMan.get("DROPBOX_KEY", "cloud"); + Common::String k = CloudConfig.get("DROPBOX_KEY"); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); KEY[k.size()] = 0; - k = ConfMan.get("DROPBOX_SECRET", "cloud"); + k = CloudConfig.get("DROPBOX_SECRET"); SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; @@ -80,9 +80,9 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { } else { _token = result.getVal("access_token")->asString(); _uid = result.getVal("uid")->asString(); - ConfMan.removeKey("dropbox_code", "cloud"); + CloudConfig.removeKey("dropbox_code"); CloudMan.replaceStorage(this, kStorageDropboxId); - ConfMan.flushToDisk(); + CloudConfig.flushToDisk(); debug("Done! You can use Dropbox now! Look:"); CloudMan.testFeature(); } @@ -94,8 +94,8 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { } void DropboxStorage::saveConfig(Common::String keyPrefix) { - ConfMan.set(keyPrefix + "access_token", _token, "cloud"); - ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); + CloudConfig.set(keyPrefix + "access_token", _token); + CloudConfig.set(keyPrefix + "user_id", _uid); } Common::String DropboxStorage::name() const { @@ -199,18 +199,18 @@ void DropboxStorage::infoMethodCallback(StorageInfoResponse response) { DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); - if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { + if (!CloudConfig.hasKey(keyPrefix + "access_token")) { warning("No access_token found"); return 0; } - if (!ConfMan.hasKey(keyPrefix + "user_id", "cloud")) { + if (!CloudConfig.hasKey(keyPrefix + "user_id")) { warning("No user_id found"); return 0; } - Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud"); - Common::String userId = ConfMan.get(keyPrefix + "user_id", "cloud"); + Common::String accessToken = CloudConfig.get(keyPrefix + "access_token"); + Common::String userId = CloudConfig.get(keyPrefix + "user_id"); return new DropboxStorage(accessToken, userId); } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 76ff1dd7fc..2b044ce12a 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -27,7 +27,6 @@ #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" -#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include @@ -38,20 +37,21 @@ #include "googledrivestreamfilerequest.h" #include "googledrivedownloadrequest.h" #include "googledriveuploadrequest.h" +#include "backends/cloud/cloudconfighelper.h" namespace Cloud { namespace GoogleDrive { -char *GoogleDriveStorage::KEY = nullptr; //can't use ConfMan there yet, loading it on instance creation/auth +char *GoogleDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth char *GoogleDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void GoogleDriveStorage::loadKeyAndSecret() { - Common::String k = ConfMan.get("GOOGLE_DRIVE_KEY", "cloud"); + Common::String k = CloudConfig.get("GOOGLE_DRIVE_KEY"); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); KEY[k.size()] = 0; - k = ConfMan.get("GOOGLE_DRIVE_SECRET", "cloud"); + k = CloudConfig.get("GOOGLE_DRIVE_SECRET"); SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; @@ -122,16 +122,16 @@ void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { return; } - ConfMan.removeKey("googledrive_code", "cloud"); + CloudConfig.removeKey("googledrive_code"); CloudMan.replaceStorage(this, kStorageGoogleDriveId); - ConfMan.flushToDisk(); + CloudConfig.flushToDisk(); debug("Done! You can use Google Drive now! Look:"); CloudMan.testFeature(); } void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { - ConfMan.set(keyPrefix + "access_token", _token, "cloud"); - ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); + CloudConfig.set(keyPrefix + "access_token", _token); + CloudConfig.set(keyPrefix + "refresh_token", _refreshToken); } Common::String GoogleDriveStorage::name() const { @@ -339,18 +339,18 @@ Common::String GoogleDriveStorage::savesDirectoryPath() { return "scummvm/saves/ GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); - if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { + if (!CloudConfig.hasKey(keyPrefix + "access_token")) { warning("No access_token found"); return 0; } - if (!ConfMan.hasKey(keyPrefix + "refresh_token", "cloud")) { + if (!CloudConfig.hasKey(keyPrefix + "refresh_token")) { warning("No refresh_token found"); return 0; } - Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud"); - Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", "cloud"); + Common::String accessToken = CloudConfig.get(keyPrefix + "access_token"); + Common::String refreshToken = CloudConfig.get(keyPrefix + "refresh_token"); return new GoogleDriveStorage(accessToken, refreshToken); } @@ -365,16 +365,16 @@ Common::String GoogleDriveStorage::getAuthLink() { } void GoogleDriveStorage::authThroughConsole() { - if (!ConfMan.hasKey("GOOGLE_DRIVE_KEY", "cloud") || !ConfMan.hasKey("GOOGLE_DRIVE_SECRET", "cloud")) { + if (!CloudConfig.hasKey("GOOGLE_DRIVE_KEY") || !CloudConfig.hasKey("GOOGLE_DRIVE_SECRET")) { warning("No Google Drive keys available, cannot do auth"); return; } loadKeyAndSecret(); - if (ConfMan.hasKey("googledrive_code", "cloud")) { + if (CloudConfig.hasKey("googledrive_code")) { //phase 2: get access_token using specified code - new GoogleDriveStorage(ConfMan.get("googledrive_code", "cloud")); + new GoogleDriveStorage(CloudConfig.get("googledrive_code")); return; } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 6ae5cb0b16..bc1a4ff130 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -30,24 +30,24 @@ #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" -#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include +#include "backends/cloud/cloudconfighelper.h" namespace Cloud { namespace OneDrive { -char *OneDriveStorage::KEY = nullptr; //can't use ConfMan there yet, loading it on instance creation/auth +char *OneDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth char *OneDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void OneDriveStorage::loadKeyAndSecret() { - Common::String k = ConfMan.get("ONEDRIVE_KEY", "cloud"); + Common::String k = CloudConfig.get("ONEDRIVE_KEY"); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); KEY[k.size()] = 0; - k = ConfMan.get("ONEDRIVE_SECRET", "cloud"); + k = CloudConfig.get("ONEDRIVE_SECRET"); SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; @@ -116,17 +116,17 @@ void OneDriveStorage::codeFlowComplete(BoolResponse response) { return; } - ConfMan.removeKey("onedrive_code", "cloud"); + CloudConfig.removeKey("onedrive_code"); CloudMan.replaceStorage(this, kStorageOneDriveId); - ConfMan.flushToDisk(); + CloudConfig.flushToDisk(); debug("Done! You can use OneDrive now! Look:"); CloudMan.syncSaves(); } void OneDriveStorage::saveConfig(Common::String keyPrefix) { - ConfMan.set(keyPrefix + "access_token", _token, "cloud"); - ConfMan.set(keyPrefix + "user_id", _uid, "cloud"); - ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud"); + CloudConfig.set(keyPrefix + "access_token", _token); + CloudConfig.set(keyPrefix + "user_id", _uid); + CloudConfig.set(keyPrefix + "refresh_token", _refreshToken); } Common::String OneDriveStorage::name() const { @@ -262,24 +262,24 @@ Common::String OneDriveStorage::savesDirectoryPath() { return "saves/"; } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); - if (!ConfMan.hasKey(keyPrefix + "access_token", "cloud")) { + if (!CloudConfig.hasKey(keyPrefix + "access_token")) { warning("No access_token found"); return 0; } - if (!ConfMan.hasKey(keyPrefix + "user_id", "cloud")) { + if (!CloudConfig.hasKey(keyPrefix + "user_id")) { warning("No user_id found"); return 0; } - if (!ConfMan.hasKey(keyPrefix + "refresh_token", "cloud")) { + if (!CloudConfig.hasKey(keyPrefix + "refresh_token")) { warning("No refresh_token found"); return 0; } - Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud"); - Common::String userId = ConfMan.get(keyPrefix + "user_id", "cloud"); - Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", "cloud"); + Common::String accessToken = CloudConfig.get(keyPrefix + "access_token"); + Common::String userId = CloudConfig.get(keyPrefix + "user_id"); + Common::String refreshToken = CloudConfig.get(keyPrefix + "refresh_token"); return new OneDriveStorage(accessToken, userId, refreshToken); } @@ -294,16 +294,16 @@ Common::String OneDriveStorage::getAuthLink() { } void OneDriveStorage::authThroughConsole() { - if (!ConfMan.hasKey("ONEDRIVE_KEY", "cloud") || !ConfMan.hasKey("ONEDRIVE_SECRET", "cloud")) { + if (!CloudConfig.hasKey("ONEDRIVE_KEY") || !CloudConfig.hasKey("ONEDRIVE_SECRET")) { warning("No OneDrive keys available, cannot do auth"); return; } loadKeyAndSecret(); - if (ConfMan.hasKey("onedrive_code", "cloud")) { + if (CloudConfig.hasKey("onedrive_code")) { //phase 2: get access_token using specified code - new OneDriveStorage(ConfMan.get("onedrive_code", "cloud")); + new OneDriveStorage(CloudConfig.get("onedrive_code")); return; } -- cgit v1.2.3 From 0aea8db7e1a59e8cf88436f78019685c9aff6332 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 13 Jun 2016 12:32:33 +0600 Subject: CLOUD: Make Storage::savesSync() restart If Storage::syncSaves() is called when sync is running, another sync would be automatically scheduled in the end of the current one. That could be helpful when we want to specify that we changed something during sync (created new save slot, for example). --- backends/cloud/storage.cpp | 10 +++++++++- backends/cloud/storage.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 08ab9e9c90..b98f213327 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -52,12 +52,18 @@ Networking::Request *Storage::addRequest(Networking::Request *request) { } void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer) { + bool restartSync = false; + _runningRequestsMutex.lock(); if (invalidRequestPointer == _savesSyncRequest) _savesSyncRequest = nullptr; --_runningRequestsCount; - if (_runningRequestsCount == 0) debug("Storage is not working now"); + if (_syncRestartRequestsed) restartSync = true; + if (_runningRequestsCount == 0 && !restartSync) debug("Storage is not working now"); _runningRequestsMutex.unlock(); + + if (restartSync) + syncSaves(nullptr, nullptr); } Networking::Request *Storage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { @@ -111,11 +117,13 @@ SavesSyncRequest *Storage::syncSaves(BoolCallback callback, Networking::ErrorCal _runningRequestsMutex.lock(); if (_savesSyncRequest) { warning("Storage::syncSaves: there is a sync in progress already"); + _syncRestartRequestsed = true; _runningRequestsMutex.unlock(); return _savesSyncRequest; } if (!errorCallback) errorCallback = getErrorPrintingCallback(); _savesSyncRequest = new SavesSyncRequest(this, callback, errorCallback); + _syncRestartRequestsed = false; _runningRequestsMutex.unlock(); return (SavesSyncRequest *)addRequest(_savesSyncRequest); //who knows what that ConnMan could return in the future } diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index a76f2169bc..ace2f30864 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -62,6 +62,7 @@ protected: uint32 _runningRequestsCount; Common::Mutex _runningRequestsMutex; SavesSyncRequest *_savesSyncRequest; + bool _syncRestartRequestsed; /** Returns default error callback (printErrorResponse). */ virtual Networking::ErrorCallback getErrorPrintingCallback(); -- cgit v1.2.3 From 8a84263d2b7f30bdb87a0b49c1d84454ece38b21 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 14 Jun 2016 21:16:11 +0600 Subject: CLOUD: Do saves sync on Storage connect --- backends/cloud/cloudmanager.cpp | 7 ++++++- backends/cloud/dropbox/dropboxstorage.cpp | 3 +-- backends/cloud/googledrive/googledrivestorage.cpp | 2 -- backends/cloud/onedrive/onedrivestorage.cpp | 2 -- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 38b740216b..a6f5575b3a 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -124,7 +124,12 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) { _activeStorage = storage; _currentStorageIndex = index; save(); - if (_activeStorage) _activeStorage->info(nullptr, nullptr); //automatically calls setStorageUsername() + + //do what should be done on first Storage connect + if (_activeStorage) { + _activeStorage->info(nullptr, nullptr); //automatically calls setStorageUsername() + _activeStorage->syncSaves(nullptr, nullptr); + } } Storage *CloudManager::getCurrentStorage() const { diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index b677b56ff9..d77e958da7 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -76,6 +76,7 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { if (json) { Common::JSONObject result = json->asObject(); if (!result.contains("access_token") || !result.contains("uid")) { + warning(json->stringify(true).c_str()); warning("Bad response, no token/uid passed"); } else { _token = result.getVal("access_token")->asString(); @@ -83,8 +84,6 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { CloudConfig.removeKey("dropbox_code"); CloudMan.replaceStorage(this, kStorageDropboxId); CloudConfig.flushToDisk(); - debug("Done! You can use Dropbox now! Look:"); - CloudMan.testFeature(); } delete json; diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 2b044ce12a..1e31121d6c 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -125,8 +125,6 @@ void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { CloudConfig.removeKey("googledrive_code"); CloudMan.replaceStorage(this, kStorageGoogleDriveId); CloudConfig.flushToDisk(); - debug("Done! You can use Google Drive now! Look:"); - CloudMan.testFeature(); } void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index bc1a4ff130..b91d1cdce1 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -119,8 +119,6 @@ void OneDriveStorage::codeFlowComplete(BoolResponse response) { CloudConfig.removeKey("onedrive_code"); CloudMan.replaceStorage(this, kStorageOneDriveId); CloudConfig.flushToDisk(); - debug("Done! You can use OneDrive now! Look:"); - CloudMan.syncSaves(); } void OneDriveStorage::saveConfig(Common::String keyPrefix) { -- cgit v1.2.3 From a8eebbe8517bf75131af4d7846592ebcc7e79d25 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Tue, 14 Jun 2016 20:47:03 +0200 Subject: CLOUD: Get rid of CloudConfigHelper, use kCloudDomain where approriate --- backends/cloud/cloudconfighelper.cpp | 58 ----------------------- backends/cloud/cloudconfighelper.h | 49 ------------------- backends/cloud/cloudmanager.cpp | 39 +++++++++------ backends/cloud/dropbox/dropboxstorage.cpp | 25 +++++----- backends/cloud/googledrive/googledrivestorage.cpp | 28 +++++------ backends/cloud/onedrive/onedrivestorage.cpp | 36 +++++++------- 6 files changed, 70 insertions(+), 165 deletions(-) delete mode 100644 backends/cloud/cloudconfighelper.cpp delete mode 100644 backends/cloud/cloudconfighelper.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudconfighelper.cpp b/backends/cloud/cloudconfighelper.cpp deleted file mode 100644 index 8c31b1c770..0000000000 --- a/backends/cloud/cloudconfighelper.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* 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/cloudconfighelper.h" -#include "common/config-manager.h" - -namespace Common { - -DECLARE_SINGLETON(Cloud::CloudConfigHelper); - -} - -namespace Cloud { - -bool CloudConfigHelper::hasKey(const Common::String &key) const { - return ConfMan.hasKey(key, ConfMan.kCloudDomain); -} - -void CloudConfigHelper::removeKey(const Common::String &key) { - ConfMan.removeKey(key, ConfMan.kCloudDomain); -} - -const Common::String &CloudConfigHelper::get(const Common::String &key) const { - return ConfMan.get(key, ConfMan.kCloudDomain); -} - -int CloudConfigHelper::getInt(const Common::String &key) const { - return ConfMan.getInt(key, ConfMan.kCloudDomain); -} - -void CloudConfigHelper::set(const Common::String &key, const Common::String &value) { - ConfMan.set(key, value, ConfMan.kCloudDomain); -} - -void CloudConfigHelper::flushToDisk() { - ConfMan.flushToDisk(); -} - -} // End of namespace Cloud diff --git a/backends/cloud/cloudconfighelper.h b/backends/cloud/cloudconfighelper.h deleted file mode 100644 index efa8792190..0000000000 --- a/backends/cloud/cloudconfighelper.h +++ /dev/null @@ -1,49 +0,0 @@ -/* 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 CLOUD_CLOUDCONFIGHELPER_H -#define CLOUD_CLOUDCONFIGHELPER_H - -#include "common/singleton.h" -#include "common/str.h" - -namespace Cloud { - -/** - * Convenience wrapper around ConfMan for the cloud backend. - */ -class CloudConfigHelper : public Common::Singleton { -public: - bool hasKey(const Common::String &key) const; - void removeKey(const Common::String &key); - const Common::String &get(const Common::String &key) const; - int getInt(const Common::String &key) const; - void set(const Common::String &key, const Common::String &value); - void flushToDisk(); -}; - -/** Shortcut for accessing the cloud configuration helper. */ -#define CloudConfig Cloud::CloudConfigHelper::instance() - -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a6f5575b3a..19551213cd 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -26,7 +26,8 @@ #include "backends/cloud/googledrive/googledrivestorage.h" #include "common/debug.h" #include "common/translation.h" -#include "backends/cloud/cloudconfighelper.h" +#include "common/config-manager.h" +#include "common/str.h" namespace Common { @@ -77,6 +78,9 @@ void CloudManager::loadStorage() { } void CloudManager::init() { + Common::String oldDomain = ConfMan.getActiveDomainName(); + ConfMan.setActiveDomain(ConfMan.kCloudDomain); + //init configs structs for (uint32 i = 0; i < kStorageTotal; ++i) { Common::String name = getStorageConfigName(i); @@ -85,36 +89,43 @@ void CloudManager::init() { config.username = ""; config.lastSyncDate = ""; config.usedBytes = 0; - if (CloudConfig.hasKey(kStoragePrefix + name + "_username")) - config.username = CloudConfig.get(kStoragePrefix + name + "_username"); - if (CloudConfig.hasKey(kStoragePrefix + name + "_lastSync")) - config.lastSyncDate = CloudConfig.get(kStoragePrefix + name + "_lastSync"); - if (CloudConfig.hasKey(kStoragePrefix + name + "_usedBytes")) - config.usedBytes = CloudConfig.get(kStoragePrefix + name + "_usedBytes").asUint64(); + if (ConfMan.hasKey(kStoragePrefix + name + "_username")) + config.username = ConfMan.get(kStoragePrefix + name + "_username"); + if (ConfMan.hasKey(kStoragePrefix + name + "_lastSync")) + config.lastSyncDate = ConfMan.get(kStoragePrefix + name + "_lastSync"); + if (ConfMan.hasKey(kStoragePrefix + name + "_usedBytes")) + config.usedBytes = ConfMan.get(kStoragePrefix + name + "_usedBytes").asUint64(); _storages.push_back(config); } //load an active storage if there is any _currentStorageIndex = kStorageNoneId; - if (CloudConfig.hasKey("current_storage")) - _currentStorageIndex = CloudConfig.getInt("current_storage"); + if (ConfMan.hasKey("current_storage")) + _currentStorageIndex = ConfMan.getInt("current_storage"); loadStorage(); + + ConfMan.setActiveDomain(oldDomain); } void CloudManager::save() { + Common::String oldDomain = ConfMan.getActiveDomainName(); + ConfMan.setActiveDomain(ConfMan.kCloudDomain); + for (uint32 i = 0; i < _storages.size(); ++i) { if (i == kStorageNoneId) continue; Common::String name = getStorageConfigName(i); - CloudConfig.set(kStoragePrefix + name + "_username", _storages[i].username); - CloudConfig.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate); - CloudConfig.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes)); + ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username); + ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate); + ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes)); } - CloudConfig.set("current_storage", Common::String::format("%d", _currentStorageIndex)); + ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex)); if (_activeStorage) _activeStorage->saveConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); - CloudConfig.flushToDisk(); + ConfMan.flushToDisk(); + + ConfMan.setActiveDomain(oldDomain); } void CloudManager::replaceStorage(Storage *storage, uint32 index) { diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index d77e958da7..64425812db 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -31,7 +31,7 @@ #include "common/debug.h" #include "common/json.h" #include -#include "backends/cloud/cloudconfighelper.h" +#include "common/config-manager.h" namespace Cloud { namespace Dropbox { @@ -40,12 +40,12 @@ char *DropboxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading char *DropboxStorage::SECRET = nullptr; //TODO: hide these secrets somehow void DropboxStorage::loadKeyAndSecret() { - Common::String k = CloudConfig.get("DROPBOX_KEY"); + Common::String k = ConfMan.get("DROPBOX_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); KEY[k.size()] = 0; - k = CloudConfig.get("DROPBOX_SECRET"); + k = ConfMan.get("DROPBOX_SECRET", ConfMan.kCloudDomain); SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; @@ -81,9 +81,9 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { } else { _token = result.getVal("access_token")->asString(); _uid = result.getVal("uid")->asString(); - CloudConfig.removeKey("dropbox_code"); + ConfMan.removeKey("dropbox_code", ConfMan.kCloudDomain); CloudMan.replaceStorage(this, kStorageDropboxId); - CloudConfig.flushToDisk(); + ConfMan.flushToDisk(); } delete json; @@ -92,9 +92,9 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { } } -void DropboxStorage::saveConfig(Common::String keyPrefix) { - CloudConfig.set(keyPrefix + "access_token", _token); - CloudConfig.set(keyPrefix + "user_id", _uid); +void DropboxStorage::saveConfig(Common::String keyPrefix) { + ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); + ConfMan.set(keyPrefix + "user_id", _uid, ConfMan.kCloudDomain); } Common::String DropboxStorage::name() const { @@ -198,18 +198,19 @@ void DropboxStorage::infoMethodCallback(StorageInfoResponse response) { DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); - if (!CloudConfig.hasKey(keyPrefix + "access_token")) { + if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { warning("No access_token found"); return 0; } - if (!CloudConfig.hasKey(keyPrefix + "user_id")) { + if (!ConfMan.hasKey(keyPrefix + "user_id", ConfMan.kCloudDomain)) { warning("No user_id found"); return 0; } - Common::String accessToken = CloudConfig.get(keyPrefix + "access_token"); - Common::String userId = CloudConfig.get(keyPrefix + "user_id"); + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); + Common::String userId = ConfMan.get(keyPrefix + "user_id", ConfMan.kCloudDomain); + return new DropboxStorage(accessToken, userId); } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 1e31121d6c..6d0a152938 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -37,7 +37,7 @@ #include "googledrivestreamfilerequest.h" #include "googledrivedownloadrequest.h" #include "googledriveuploadrequest.h" -#include "backends/cloud/cloudconfighelper.h" +#include "common/config-manager.h" namespace Cloud { namespace GoogleDrive { @@ -46,12 +46,12 @@ char *GoogleDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, load char *GoogleDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void GoogleDriveStorage::loadKeyAndSecret() { - Common::String k = CloudConfig.get("GOOGLE_DRIVE_KEY"); + Common::String k = ConfMan.get("GOOGLE_DRIVE_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); KEY[k.size()] = 0; - k = CloudConfig.get("GOOGLE_DRIVE_SECRET"); + k = ConfMan.get("GOOGLE_DRIVE_SECRET", ConfMan.kCloudDomain); SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; @@ -122,14 +122,14 @@ void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { return; } - CloudConfig.removeKey("googledrive_code"); + ConfMan.removeKey("googledrive_code", ConfMan.kCloudDomain); CloudMan.replaceStorage(this, kStorageGoogleDriveId); - CloudConfig.flushToDisk(); + ConfMan.flushToDisk(); } void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { - CloudConfig.set(keyPrefix + "access_token", _token); - CloudConfig.set(keyPrefix + "refresh_token", _refreshToken); + ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); + ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); } Common::String GoogleDriveStorage::name() const { @@ -337,18 +337,18 @@ Common::String GoogleDriveStorage::savesDirectoryPath() { return "scummvm/saves/ GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); - if (!CloudConfig.hasKey(keyPrefix + "access_token")) { + if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { warning("No access_token found"); return 0; } - if (!CloudConfig.hasKey(keyPrefix + "refresh_token")) { + if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { warning("No refresh_token found"); return 0; } - Common::String accessToken = CloudConfig.get(keyPrefix + "access_token"); - Common::String refreshToken = CloudConfig.get(keyPrefix + "refresh_token"); + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); + Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", ConfMan.kCloudDomain); return new GoogleDriveStorage(accessToken, refreshToken); } @@ -363,16 +363,16 @@ Common::String GoogleDriveStorage::getAuthLink() { } void GoogleDriveStorage::authThroughConsole() { - if (!CloudConfig.hasKey("GOOGLE_DRIVE_KEY") || !CloudConfig.hasKey("GOOGLE_DRIVE_SECRET")) { + if (!ConfMan.hasKey("GOOGLE_DRIVE_KEY", ConfMan.kCloudDomain) || !ConfMan.hasKey("GOOGLE_DRIVE_SECRET", ConfMan.kCloudDomain)) { warning("No Google Drive keys available, cannot do auth"); return; } loadKeyAndSecret(); - if (CloudConfig.hasKey("googledrive_code")) { + if (ConfMan.hasKey("googledrive_code", ConfMan.kCloudDomain)) { //phase 2: get access_token using specified code - new GoogleDriveStorage(CloudConfig.get("googledrive_code")); + new GoogleDriveStorage(ConfMan.get("googledrive_code", ConfMan.kCloudDomain)); return; } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index b91d1cdce1..5c230366a8 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -33,7 +33,7 @@ #include "common/debug.h" #include "common/json.h" #include -#include "backends/cloud/cloudconfighelper.h" +#include "common/config-manager.h" namespace Cloud { namespace OneDrive { @@ -42,12 +42,12 @@ char *OneDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading char *OneDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void OneDriveStorage::loadKeyAndSecret() { - Common::String k = CloudConfig.get("ONEDRIVE_KEY"); + Common::String k = ConfMan.get("ONEDRIVE_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); KEY[k.size()] = 0; - k = CloudConfig.get("ONEDRIVE_SECRET"); + k = ConfMan.get("ONEDRIVE_SECRET", ConfMan.kCloudDomain); SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; @@ -116,15 +116,15 @@ void OneDriveStorage::codeFlowComplete(BoolResponse response) { return; } - CloudConfig.removeKey("onedrive_code"); + ConfMan.removeKey("onedrive_code", ConfMan.kCloudDomain); CloudMan.replaceStorage(this, kStorageOneDriveId); - CloudConfig.flushToDisk(); + ConfMan.flushToDisk(); } -void OneDriveStorage::saveConfig(Common::String keyPrefix) { - CloudConfig.set(keyPrefix + "access_token", _token); - CloudConfig.set(keyPrefix + "user_id", _uid); - CloudConfig.set(keyPrefix + "refresh_token", _refreshToken); +void OneDriveStorage::saveConfig(Common::String keyPrefix) { + ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); + ConfMan.set(keyPrefix + "user_id", _uid, ConfMan.kCloudDomain); + ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); } Common::String OneDriveStorage::name() const { @@ -260,24 +260,24 @@ Common::String OneDriveStorage::savesDirectoryPath() { return "saves/"; } OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); - if (!CloudConfig.hasKey(keyPrefix + "access_token")) { + if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { warning("No access_token found"); return 0; } - if (!CloudConfig.hasKey(keyPrefix + "user_id")) { + if (!ConfMan.hasKey(keyPrefix + "user_id", ConfMan.kCloudDomain)) { warning("No user_id found"); return 0; } - if (!CloudConfig.hasKey(keyPrefix + "refresh_token")) { + if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { warning("No refresh_token found"); return 0; } - Common::String accessToken = CloudConfig.get(keyPrefix + "access_token"); - Common::String userId = CloudConfig.get(keyPrefix + "user_id"); - Common::String refreshToken = CloudConfig.get(keyPrefix + "refresh_token"); + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); + Common::String userId = ConfMan.get(keyPrefix + "user_id", ConfMan.kCloudDomain); + Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", ConfMan.kCloudDomain); return new OneDriveStorage(accessToken, userId, refreshToken); } @@ -292,16 +292,16 @@ Common::String OneDriveStorage::getAuthLink() { } void OneDriveStorage::authThroughConsole() { - if (!CloudConfig.hasKey("ONEDRIVE_KEY") || !CloudConfig.hasKey("ONEDRIVE_SECRET")) { + if (!ConfMan.hasKey("ONEDRIVE_KEY", ConfMan.kCloudDomain) || !ConfMan.hasKey("ONEDRIVE_SECRET", ConfMan.kCloudDomain)) { warning("No OneDrive keys available, cannot do auth"); return; } loadKeyAndSecret(); - if (CloudConfig.hasKey("onedrive_code")) { + if (ConfMan.hasKey("onedrive_code", ConfMan.kCloudDomain)) { //phase 2: get access_token using specified code - new OneDriveStorage(CloudConfig.get("onedrive_code")); + new OneDriveStorage(ConfMan.get("onedrive_code", ConfMan.kCloudDomain)); return; } -- cgit v1.2.3 From c1ffb09fb0e75a96e48299c1df0742f357e5d03d Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Tue, 14 Jun 2016 21:16:18 +0200 Subject: CLOUD: Fix configuration handling in CloudManager --- backends/cloud/cloudmanager.cpp | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 19551213cd..8b104dfb20 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -78,9 +78,6 @@ void CloudManager::loadStorage() { } void CloudManager::init() { - Common::String oldDomain = ConfMan.getActiveDomainName(); - ConfMan.setActiveDomain(ConfMan.kCloudDomain); - //init configs structs for (uint32 i = 0; i < kStorageTotal; ++i) { Common::String name = getStorageConfigName(i); @@ -89,43 +86,36 @@ void CloudManager::init() { config.username = ""; config.lastSyncDate = ""; config.usedBytes = 0; - if (ConfMan.hasKey(kStoragePrefix + name + "_username")) - config.username = ConfMan.get(kStoragePrefix + name + "_username"); - if (ConfMan.hasKey(kStoragePrefix + name + "_lastSync")) - config.lastSyncDate = ConfMan.get(kStoragePrefix + name + "_lastSync"); - if (ConfMan.hasKey(kStoragePrefix + name + "_usedBytes")) - config.usedBytes = ConfMan.get(kStoragePrefix + name + "_usedBytes").asUint64(); + if (ConfMan.hasKey(kStoragePrefix + name + "_username", ConfMan.kCloudDomain)) + config.username = ConfMan.get(kStoragePrefix + name + "_username", ConfMan.kCloudDomain); + if (ConfMan.hasKey(kStoragePrefix + name + "_lastSync", ConfMan.kCloudDomain)) + config.lastSyncDate = ConfMan.get(kStoragePrefix + name + "_lastSync", ConfMan.kCloudDomain); + if (ConfMan.hasKey(kStoragePrefix + name + "_usedBytes", ConfMan.kCloudDomain)) + config.usedBytes = ConfMan.get(kStoragePrefix + name + "_usedBytes", ConfMan.kCloudDomain).asUint64(); _storages.push_back(config); } //load an active storage if there is any _currentStorageIndex = kStorageNoneId; - if (ConfMan.hasKey("current_storage")) - _currentStorageIndex = ConfMan.getInt("current_storage"); + if (ConfMan.hasKey("current_storage", ConfMan.kCloudDomain)) + _currentStorageIndex = ConfMan.getInt("current_storage", ConfMan.kCloudDomain); loadStorage(); - - ConfMan.setActiveDomain(oldDomain); } void CloudManager::save() { - Common::String oldDomain = ConfMan.getActiveDomainName(); - ConfMan.setActiveDomain(ConfMan.kCloudDomain); - for (uint32 i = 0; i < _storages.size(); ++i) { if (i == kStorageNoneId) continue; Common::String name = getStorageConfigName(i); - ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username); - ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate); - ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes)); + ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username, ConfMan.kCloudDomain); + ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate, ConfMan.kCloudDomain); + ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes, ConfMan.kCloudDomain)); } - ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex)); + ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex, ConfMan.kCloudDomain)); if (_activeStorage) _activeStorage->saveConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); ConfMan.flushToDisk(); - - ConfMan.setActiveDomain(oldDomain); } void CloudManager::replaceStorage(Storage *storage, uint32 index) { -- cgit v1.2.3 From 0af97e59bc63538d18d2241285b68ed287ccd87c Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 15 Jun 2016 16:38:37 +0600 Subject: CLOUD: Add LocalWebserver Available as LocalServer singleton. It's being started and stopped by StorageWizardDialog. It doesn't handle clients yet, though. --- backends/cloud/cloudmanager.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 8b104dfb20..96521178ed 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -253,17 +253,8 @@ SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networ } void CloudManager::testFeature() { - Storage *storage = getCurrentStorage(); + //Storage *storage = getCurrentStorage(); //if (storage) storage->info(nullptr, nullptr); - GoogleDrive::GoogleDriveStorage *gd = dynamic_cast(storage); - if (gd) { - } - //gd->resolveFileId("firstfolder/subfolder", nullptr, nullptr); - //gd->listDirectoryById("appDataFolder", nullptr, nullptr); - //gd->listDirectoryById("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", nullptr, nullptr); - //gd->createDirectoryWithParentId("1LWq-r1IwegkJJ0eZpswGlyjj8nu6XyUmosvxD7L0F9X3", "subfolder", nullptr, nullptr); - //gd->createDirectoryWithParentId("appDataFolder", "firstfolder", nullptr, nullptr); - else debug("FAILURE"); } bool CloudManager::isWorking() { -- cgit v1.2.3 From 1addefad7e29ff674828c6dad5330c87a4203f29 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 18 Jun 2016 14:25:55 +0600 Subject: CLOUD: Use correct redirect_uris Usage of #ifdef there (and in StorageWizardDialog) means that ScummVM doesn't support both local webserver and scummvm.org paths at the same time. It's either built with SDL_net (thus supporting localhost path) or without it (thus using scummvm.org). --- backends/cloud/dropbox/dropboxstorage.cpp | 4 ++++ backends/cloud/googledrive/googledrivestorage.cpp | 6 +++++- backends/cloud/onedrive/onedrivestorage.cpp | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 64425812db..3cf14d5e0b 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -67,7 +67,11 @@ void DropboxStorage::getAccessToken(Common::String code) { request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); +#ifdef USE_SDL_NET request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); +#else + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); +#endif addRequest(request); } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 6d0a152938..df29a87eec 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -87,7 +87,11 @@ void GoogleDriveStorage::getAccessToken(BoolCallback callback, Common::String co } request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost"); +#ifdef USE_SDL_NET + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); +#else + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); +#endif addRequest(request); } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 5c230366a8..0d2f91c3a8 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -83,7 +83,11 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) } request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); +#ifdef USE_SDL_NET request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); +#else + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); +#endif addRequest(request); } -- cgit v1.2.3 From b908b286b9767ff7a0207ce9414279ce5291762c Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 18 Jun 2016 14:34:43 +0600 Subject: CLOUD: Fix "signed/unsigned integers" warning The "comparison between signed and unsigned integer expressions" one. Note that in UploadRequests size() and pos() are acutally signed, because they could return -1. This commit implies that Requests are working with such Streams which doesn't. --- backends/cloud/dropbox/dropboxuploadrequest.cpp | 4 ++-- backends/cloud/onedrive/onedriveuploadrequest.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index 5765892a70..f1fb818d36 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -69,7 +69,7 @@ void DropboxUploadRequest::uploadNextPart() { Common::JSONObject jsonRequestParameters; if (_contentsStream->pos() == 0 || _sessionId == "") { - if (_contentsStream->size() <= UPLOAD_PER_ONE_REQUEST) { + if ((uint32)_contentsStream->size() <= UPLOAD_PER_ONE_REQUEST) { url = "https://content.dropboxapi.com/2/files/upload"; jsonRequestParameters.setVal("path", new Common::JSONValue(_savePath)); jsonRequestParameters.setVal("mode", new Common::JSONValue("overwrite")); @@ -80,7 +80,7 @@ void DropboxUploadRequest::uploadNextPart() { jsonRequestParameters.setVal("close", new Common::JSONValue(false)); } } else { - if (_contentsStream->size() - _contentsStream->pos() <= UPLOAD_PER_ONE_REQUEST) { + if ((uint32)(_contentsStream->size() - _contentsStream->pos()) <= UPLOAD_PER_ONE_REQUEST) { url += "finish"; Common::JSONObject jsonCursor, jsonCommit; jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId)); diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index bc54a811a9..08f45935d2 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -62,7 +62,7 @@ void OneDriveUploadRequest::start() { void OneDriveUploadRequest::uploadNextPart() { const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; - if (_uploadUrl == "" && _contentsStream->size() > UPLOAD_PER_ONE_REQUEST) { + if (_uploadUrl == "" && (uint32)_contentsStream->size() > UPLOAD_PER_ONE_REQUEST) { Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+ConnMan.urlEncode(_savePath)+":/upload.createSession"; //folder must exist Networking::JsonCallback callback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedErrorCallback); -- cgit v1.2.3 From 39eb76f8c2ea62520c29e76ee10d97c2a13f0f42 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 18 Jun 2016 14:39:34 +0600 Subject: CLOUD: Fix "zero-length format string" warning --- backends/cloud/googledrive/googledrivestorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index df29a87eec..327c9ee8eb 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -264,7 +264,7 @@ void GoogleDriveStorage::printFiles(FileArrayResponse response) { debug("\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); debug("\t%s", files[i].path().c_str()); debug("\t%s", files[i].id().c_str()); - debug(""); + debug(" "); } } -- cgit v1.2.3 From 65e87c6c70fc1e5af8f0c3fb762ca13e6aa6a8e4 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 18 Jun 2016 19:35:57 +0600 Subject: CLOUD: Update save's timestamp on rewrite This commit moves save/load timestamps static methods into DefaultSaveFileManager and fixes a few related bugs. --- backends/cloud/savessyncrequest.cpp | 133 ++++++------------------------------ backends/cloud/savessyncrequest.h | 8 +-- 2 files changed, 20 insertions(+), 121 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index f059e29a8d..4d18647911 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -29,11 +29,10 @@ #include "common/savefile.h" #include "common/system.h" #include "gui/saveload-dialog.h" +#include namespace Cloud { -const char *SavesSyncRequest::TIMESTAMPS_FILENAME = "timestamps"; - SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb): Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _boolCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { @@ -59,7 +58,7 @@ void SavesSyncRequest::start() { _ignoreCallback = false; //load timestamps - loadTimestamps(); + _localFilesTimestamps = DefaultSaveFileManager::loadTimestamps(); //list saves directory Common::String dir = _storage->savesDirectoryPath(); @@ -90,25 +89,23 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re StorageFile &file = remoteFiles[i]; if (file.isDirectory()) continue; totalSize += file.size(); - if (file.name() == TIMESTAMPS_FILENAME) continue; + if (file.name() == DefaultSaveFileManager::TIMESTAMPS_FILENAME) continue; Common::String name = file.name(); if (!_localFilesTimestamps.contains(name)) _filesToDownload.push_back(file); else { localFileNotAvailableInCloud[name] = false; - - if (_localFilesTimestamps[name] != INVALID_TIMESTAMP) { - if (_localFilesTimestamps[name] == file.timestamp()) - continue; - - //we actually can have some files not only with timestamp < remote - //but also with timestamp > remote (when we have been using ANOTHER CLOUD and then switched back) - if (_localFilesTimestamps[name] < file.timestamp()) - _filesToDownload.push_back(file); - else - _filesToUpload.push_back(file.name()); - } + + if (_localFilesTimestamps[name] == file.timestamp()) + continue; + + //we actually can have some files not only with timestamp < remote + //but also with timestamp > remote (when we have been using ANOTHER CLOUD and then switched back) + if (_localFilesTimestamps[name] > file.timestamp() || _localFilesTimestamps[name] == DefaultSaveFileManager::INVALID_TIMESTAMP) + _filesToUpload.push_back(file.name()); + else + _filesToDownload.push_back(file); } } @@ -116,7 +113,7 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re //upload files which are unavailable in cloud for (Common::HashMap::iterator i = localFileNotAvailableInCloud.begin(); i != localFileNotAvailableInCloud.end(); ++i) { - if (i->_key == TIMESTAMPS_FILENAME) continue; + if (i->_key == DefaultSaveFileManager::TIMESTAMPS_FILENAME) continue; if (i->_value) _filesToUpload.push_back(i->_key); } @@ -234,7 +231,7 @@ void SavesSyncRequest::downloadNextFile() { /////// debug("downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); /////// - _workingRequest = _storage->downloadById(_currentDownloadingFile.id(), concatWithSavesPath(_currentDownloadingFile.name()), + _workingRequest = _storage->downloadById(_currentDownloadingFile.id(), DefaultSaveFileManager::concatWithSavesPath(_currentDownloadingFile.name()), new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), new Common::Callback(this, &SavesSyncRequest::fileDownloadedErrorCallback) ); @@ -252,7 +249,9 @@ void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse response) { } //update local timestamp for downloaded file + _localFilesTimestamps = DefaultSaveFileManager::loadTimestamps(); _localFilesTimestamps[_currentDownloadingFile.name()] = _currentDownloadingFile.timestamp(); + DefaultSaveFileManager::saveTimestamps(_localFilesTimestamps); //continue downloading files downloadNextFile(); @@ -290,7 +289,9 @@ void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse response) { if (_ignoreCallback) return; //update local timestamp for the uploaded file + _localFilesTimestamps = DefaultSaveFileManager::loadTimestamps(); _localFilesTimestamps[_currentUploadingFile] = response.value.timestamp(); + DefaultSaveFileManager::saveTimestamps(_localFilesTimestamps); //continue uploading files uploadNextFile(); @@ -342,112 +343,16 @@ Common::Array SavesSyncRequest::getFilesToDownload() { void SavesSyncRequest::finishError(Networking::ErrorResponse error) { debug("SavesSync::finishError"); - //save updated timestamps (even if Request failed, there would be only valid timestamps) - saveTimestamps(); - Request::finishError(error); } void SavesSyncRequest::finishSuccess(bool success) { Request::finishSuccess(); - //save updated timestamps (even if Request failed, there would be only valid timestamps) - saveTimestamps(); - //update last successful sync date CloudMan.setStorageLastSync(CloudMan.getStorageIndex(), _date); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } -void SavesSyncRequest::loadTimestamps() { - //refresh the files list - Common::Array files; - g_system->getSavefileManager()->updateSavefilesList(files); - - //start with listing all the files in saves/ directory and setting invalid timestamp to them - Common::StringArray localFiles = g_system->getSavefileManager()->listSavefiles("*"); - for (uint32 i = 0; i < localFiles.size(); ++i) - _localFilesTimestamps[localFiles[i]] = INVALID_TIMESTAMP; - - //now actually load timestamps from file - Common::InSaveFile *file = g_system->getSavefileManager()->openRawFile(TIMESTAMPS_FILENAME); - if (!file) { - warning("SavesSyncRequest: failed to open '%s' file to load timestamps", TIMESTAMPS_FILENAME); - return; - } - - while (!file->eos()) { - //read filename into buffer (reading until the first ' ') - Common::String buffer; - while (!file->eos()) { - byte b = file->readByte(); - if (b == ' ') break; - buffer += (char)b; - } - - //read timestamp info buffer (reading until ' ' or some line ending char) - Common::String filename = buffer; - bool lineEnded = false; - buffer = ""; - while (!file->eos()) { - byte b = file->readByte(); - if (b == ' ' || b == '\n' || b == '\r') { - lineEnded = (b == '\n'); - break; - } - buffer += (char)b; - } - - //parse timestamp - uint timestamp = atol(buffer.c_str()); - if (buffer == "" || timestamp == 0) break; - _localFilesTimestamps[filename] = timestamp; - - //read until the end of the line - if (!lineEnded) { - while (!file->eos()) { - byte b = file->readByte(); - if (b == '\n') break; - } - } - } - - delete file; -} - -void SavesSyncRequest::saveTimestamps() { - Common::DumpFile f; - Common::String filename = concatWithSavesPath(TIMESTAMPS_FILENAME); - if (!f.open(filename, true)) { - warning("SavesSyncRequest: failed to open '%s' file to save timestamps", filename.c_str()); - return; - } - - for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { - Common::String data = i->_key + Common::String::format(" %u\n", i->_value); - if (f.write(data.c_str(), data.size()) != data.size()) { - warning("SavesSyncRequest: failed to write timestamps data into '%s'", filename.c_str()); - return; - } - } - - f.close(); -} - -Common::String SavesSyncRequest::concatWithSavesPath(Common::String name) { - Common::String path = ConfMan.get("savepath"); - if (path.size() > 0 && (path.lastChar() == '/' || path.lastChar() == '\\')) - return path + name; - - //simple heuristic to determine which path separator to use - int backslashes = 0; - for (uint32 i = 0; i < path.size(); ++i) - if (path[i] == '/') --backslashes; - else if (path[i] == '\\') ++backslashes; - - if (backslashes) return path + '\\' + name; - return path + '/' + name; -} - } // End of namespace Cloud diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 105d7f7f65..19e67d9dd8 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -28,14 +28,10 @@ #include "common/hashmap.h" #include "common/hash-str.h" #include "gui/object.h" -#include namespace Cloud { class SavesSyncRequest: public Networking::Request, public GUI::CommandSender { - const uint32 INVALID_TIMESTAMP = UINT_MAX; - static const char *TIMESTAMPS_FILENAME; - Storage *_storage; Storage::BoolCallback _boolCallback; Common::HashMap _localFilesTimestamps; @@ -61,9 +57,7 @@ class SavesSyncRequest: public Networking::Request, public GUI::CommandSender { void uploadNextFile(); virtual void finishError(Networking::ErrorResponse error); void finishSuccess(bool success); - void loadTimestamps(); - void saveTimestamps(); - Common::String concatWithSavesPath(Common::String name); + public: SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb); virtual ~SavesSyncRequest(); -- cgit v1.2.3 From 4c381dafa3aff9feeb80e1be3272eba8ca73d442 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sun, 19 Jun 2016 13:50:11 +0600 Subject: CLOUD: Delete the incomplete file (when downloading) --- backends/cloud/downloadrequest.cpp | 5 +++++ backends/cloud/downloadrequest.h | 2 ++ backends/cloud/savessyncrequest.cpp | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 307ea00aa2..497509b4a9 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -118,4 +118,9 @@ void DownloadRequest::finishSuccess(bool success) { if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } +void DownloadRequest::finishError(Networking::ErrorResponse error) { + if (_localFile) _localFile->close(); + Request::finishError(error); +} + } // End of namespace Cloud diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index def69d47de..ff7820e3ee 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -43,6 +43,8 @@ class DownloadRequest: public Networking::Request { void streamCallback(Networking::NetworkReadStreamResponse response); void streamErrorCallback(Networking::ErrorResponse error); void finishSuccess(bool success); + virtual void finishError(Networking::ErrorResponse error); + public: DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFileId, Common::DumpFile *dumpFile); virtual ~DownloadRequest(); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 4d18647911..c43625315d 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -244,6 +244,8 @@ void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse response) { //stop syncing if download failed if (!response.value) { + //delete the incomplete file + g_system->getSavefileManager()->removeSavefile(_currentDownloadingFile.name()); finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; } @@ -342,7 +344,20 @@ Common::Array SavesSyncRequest::getFilesToDownload() { void SavesSyncRequest::finishError(Networking::ErrorResponse error) { debug("SavesSync::finishError"); - + //if we were downloading a file - remember the name + //and make the Request close() it, so we can delete it + Common::String name = _currentDownloadingFile.name(); + if (_workingRequest) { + _ignoreCallback = true; + _workingRequest->finish(); + _workingRequest = nullptr; + _ignoreCallback = false; + } + //unlock all the files by making getFilesToDownload() return empty array + _currentDownloadingFile = StorageFile(); + _filesToDownload.clear(); + //delete the incomplete file + if (name != "") g_system->getSavefileManager()->removeSavefile(name); Request::finishError(error); } -- cgit v1.2.3 From fa3ea83165d6c378348f61f8daec85f805626dbe Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 21 Jun 2016 16:58:09 +0600 Subject: CLOUD: Fix some warnings Mostly on format string --- backends/cloud/cloudmanager.cpp | 4 ++-- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- backends/cloud/googledrive/googledriveuploadrequest.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 96521178ed..b9de6d48ab 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -109,10 +109,10 @@ void CloudManager::save() { Common::String name = getStorageConfigName(i); ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username, ConfMan.kCloudDomain); ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate, ConfMan.kCloudDomain); - ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes, ConfMan.kCloudDomain)); + ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes), ConfMan.kCloudDomain); } - ConfMan.set("current_storage", Common::String::format("%d", _currentStorageIndex, ConfMan.kCloudDomain)); + ConfMan.set("current_storage", Common::String::format("%u", _currentStorageIndex), ConfMan.kCloudDomain); if (_activeStorage) _activeStorage->saveConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); ConfMan.flushToDisk(); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 3cf14d5e0b..6d73e52c43 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -80,7 +80,7 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { if (json) { Common::JSONObject result = json->asObject(); if (!result.contains("access_token") || !result.contains("uid")) { - warning(json->stringify(true).c_str()); + warning("%s", json->stringify(true).c_str()); warning("Bad response, no token/uid passed"); } else { _token = result.getVal("access_token")->asString(); diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index ce1fae2579..b24e02edbf 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -189,7 +189,7 @@ void GoogleDriveUploadRequest::uploadNextPart() { uint32 oldPos = _contentsStream->pos(); if (oldPos != _serverReceivedBytes) { if (!_contentsStream->seek(_serverReceivedBytes)) { - warning("GoogleDriveUploadRequest: cannot upload because stream couldn't seek(%u)", _serverReceivedBytes); + warning("GoogleDriveUploadRequest: cannot upload because stream couldn't seek(%lu)", _serverReceivedBytes); finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; } -- 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/downloadrequest.cpp | 4 ++-- backends/cloud/downloadrequest.h | 2 +- backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp | 4 ++-- backends/cloud/dropbox/dropboxcreatedirectoryrequest.h | 2 +- backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 ++-- backends/cloud/dropbox/dropboxlistdirectoryrequest.h | 2 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 6 +++--- backends/cloud/dropbox/dropboxuploadrequest.h | 2 +- backends/cloud/folderdownloadrequest.cpp | 4 ++-- backends/cloud/folderdownloadrequest.h | 2 +- backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp | 6 +++--- backends/cloud/googledrive/googledrivecreatedirectoryrequest.h | 2 +- backends/cloud/googledrive/googledrivedownloadrequest.cpp | 4 ++-- backends/cloud/googledrive/googledrivedownloadrequest.h | 2 +- backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp | 4 ++-- backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h | 2 +- backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp | 4 ++-- backends/cloud/googledrive/googledrivelistdirectoryrequest.h | 2 +- backends/cloud/googledrive/googledrivetokenrefresher.cpp | 6 +++--- backends/cloud/googledrive/googledrivetokenrefresher.h | 2 +- backends/cloud/googledrive/googledriveuploadrequest.cpp | 6 +++--- backends/cloud/googledrive/googledriveuploadrequest.h | 2 +- backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp | 4 ++-- backends/cloud/onedrive/onedrivecreatedirectoryrequest.h | 2 +- backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp | 4 ++-- backends/cloud/onedrive/onedrivelistdirectoryrequest.h | 2 +- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 6 +++--- backends/cloud/onedrive/onedrivetokenrefresher.h | 2 +- backends/cloud/onedrive/onedriveuploadrequest.cpp | 6 +++--- backends/cloud/onedrive/onedriveuploadrequest.h | 2 +- backends/cloud/savessyncrequest.cpp | 4 ++-- backends/cloud/savessyncrequest.h | 2 +- 32 files changed, 54 insertions(+), 54 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 497509b4a9..c95b8b81af 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -101,7 +101,7 @@ void DownloadRequest::handle() { //TODO: do something about it actually } - finishSuccess(_remoteFileStream->httpResponseCode() == 200); + finishDownload(_remoteFileStream->httpResponseCode() == 200); _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() } @@ -113,7 +113,7 @@ void DownloadRequest::restart() { //start(); } -void DownloadRequest::finishSuccess(bool success) { +void DownloadRequest::finishDownload(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index ff7820e3ee..d8e18f9171 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -42,7 +42,7 @@ class DownloadRequest: public Networking::Request { void start(); void streamCallback(Networking::NetworkReadStreamResponse response); void streamErrorCallback(Networking::ErrorResponse error); - void finishSuccess(bool success); + void finishDownload(bool success); virtual void finishError(Networking::ErrorResponse error); public: diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index 61cc9ddfcd..a52d41e896 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -82,7 +82,7 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re } Common::JSONObject info = json->asObject(); - if (info.contains("id")) finishSuccess(true); + if (info.contains("id")) finishCreation(true); else { error.response = json->stringify(true); finishError(error); @@ -104,7 +104,7 @@ void DropboxCreateDirectoryRequest::restart() { start(); } Common::String DropboxCreateDirectoryRequest::date() const { return _date; } -void DropboxCreateDirectoryRequest::finishSuccess(bool success) { +void DropboxCreateDirectoryRequest::finishCreation(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h index e8599c7df9..4bdc6dbee6 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h @@ -41,7 +41,7 @@ class DropboxCreateDirectoryRequest: public Networking::Request { void start(); void responseCallback(Networking::JsonResponse response); void errorCallback(Networking::ErrorResponse error); - void finishSuccess(bool success); + void finishCreation(bool success); public: DropboxCreateDirectoryRequest(Common::String token, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb); virtual ~DropboxCreateDirectoryRequest(); 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)); } diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 0d96edd1e6..62dde71f76 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -45,7 +45,7 @@ class DropboxListDirectoryRequest: public Networking::Request { void start(); void responseCallback(Networking::JsonResponse response); void errorCallback(Networking::ErrorResponse error); - void finishSuccess(Common::Array &files); + void finishListing(Common::Array &files); public: DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); virtual ~DropboxListDirectoryRequest(); diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index f1fb818d36..e530502413 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -148,7 +148,7 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons Common::String path = object.getVal("path_lower")->asString(); uint32 size = object.getVal("size")->asIntegerNumber(); uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("server_modified")->asString()); - finishSuccess(StorageFile(path, size, timestamp, false)); + finishUpload(StorageFile(path, size, timestamp, false)); return; } @@ -163,7 +163,7 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { warning("no file info to return"); - finishSuccess(StorageFile(_savePath, 0, 0, false)); + finishUpload(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } @@ -186,7 +186,7 @@ void DropboxUploadRequest::handle() {} void DropboxUploadRequest::restart() { start(); } -void DropboxUploadRequest::finishSuccess(StorageFile file) { +void DropboxUploadRequest::finishUpload(StorageFile file) { Request::finishSuccess(); if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); } diff --git a/backends/cloud/dropbox/dropboxuploadrequest.h b/backends/cloud/dropbox/dropboxuploadrequest.h index a85d7ef883..8d9a3e2650 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.h +++ b/backends/cloud/dropbox/dropboxuploadrequest.h @@ -44,7 +44,7 @@ class DropboxUploadRequest: public Networking::Request { void uploadNextPart(); void partUploadedCallback(Networking::JsonResponse response); void partUploadedErrorCallback(Networking::ErrorResponse error); - void finishSuccess(StorageFile status); + void finishUpload(StorageFile status); public: DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb); diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 905b0c79f4..83296c3d15 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -83,7 +83,7 @@ void FolderDownloadRequest::fileDownloadedErrorCallback(Networking::ErrorRespons void FolderDownloadRequest::downloadNextFile() { do { if (_files.empty()) { - finishSuccess(_failedFiles); + finishDownload(_failedFiles); return; } @@ -120,7 +120,7 @@ void FolderDownloadRequest::handle() {} void FolderDownloadRequest::restart() { start(); } -void FolderDownloadRequest::finishSuccess(Common::Array &files) { +void FolderDownloadRequest::finishDownload(Common::Array &files) { Request::finishSuccess(); if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); } diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 8fa3b1188b..bf55567b2d 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -45,7 +45,7 @@ class FolderDownloadRequest: public Networking::Request { void fileDownloadedCallback(Storage::BoolResponse response); void fileDownloadedErrorCallback(Networking::ErrorResponse error); void downloadNextFile(); - void finishSuccess(Common::Array &files); + void finishDownload(Common::Array &files); public: FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive); virtual ~FolderDownloadRequest(); diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp index 2b7a805bb9..9e339fd999 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp @@ -90,7 +90,7 @@ void GoogleDriveCreateDirectoryRequest::idResolvedCallback(Storage::UploadRespon if (response.request) _date = response.request->date(); //resolved => folder already exists - finishSuccess(false); + finishCreation(false); } void GoogleDriveCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse error) { @@ -121,7 +121,7 @@ void GoogleDriveCreateDirectoryRequest::createdDirectoryCallback(Storage::BoolRe _workingRequest = nullptr; if (_ignoreCallback) return; if (response.request) _date = response.request->date(); - finishSuccess(response.value); + finishCreation(response.value); } void GoogleDriveCreateDirectoryRequest::createdDirectoryErrorCallback(Networking::ErrorResponse error) { @@ -137,7 +137,7 @@ void GoogleDriveCreateDirectoryRequest::restart() { start(); } Common::String GoogleDriveCreateDirectoryRequest::date() const { return _date; } -void GoogleDriveCreateDirectoryRequest::finishSuccess(bool success) { +void GoogleDriveCreateDirectoryRequest::finishCreation(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h index f71afeb888..7a6ffaca1b 100644 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h +++ b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h @@ -49,7 +49,7 @@ class GoogleDriveCreateDirectoryRequest: public Networking::Request { void idResolveFailedCallback(Networking::ErrorResponse error); void createdDirectoryCallback(Storage::BoolResponse response); void createdDirectoryErrorCallback(Networking::ErrorResponse error); - void finishSuccess(bool success); + void finishCreation(bool success); public: GoogleDriveCreateDirectoryRequest(GoogleDriveStorage *storage, Common::String parentPath, Common::String directoryName, Storage::BoolCallback cb, Networking::ErrorCallback ecb); virtual ~GoogleDriveCreateDirectoryRequest(); diff --git a/backends/cloud/googledrive/googledrivedownloadrequest.cpp b/backends/cloud/googledrive/googledrivedownloadrequest.cpp index c885352fae..df28c8b27f 100644 --- a/backends/cloud/googledrive/googledrivedownloadrequest.cpp +++ b/backends/cloud/googledrive/googledrivedownloadrequest.cpp @@ -69,7 +69,7 @@ void GoogleDriveDownloadRequest::idResolveFailedCallback(Networking::ErrorRespon void GoogleDriveDownloadRequest::downloadCallback(Storage::BoolResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - finishSuccess(response.value); + finishDownload(response.value); } void GoogleDriveDownloadRequest::downloadErrorCallback(Networking::ErrorResponse error) { @@ -82,7 +82,7 @@ void GoogleDriveDownloadRequest::handle() {} void GoogleDriveDownloadRequest::restart() { start(); } -void GoogleDriveDownloadRequest::finishSuccess(bool success) { +void GoogleDriveDownloadRequest::finishDownload(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } diff --git a/backends/cloud/googledrive/googledrivedownloadrequest.h b/backends/cloud/googledrive/googledrivedownloadrequest.h index 89bd313467..202a393d7a 100644 --- a/backends/cloud/googledrive/googledrivedownloadrequest.h +++ b/backends/cloud/googledrive/googledrivedownloadrequest.h @@ -44,7 +44,7 @@ class GoogleDriveDownloadRequest: public Networking::Request { void idResolveFailedCallback(Networking::ErrorResponse error); void downloadCallback(Storage::BoolResponse response); void downloadErrorCallback(Networking::ErrorResponse error); - void finishSuccess(bool success); + void finishDownload(bool success); public: GoogleDriveDownloadRequest(GoogleDriveStorage *storage, Common::String remotePath, Common::String localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb); virtual ~GoogleDriveDownloadRequest(); diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 2530bab557..582f67c2cf 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -118,7 +118,7 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo Common::String token = responseObject.getVal("nextPageToken")->asString(); makeRequest(token); } else { - finishSuccess(_files); + finishListing(_files); } } else { warning("null, not json"); @@ -142,7 +142,7 @@ void GoogleDriveListDirectoryByIdRequest::restart() { start(); } Common::String GoogleDriveListDirectoryByIdRequest::date() const { return _date; } -void GoogleDriveListDirectoryByIdRequest::finishSuccess(Common::Array &files) { +void GoogleDriveListDirectoryByIdRequest::finishListing(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h index ceb533e635..ecde880323 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h @@ -47,7 +47,7 @@ class GoogleDriveListDirectoryByIdRequest: public Networking::Request { void makeRequest(Common::String pageToken); void responseCallback(Networking::JsonResponse response); void errorCallback(Networking::ErrorResponse error); - void finishSuccess(Common::Array &files); + void finishListing(Common::Array &files); public: GoogleDriveListDirectoryByIdRequest(GoogleDriveStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb); virtual ~GoogleDriveListDirectoryByIdRequest(); diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp index 3387b43418..f645041eb3 100644 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp @@ -75,7 +75,7 @@ void GoogleDriveListDirectoryRequest::idResolveErrorCallback(Networking::ErrorRe void GoogleDriveListDirectoryRequest::listNextDirectory() { if (_directoriesQueue.empty()) { - finishSuccess(_files); + finishListing(_files); return; } @@ -120,7 +120,7 @@ void GoogleDriveListDirectoryRequest::restart() { start(); } Common::String GoogleDriveListDirectoryRequest::date() const { return _date; } -void GoogleDriveListDirectoryRequest::finishSuccess(Common::Array &files) { +void GoogleDriveListDirectoryRequest::finishListing(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h index b3d8ff6c93..d76338b7fc 100644 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h +++ b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h @@ -51,7 +51,7 @@ class GoogleDriveListDirectoryRequest: public Networking::Request { void listNextDirectory(); void listedDirectoryCallback(Storage::FileArrayResponse response); void listedDirectoryErrorCallback(Networking::ErrorResponse error); - void finishSuccess(Common::Array &files); + void finishListing(Common::Array &files); public: GoogleDriveListDirectoryRequest(GoogleDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); virtual ~GoogleDriveListDirectoryRequest(); diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp index 3fae830105..3dfb8436e9 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.cpp +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -56,10 +56,10 @@ void GoogleDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { retry(0); } -void GoogleDriveTokenRefresher::finishSuccess(Common::JSONValue *json) { +void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (!json) { //that's probably not an error (200 OK) - CurlJsonRequest::finishSuccess(nullptr); + CurlJsonRequest::finishJson(nullptr); return; } @@ -101,7 +101,7 @@ void GoogleDriveTokenRefresher::finishSuccess(Common::JSONValue *json) { } //notify user of success - CurlJsonRequest::finishSuccess(json); + CurlJsonRequest::finishJson(json); } void GoogleDriveTokenRefresher::setHeaders(Common::Array &headers) { diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.h b/backends/cloud/googledrive/googledrivetokenrefresher.h index 3dcb56bde6..3bc5fbd784 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.h +++ b/backends/cloud/googledrive/googledrivetokenrefresher.h @@ -37,7 +37,7 @@ class GoogleDriveTokenRefresher: public Networking::CurlJsonRequest { void tokenRefreshed(Storage::BoolResponse response); - virtual void finishSuccess(Common::JSONValue *json); + virtual void finishJson(Common::JSONValue *json); public: GoogleDriveTokenRefresher(GoogleDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); virtual ~GoogleDriveTokenRefresher(); diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index b24e02edbf..d9ba2815e0 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -279,14 +279,14 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res timestamp = ISO8601::convertToTimestamp(object.getVal("modifiedTime")->asString()); //as we list directory by id, we can't determine full path for the file, so we leave it empty - finishSuccess(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); + finishUpload(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); return; } } if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { warning("no file info to return"); - finishSuccess(StorageFile(_savePath, 0, 0, false)); + finishUpload(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } @@ -320,7 +320,7 @@ void GoogleDriveUploadRequest::handle() {} void GoogleDriveUploadRequest::restart() { start(); } -void GoogleDriveUploadRequest::finishSuccess(StorageFile file) { +void GoogleDriveUploadRequest::finishUpload(StorageFile file) { Request::finishSuccess(); if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); } diff --git a/backends/cloud/googledrive/googledriveuploadrequest.h b/backends/cloud/googledrive/googledriveuploadrequest.h index e417403542..8cc40795e9 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.h +++ b/backends/cloud/googledrive/googledriveuploadrequest.h @@ -54,7 +54,7 @@ class GoogleDriveUploadRequest: public Networking::Request { void partUploadedCallback(Networking::JsonResponse response); void partUploadedErrorCallback(Networking::ErrorResponse error); bool handleHttp308(const Networking::NetworkReadStream *stream); - void finishSuccess(StorageFile status); + void finishUpload(StorageFile status); public: GoogleDriveUploadRequest(GoogleDriveStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb); diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index 2c644c42c5..617346529b 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -101,7 +101,7 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r } Common::JSONObject info = json->asObject(); - if (info.contains("id")) finishSuccess(true); + if (info.contains("id")) finishCreation(true); else { error.response = json->stringify(true); finishError(error); @@ -123,7 +123,7 @@ void OneDriveCreateDirectoryRequest::restart() { start(); } Common::String OneDriveCreateDirectoryRequest::date() const { return _date; } -void OneDriveCreateDirectoryRequest::finishSuccess(bool success) { +void OneDriveCreateDirectoryRequest::finishCreation(bool success) { Request::finishSuccess(); if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h index 880e94e8db..83c72c4e0a 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h @@ -43,7 +43,7 @@ class OneDriveCreateDirectoryRequest: public Networking::Request { void start(); void responseCallback(Networking::JsonResponse response); void errorCallback(Networking::ErrorResponse error); - void finishSuccess(bool success); + void finishCreation(bool success); public: OneDriveCreateDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb); virtual ~OneDriveCreateDirectoryRequest(); diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index be6fcb70e7..baccdf418e 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -60,7 +60,7 @@ void OneDriveListDirectoryRequest::start() { void OneDriveListDirectoryRequest::listNextDirectory() { if (_directoriesQueue.empty()) { - finishSuccess(_files); + finishListing(_files); return; } @@ -150,7 +150,7 @@ void OneDriveListDirectoryRequest::restart() { start(); } Common::String OneDriveListDirectoryRequest::date() const { return _date; } -void OneDriveListDirectoryRequest::finishSuccess(Common::Array &files) { +void OneDriveListDirectoryRequest::finishListing(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h index 5e80f4f561..eb510ab257 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.h @@ -50,7 +50,7 @@ class OneDriveListDirectoryRequest: public Networking::Request { void listedDirectoryCallback(Networking::JsonResponse response); void listedDirectoryErrorCallback(Networking::ErrorResponse error); void makeRequest(Common::String url); - void finishSuccess(Common::Array &files); + void finishListing(Common::Array &files); public: OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); virtual ~OneDriveListDirectoryRequest(); diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index bf849f7964..04e155c084 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -56,10 +56,10 @@ void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { retry(0); } -void OneDriveTokenRefresher::finishSuccess(Common::JSONValue *json) { +void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (!json) { //that's probably not an error (200 OK) - CurlJsonRequest::finishSuccess(nullptr); + CurlJsonRequest::finishJson(nullptr); return; } @@ -105,7 +105,7 @@ void OneDriveTokenRefresher::finishSuccess(Common::JSONValue *json) { } //notify user of success - CurlJsonRequest::finishSuccess(json); + CurlJsonRequest::finishJson(json); } void OneDriveTokenRefresher::setHeaders(Common::Array &headers) { diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h index 04b0bf26b8..4be1fa726b 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.h +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -37,7 +37,7 @@ class OneDriveTokenRefresher: public Networking::CurlJsonRequest { void tokenRefreshed(Storage::BoolResponse response); - virtual void finishSuccess(Common::JSONValue *json); + virtual void finishJson(Common::JSONValue *json); public: OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); virtual ~OneDriveTokenRefresher(); diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 08f45935d2..fb32443a27 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -126,7 +126,7 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon 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)); + finishUpload(StorageFile(path, size, timestamp, false)); return; } @@ -140,7 +140,7 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { warning("no file info to return"); - finishSuccess(StorageFile(_savePath, 0, 0, false)); + finishUpload(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } @@ -162,7 +162,7 @@ void OneDriveUploadRequest::handle() {} void OneDriveUploadRequest::restart() { start(); } -void OneDriveUploadRequest::finishSuccess(StorageFile file) { +void OneDriveUploadRequest::finishUpload(StorageFile file) { Request::finishSuccess(); if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); } diff --git a/backends/cloud/onedrive/onedriveuploadrequest.h b/backends/cloud/onedrive/onedriveuploadrequest.h index 09419d8a15..f613c415e1 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.h +++ b/backends/cloud/onedrive/onedriveuploadrequest.h @@ -45,7 +45,7 @@ class OneDriveUploadRequest: public Networking::Request { void uploadNextPart(); void partUploadedCallback(Networking::JsonResponse response); void partUploadedErrorCallback(Networking::ErrorResponse error); - void finishSuccess(StorageFile status); + void finishUpload(StorageFile status); public: OneDriveUploadRequest(OneDriveStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index c43625315d..e12f5af7cc 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -269,7 +269,7 @@ void SavesSyncRequest::fileDownloadedErrorCallback(Networking::ErrorResponse err void SavesSyncRequest::uploadNextFile() { if (_filesToUpload.empty()) { - finishSuccess(true); + finishSync(true); return; } @@ -361,7 +361,7 @@ void SavesSyncRequest::finishError(Networking::ErrorResponse error) { Request::finishError(error); } -void SavesSyncRequest::finishSuccess(bool success) { +void SavesSyncRequest::finishSync(bool success) { Request::finishSuccess(); //update last successful sync date diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 19e67d9dd8..d1a9d4a44c 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -56,7 +56,7 @@ class SavesSyncRequest: public Networking::Request, public GUI::CommandSender { void downloadNextFile(); void uploadNextFile(); virtual void finishError(Networking::ErrorResponse error); - void finishSuccess(bool success); + void finishSync(bool success); public: SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb); -- cgit v1.2.3 From a37c63998671ad8a341e1b88aead758f408e5fc2 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 4 Jul 2016 13:40:32 +0600 Subject: CLOUD: Make Google Drive sort files list GoogleDriveListDirectoryByIdRequest now uses "orderBy" field to specify that we want the commonly used "alphabetical, folders first" order. That's mostly needed for RemoteBrowserDialog, because Requests don't care about the order, and this one is more user-friendly. --- backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 582f67c2cf..36bc390da0 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -55,7 +55,7 @@ void GoogleDriveListDirectoryByIdRequest::start() { } void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) { - Common::String url = "https://www.googleapis.com/drive/v3/files?spaces=drive&fields=files%28id,mimeType,modifiedTime,name,size%29,nextPageToken"; + Common::String url = "https://www.googleapis.com/drive/v3/files?spaces=drive&fields=files%28id,mimeType,modifiedTime,name,size%29,nextPageToken&orderBy=folder,name"; //files(id,mimeType,modifiedTime,name,size),nextPageToken if (pageToken != "") url += "&pageToken=" + pageToken; url += "&q=%27" + _requestedId + "%27+in+parents"; -- cgit v1.2.3 From dc0a95617227c2a2489150aec69ec0c464cd30de Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 4 Jul 2016 15:11:07 +0600 Subject: CLOUD: Add CloudManager::downloadFolder() --- backends/cloud/cloudmanager.cpp | 11 +++++++++++ backends/cloud/cloudmanager.h | 3 +++ 2 files changed, 14 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index b9de6d48ab..0a5006ccef 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -226,6 +226,17 @@ Networking::Request *CloudManager::listDirectory(Common::String path, Storage::L return nullptr; } +Networking::Request *CloudManager::downloadFolder(Common::String remotePath, Common::String localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + Storage *storage = getCurrentStorage(); + if (storage) storage->downloadFolder(remotePath, localPath, callback, errorCallback, recursive); + else { + delete callback; + delete errorCallback; + //TODO: should we call errorCallback? + } + return nullptr; +} + Networking::Request *CloudManager::info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); if (storage) storage->info(callback, errorCallback); diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 70b32f0758..574c51a439 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -184,6 +184,9 @@ public: /** Returns ListDirectoryResponse with list of files. */ Networking::Request *listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + /** Returns Common::Array with list of files, which were not downloaded. */ + Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + /** Return the StorageInfo struct. */ Networking::Request *info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback); -- cgit v1.2.3 From 10250af2516c8f7d41cc79e3c55b59f2eeecfa92 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 4 Jul 2016 15:23:13 +0600 Subject: CLOUD: Fix CloudManager's methods Were not returning created Request. --- backends/cloud/cloudmanager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 0a5006ccef..68c7e9aa8a 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -217,7 +217,7 @@ void CloudManager::printBool(Storage::BoolResponse response) const { Networking::Request *CloudManager::listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { Storage *storage = getCurrentStorage(); - if (storage) storage->listDirectory(path, callback, errorCallback, recursive); + if (storage) return storage->listDirectory(path, callback, errorCallback, recursive); else { delete callback; delete errorCallback; @@ -228,7 +228,7 @@ Networking::Request *CloudManager::listDirectory(Common::String path, Storage::L Networking::Request *CloudManager::downloadFolder(Common::String remotePath, Common::String localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { Storage *storage = getCurrentStorage(); - if (storage) storage->downloadFolder(remotePath, localPath, callback, errorCallback, recursive); + if (storage) return storage->downloadFolder(remotePath, localPath, callback, errorCallback, recursive); else { delete callback; delete errorCallback; -- cgit v1.2.3 From b8ee9d4e7d32d0cc0dd832cbd0ffec5c5d08db34 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 4 Jul 2016 16:14:30 +0600 Subject: CLOUD: Add FolderDownload-related methods in Storage CloudManager's shortcuts are added too. The idea is to keep FolderDownload request within Storage, and provide necessary means to access it. The download is started and cancelled through the DownloadDialog. --- backends/cloud/cloudmanager.cpp | 32 ++++++++++++++ backends/cloud/cloudmanager.h | 19 +++++++++ backends/cloud/folderdownloadrequest.cpp | 4 +- backends/cloud/folderdownloadrequest.h | 8 +++- backends/cloud/storage.cpp | 71 +++++++++++++++++++++++++++++++- backends/cloud/storage.h | 28 +++++++++++++ 6 files changed, 158 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 68c7e9aa8a..a1756ed5a6 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -274,6 +274,8 @@ bool CloudManager::isWorking() { return false; } +///// SavesSyncRequest-related ///// + bool CloudManager::isSyncing() { Storage *storage = getCurrentStorage(); if (storage) return storage->isSyncing(); @@ -308,4 +310,34 @@ void CloudManager::setSyncTarget(GUI::CommandReceiver *target) { if (storage) storage->setSyncTarget(target); } +///// DownloadFolderRequest-related ///// + +bool CloudManager::startDownload(Common::String remotePath, Common::String localPath) { + Storage *storage = getCurrentStorage(); + if (storage) return storage->startDownload(remotePath, localPath); + return false; +} + +void CloudManager::cancelDownload() { + Storage *storage = getCurrentStorage(); + if (storage) storage->cancelDownload(); +} + +void CloudManager::setDownloadTarget(GUI::CommandReceiver *target) { + Storage *storage = getCurrentStorage(); + if (storage) storage->setDownloadTarget(target); +} + +bool CloudManager::isDownloading() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->isDownloading(); + return false; +} + +double CloudManager::getDownloadingProgress() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getDownloadingProgress(); + return 1; +} + } // End of namespace Cloud diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 574c51a439..2617a9c62e 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -206,6 +206,8 @@ public: /** Returns whether there are any requests running. */ bool isWorking(); + ///// SavesSyncRequest-related ///// + /** Returns whether there is a SavesSyncRequest running. */ bool isSyncing(); @@ -223,6 +225,23 @@ public: /** Sets SavesSyncRequest's target to given CommandReceiver. */ void setSyncTarget(GUI::CommandReceiver *target); + + ///// DownloadFolderRequest-related ///// + + /** Starts a folder download. */ + bool startDownload(Common::String remotePath, Common::String localPath); + + /** Cancels running download. */ + void cancelDownload(); + + /** Sets FolderDownloadRequest's target to given CommandReceiver. */ + void setDownloadTarget(GUI::CommandReceiver *target); + + /** Returns whether there is a FolderDownloadRequest running. */ + bool isDownloading(); + + /** Returns a number in [0, 1] range which represents current download progress (1 = complete). */ + double getDownloadingProgress(); }; /** Shortcut for accessing the connection manager. */ diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 83296c3d15..e00f85121f 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -26,7 +26,7 @@ namespace Cloud { FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive): - Request(nullptr, ecb), _storage(storage), _fileArrayCallback(callback), + Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _fileArrayCallback(callback), _remoteDirectoryPath(remoteDirectoryPath), _localDirectoryPath(localDirectoryPath), _recursive(recursive), _workingRequest(nullptr), _ignoreCallback(false) { start(); @@ -125,4 +125,6 @@ void FolderDownloadRequest::finishDownload(Common::Array &files) { if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); } +double FolderDownloadRequest::getProgress() { return 0; } //TODO + } // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index bf55567b2d..83d3432746 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -26,10 +26,11 @@ #include "backends/networking/curl/request.h" #include "backends/networking/curl/networkreadstream.h" #include "backends/cloud/storage.h" +#include "gui/object.h" namespace Cloud { -class FolderDownloadRequest: public Networking::Request { +class FolderDownloadRequest: public Networking::Request, public GUI::CommandSender { Storage *_storage; Storage::FileArrayCallback _fileArrayCallback; Common::String _remoteDirectoryPath, _localDirectoryPath; @@ -51,7 +52,10 @@ public: virtual ~FolderDownloadRequest(); virtual void handle(); - virtual void restart(); + virtual void restart(); + + /** Returns a number in range [0, 1], where 1 is "complete". */ + double getProgress(); }; } // End of namespace Cloud diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index b98f213327..a08fe11a70 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -30,7 +30,9 @@ namespace Cloud { -Storage::Storage(): _runningRequestsCount(0), _savesSyncRequest(nullptr) {} +Storage::Storage(): + _runningRequestsCount(0), _savesSyncRequest(nullptr), _syncRestartRequestsed(false), + _downloadFolderRequest(nullptr) {} Storage::~Storage() {} @@ -135,6 +137,8 @@ bool Storage::isWorking() { return working; } +///// SavesSyncRequest-related ///// + bool Storage::isSyncing() { _runningRequestsMutex.lock(); bool syncing = _savesSyncRequest != nullptr; @@ -183,5 +187,70 @@ void Storage::setSyncTarget(GUI::CommandReceiver *target) { _runningRequestsMutex.unlock(); } +///// DownloadFolderRequest-related ///// + +bool Storage::startDownload(Common::String remotePath, Common::String localPath) { + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) { + warning("Storage::startDownload: there is a download in progress already"); + _runningRequestsMutex.unlock(); + return false; + } + _downloadFolderRequest = (FolderDownloadRequest *)downloadFolder( + remotePath, localPath, + new Common::Callback(this, &Storage::directoryDownloadedCallback), + new Common::Callback(this, &Storage::directoryDownloadedErrorCallback), + true + ); + _runningRequestsMutex.unlock(); + return true; +} + +void Storage::cancelDownload() { + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + _downloadFolderRequest->finish(); + _runningRequestsMutex.unlock(); +} + +void Storage::setDownloadTarget(GUI::CommandReceiver *target) { + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + _downloadFolderRequest->setTarget(target); + _runningRequestsMutex.unlock(); +} + +bool Storage::isDownloading() { + _runningRequestsMutex.lock(); + bool syncing = _downloadFolderRequest != nullptr; + _runningRequestsMutex.unlock(); + return syncing; +} + +double Storage::getDownloadingProgress() { + double result = 1; + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + result = _downloadFolderRequest->getProgress(); + _runningRequestsMutex.unlock(); + return result; +} + +void Storage::directoryDownloadedCallback(Cloud::Storage::FileArrayResponse response) { + _runningRequestsMutex.lock(); + _downloadFolderRequest = nullptr; + _runningRequestsMutex.unlock(); + + //TODO: show response.value (if not empty), show message on OSD +} + +void Storage::directoryDownloadedErrorCallback(Networking::ErrorResponse error) { + _runningRequestsMutex.lock(); + _downloadFolderRequest = nullptr; + _runningRequestsMutex.unlock(); + + //TODO: _showError = true; +} + } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index ace2f30864..28a20720b7 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -42,6 +42,7 @@ class CommandReceiver; namespace Cloud { class SavesSyncRequest; +class FolderDownloadRequest; class Storage { public: @@ -63,6 +64,7 @@ protected: Common::Mutex _runningRequestsMutex; SavesSyncRequest *_savesSyncRequest; bool _syncRestartRequestsed; + FolderDownloadRequest *_downloadFolderRequest; /** Returns default error callback (printErrorResponse). */ virtual Networking::ErrorCallback getErrorPrintingCallback(); @@ -159,6 +161,8 @@ public: /** Returns whether there are any requests running. */ virtual bool isWorking(); + ///// SavesSyncRequest-related ///// + /** Returns whether there is a SavesSyncRequest running. */ virtual bool isSyncing(); @@ -176,6 +180,30 @@ public: /** Sets SavesSyncRequest's target to given CommandReceiver. */ virtual void setSyncTarget(GUI::CommandReceiver *target); + + ///// DownloadFolderRequest-related ///// + + /** Starts a folder download. */ + virtual bool startDownload(Common::String remotePath, Common::String localPath); + + /** Cancels running download. */ + virtual void cancelDownload(); + + /** Sets FolderDownloadRequest's target to given CommandReceiver. */ + virtual void setDownloadTarget(GUI::CommandReceiver *target); + + /** Returns whether there is a FolderDownloadRequest running. */ + virtual bool isDownloading(); + + /** Returns a number in [0, 1] range which represents current download progress (1 = complete). */ + virtual double getDownloadingProgress(); + +protected: + /** Finishes the download. Shows an OSD message. */ + virtual void directoryDownloadedCallback(FileArrayResponse response); + + /** Finishes the download. Shows an OSD message. */ + virtual void directoryDownloadedErrorCallback(Networking::ErrorResponse error); }; } // End of namespace Cloud -- cgit v1.2.3 From ddb1a6ccb6238aaed599b271506a94a7c0f18844 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 4 Jul 2016 17:11:58 +0600 Subject: GUI: Upgrade DownloadDialog It now shows the remote and local directories and a progress bar. Storage now shows OSD messages on download success and failure. --- backends/cloud/cloudmanager.cpp | 12 ++++++++++++ backends/cloud/cloudmanager.h | 6 ++++++ backends/cloud/folderdownloadrequest.cpp | 13 +++++++++++-- backends/cloud/folderdownloadrequest.h | 7 +++++++ backends/cloud/storage.cpp | 33 ++++++++++++++++++++++++++++---- backends/cloud/storage.h | 6 ++++++ 6 files changed, 71 insertions(+), 6 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a1756ed5a6..dfe65e7f44 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -340,4 +340,16 @@ double CloudManager::getDownloadingProgress() { return 1; } +Common::String CloudManager::getDownloadRemoteDirectory() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getDownloadRemoteDirectory(); + return ""; +} + +Common::String CloudManager::getDownloadLocalDirectory() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getDownloadLocalDirectory(); + return ""; +} + } // End of namespace Cloud diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 2617a9c62e..1cdbbccdb9 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -242,6 +242,12 @@ public: /** Returns a number in [0, 1] range which represents current download progress (1 = complete). */ double getDownloadingProgress(); + + /** Returns remote directory path. */ + virtual Common::String getDownloadRemoteDirectory(); + + /** Returns local directory path. */ + virtual Common::String getDownloadLocalDirectory(); }; /** Shortcut for accessing the connection manager. */ diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index e00f85121f..d57da6bc7f 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -22,17 +22,19 @@ #include "backends/cloud/folderdownloadrequest.h" #include "common/debug.h" +#include "gui/downloaddialog.h" namespace Cloud { FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArrayCallback callback, Networking::ErrorCallback ecb, Common::String remoteDirectoryPath, Common::String localDirectoryPath, bool recursive): Request(nullptr, ecb), CommandSender(nullptr), _storage(storage), _fileArrayCallback(callback), _remoteDirectoryPath(remoteDirectoryPath), _localDirectoryPath(localDirectoryPath), _recursive(recursive), - _workingRequest(nullptr), _ignoreCallback(false) { + _workingRequest(nullptr), _ignoreCallback(false), _totalFiles(0) { start(); } FolderDownloadRequest::~FolderDownloadRequest() { + sendCommand(GUI::kDownloadEndedCmd, 0); _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); delete _fileArrayCallback; @@ -46,6 +48,7 @@ void FolderDownloadRequest::start() { _files.clear(); _failedFiles.clear(); _ignoreCallback = false; + _totalFiles = 0; //list directory first _workingRequest = _storage->listDirectory( @@ -60,6 +63,7 @@ void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryRespon _workingRequest = nullptr; if (_ignoreCallback) return; _files = response.value; + _totalFiles = _files.size(); downloadNextFile(); } @@ -91,6 +95,8 @@ void FolderDownloadRequest::downloadNextFile() { _files.pop_back(); } while (_currentFile.isDirectory()); //TODO: may be create these directories (in case those are empty) + sendCommand(GUI::kDownloadProgressCmd, (int)(getProgress() * 100)); + Common::String remotePath = _currentFile.path(); Common::String localPath = remotePath; if (_remoteDirectoryPath == "" || remotePath.hasPrefix(_remoteDirectoryPath)) { @@ -125,6 +131,9 @@ void FolderDownloadRequest::finishDownload(Common::Array &files) { if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); } -double FolderDownloadRequest::getProgress() { return 0; } //TODO +double FolderDownloadRequest::getProgress() { + if (_totalFiles == 0) return 0; + return (double)(_totalFiles - _files.size()) / (double)(_totalFiles); +} } // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 83d3432746..41eacc2afe 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -39,6 +39,7 @@ class FolderDownloadRequest: public Networking::Request, public GUI::CommandSend StorageFile _currentFile; Request *_workingRequest; bool _ignoreCallback; + uint32 _totalFiles; void start(); void directoryListedCallback(Storage::ListDirectoryResponse response); @@ -56,6 +57,12 @@ public: /** Returns a number in range [0, 1], where 1 is "complete". */ double getProgress(); + + /** Returns remote directory path. */ + Common::String getRemotePath() { return _remoteDirectoryPath; } + + /** Returns local directory path. */ + Common::String getLocalPath() { return _localDirectoryPath; } }; } // End of namespace Cloud diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index a08fe11a70..4e3dc435a6 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -27,6 +27,7 @@ #include "backends/networking/curl/connectionmanager.h" #include "common/debug.h" #include "common/file.h" +#include namespace Cloud { @@ -198,7 +199,7 @@ bool Storage::startDownload(Common::String remotePath, Common::String localPath) } _downloadFolderRequest = (FolderDownloadRequest *)downloadFolder( remotePath, localPath, - new Common::Callback(this, &Storage::directoryDownloadedCallback), + new Common::Callback(this, &Storage::directoryDownloadedCallback), new Common::Callback(this, &Storage::directoryDownloadedErrorCallback), true ); @@ -236,12 +237,36 @@ double Storage::getDownloadingProgress() { return result; } -void Storage::directoryDownloadedCallback(Cloud::Storage::FileArrayResponse response) { +Common::String Storage::getDownloadRemoteDirectory() { + Common::String result = ""; + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + result = _downloadFolderRequest->getRemotePath(); + _runningRequestsMutex.unlock(); + return result; +} + +Common::String Storage::getDownloadLocalDirectory() { + Common::String result = ""; + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + result = _downloadFolderRequest->getLocalPath(); + _runningRequestsMutex.unlock(); + return result; +} + +void Storage::directoryDownloadedCallback(FileArrayResponse response) { _runningRequestsMutex.lock(); _downloadFolderRequest = nullptr; _runningRequestsMutex.unlock(); - //TODO: show response.value (if not empty), show message on OSD + Common::String message; + if (response.value.size()) { + message = Common::String::format(_("Download complete.\nFailed to download %u files."), response.value.size()); + } else { + message = _("Download complete."); + } + g_system->displayMessageOnOSD(message.c_str()); } void Storage::directoryDownloadedErrorCallback(Networking::ErrorResponse error) { @@ -249,7 +274,7 @@ void Storage::directoryDownloadedErrorCallback(Networking::ErrorResponse error) _downloadFolderRequest = nullptr; _runningRequestsMutex.unlock(); - //TODO: _showError = true; + g_system->displayMessageOnOSD(_("Download failed.")); } } // End of namespace Cloud diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 28a20720b7..62b42697e6 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -198,6 +198,12 @@ public: /** Returns a number in [0, 1] range which represents current download progress (1 = complete). */ virtual double getDownloadingProgress(); + /** Returns remote directory path. */ + virtual Common::String getDownloadRemoteDirectory(); + + /** Returns local directory path. */ + virtual Common::String getDownloadLocalDirectory(); + protected: /** Finishes the download. Shows an OSD message. */ virtual void directoryDownloadedCallback(FileArrayResponse response); -- cgit v1.2.3 From 1cfdb9661678a5cabb77c2cf60d2fa357121d584 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Mon, 4 Jul 2016 17:55:09 +0600 Subject: CLOUD: Fix FolderDownloadRequest Actually, I'm not completely sure, but this fixed the segfault when user closes ScummVM during the download. Even if that's not a fix, these lines must be in this method anyway. --- backends/cloud/folderdownloadrequest.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index d57da6bc7f..6cf55b28cf 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -81,6 +81,8 @@ void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse respons } void FolderDownloadRequest::fileDownloadedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; fileDownloadedCallback(Storage::BoolResponse(error.request, false)); } -- cgit v1.2.3 From b37b392fa07c5d24fbef2ffe4b4704e8f666f9a1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 00:33:35 +0600 Subject: CLOUD: Add BoxStorage sketch --- backends/cloud/box/boxstorage.cpp | 292 ++++++++++++++++++++++++++++++++++++++ backends/cloud/box/boxstorage.h | 127 +++++++++++++++++ backends/cloud/cloudmanager.cpp | 6 + backends/cloud/cloudmanager.h | 1 + 4 files changed, 426 insertions(+) create mode 100644 backends/cloud/box/boxstorage.cpp create mode 100644 backends/cloud/box/boxstorage.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp new file mode 100644 index 0000000000..8a2e004e53 --- /dev/null +++ b/backends/cloud/box/boxstorage.cpp @@ -0,0 +1,292 @@ +/* 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. +* +*/ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/box/boxstorage.h" +#include "backends/cloud/cloudmanager.h" +#include "backends/networking/curl/connectionmanager.h" +#include "backends/networking/curl/curljsonrequest.h" +#include "backends/networking/curl/networkreadstream.h" +#include "common/debug.h" +#include "common/json.h" +#include +#include "common/config-manager.h" + +namespace Cloud { +namespace Box { + +char *BoxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth +char *BoxStorage::SECRET = nullptr; //TODO: hide these secrets somehow + +void BoxStorage::loadKeyAndSecret() { + Common::String k = ConfMan.get("BOX_KEY", ConfMan.kCloudDomain); + KEY = new char[k.size() + 1]; + memcpy(KEY, k.c_str(), k.size()); + KEY[k.size()] = 0; + + k = ConfMan.get("BOX_SECRET", ConfMan.kCloudDomain); + SECRET = new char[k.size() + 1]; + memcpy(SECRET, k.c_str(), k.size()); + SECRET[k.size()] = 0; +} + +BoxStorage::BoxStorage(Common::String accessToken, Common::String refreshToken): + _token(accessToken), _refreshToken(refreshToken) {} + +BoxStorage::BoxStorage(Common::String code) { + getAccessToken(new Common::Callback(this, &BoxStorage::codeFlowComplete), code); +} + +BoxStorage::~BoxStorage() {} + +void BoxStorage::getAccessToken(BoolCallback callback, Common::String code) { + if (!KEY || !SECRET) loadKeyAndSecret(); + bool codeFlow = (code != ""); + + if (!codeFlow && _refreshToken == "") { + warning("BoxStorage: no refresh token available to get new access token."); + if (callback) (*callback)(BoolResponse(nullptr, false)); + return; + } + + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::tokenRefreshed, callback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, getErrorPrintingCallback(), "https://api.box.com/oauth2/token"); + if (codeFlow) { + request->addPostField("grant_type=authorization_code"); + request->addPostField("code=" + code); + } else { + request->addPostField("grant_type=refresh_token"); + request->addPostField("refresh_token=" + _refreshToken); + } + request->addPostField("client_id=" + Common::String(KEY)); + request->addPostField("client_secret=" + Common::String(SECRET)); + /* +#ifdef USE_SDL_NET + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); +#else + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); +#endif + */ + addRequest(request); +} + +void BoxStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("BoxStorage: got NULL instead of JSON"); + if (callback) (*callback)(BoolResponse(nullptr, false)); + return; + } + + Common::JSONObject result = json->asObject(); + if (!result.contains("access_token") || !result.contains("refresh_token")) { + warning("Bad response, no token passed"); + debug("%s", json->stringify().c_str()); + if (callback) (*callback)(BoolResponse(nullptr, false)); + } else { + _token = result.getVal("access_token")->asString(); + _refreshToken = result.getVal("refresh_token")->asString(); + CloudMan.save(); //ask CloudManager to save our new refreshToken + if (callback) (*callback)(BoolResponse(nullptr, true)); + } + delete json; +} + +void BoxStorage::codeFlowComplete(BoolResponse response) { + if (!response.value) { + warning("BoxStorage: failed to get access token through code flow"); + return; + } + + CloudMan.replaceStorage(this, kStorageBoxId); + ConfMan.flushToDisk(); +} + +void BoxStorage::saveConfig(Common::String keyPrefix) { + ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); + ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); +} + +Common::String BoxStorage::name() const { + return "Box"; +} + +void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("NULL passed instead of JSON"); + delete outerCallback; + return; + } + + Common::JSONObject info = json->asObject(); + + Common::String uid, name, email; + uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one + + if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { + Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); + if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { + Common::JSONObject user = createdBy.getVal("user")->asObject(); + uid = user.getVal("id")->asString(); + name = user.getVal("displayName")->asString(); + } + } + + if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { + quotaUsed = info.getVal("size")->asIntegerNumber(); + } + + Common::String username = email; + if (username == "") username = name; + if (username == "") username = uid; + CloudMan.setStorageUsername(kStorageBoxId, username); + + if (outerCallback) { + (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaUsed, quotaAllocated))); + delete outerCallback; + } + + delete json; +} + +void BoxStorage::printJson(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("printJson: NULL"); + return; + } + + debug("%s", json->stringify().c_str()); + delete json; +} + +void BoxStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { + if (!response.value) { + warning("fileInfoCallback: NULL"); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); + return; + } + + Common::JSONObject result = response.value->asObject(); + if (result.contains("@content.downloadUrl")) { + const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); + if (outerCallback) + (*outerCallback)(Networking::NetworkReadStreamResponse( + response.request, + new Networking::NetworkReadStream(url, 0, "") + )); + } else { + warning("downloadUrl not found in passed JSON"); + debug("%s", response.value->stringify().c_str()); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); + } + delete response.value; +} + +Networking::Request *BoxStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + //return addRequest(new BoxListDirectoryRequest(this, path, callback, errorCallback, recursive)); + return nullptr; //TODO +} + +Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { + //return addRequest(new BoxUploadRequest(this, path, contents, callback, errorCallback)); + return nullptr; //TODO +} + +Networking::Request *BoxStorage::streamFileById(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { + /* + Common::String url = "https://api.Box.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(path); + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::fileInfoCallback, outerCallback); + Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _token); + return addRequest(request); + */ + return nullptr; //TODO +} + +void BoxStorage::fileDownloaded(BoolResponse response) { + if (response.value) debug("file downloaded!"); + else debug("download failed!"); +} + +void BoxStorage::printFiles(FileArrayResponse response) { + debug("files:"); + Common::Array &files = response.value; + for (uint32 i = 0; i < files.size(); ++i) + debug("\t%s", files[i].path().c_str()); +} + +void BoxStorage::printBool(BoolResponse response) { + debug("bool: %s", response.value ? "true" : "false"); +} + +void BoxStorage::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()); +} + +Networking::Request *BoxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + //return addRequest(new BoxCreateDirectoryRequest(this, path, callback, errorCallback)); + return nullptr; //TODO +} + +Networking::Request *BoxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { + /* + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::infoInnerCallback, callback); + Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.Box.com/v1.0/drive/special/approot"); + request->addHeader("Authorization: bearer " + _token); + return addRequest(request); + */ + return nullptr; //TODO +} + +Common::String BoxStorage::savesDirectoryPath() { return "saves/"; } + +BoxStorage *BoxStorage::loadFromConfig(Common::String keyPrefix) { + loadKeyAndSecret(); + + if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { + warning("No access_token found"); + return 0; + } + + if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { + warning("No refresh_token found"); + return 0; + } + + Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); + Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", ConfMan.kCloudDomain); + return new BoxStorage(accessToken, refreshToken); +} + +Common::String BoxStorage::getAuthLink() { + // now we only specify short "scummvm.org/c/bx" with actual redirect to the auth page + return ""; +} + +} // End of namespace Box +} // End of namespace Cloud diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h new file mode 100644 index 0000000000..b58608c7f0 --- /dev/null +++ b/backends/cloud/box/boxstorage.h @@ -0,0 +1,127 @@ +/* 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_BOX_BOXSTORAGE_H +#define BACKENDS_CLOUD_BOX_BOXSTORAGE_H + +#include "backends/cloud/storage.h" +#include "common/callback.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace Box { + +class BoxStorage: public Cloud::Storage { + static char *KEY, *SECRET; + + static void loadKeyAndSecret(); + + Common::String _token, _refreshToken; + + /** This private constructor is called from loadFromConfig(). */ + BoxStorage(Common::String token, Common::String refreshToken); + + void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); + void codeFlowComplete(BoolResponse response); + + /** Constructs StorageInfo based on JSON response from cloud. */ + void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); + + void printJson(Networking::JsonResponse response); + void fileDownloaded(BoolResponse response); + void printFiles(FileArrayResponse response); + void printBool(BoolResponse response); + void printFile(UploadResponse response); + + void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); +public: + /** This constructor uses OAuth code flow to get tokens. */ + BoxStorage(Common::String code); + virtual ~BoxStorage(); + + /** + * Storage methods, which are used by CloudManager to save + * storage in configuration file. + */ + + /** + * Save storage data using ConfMan. + * @param keyPrefix all saved keys must start with this prefix. + * @note every Storage must write keyPrefix + "type" key + * with common value (e.g. "Dropbox"). + */ + virtual void saveConfig(Common::String keyPrefix); + + /** + * Return unique storage name. + * @returns some unique storage name (for example, "Dropbox (user@example.com)") + */ + virtual Common::String name() const; + + /** Public Cloud API comes down there. */ + + /** Returns ListDirectoryStatus struct with list of files. */ + virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + + /** Returns UploadStatus struct with info about uploaded file. */ + virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns pointer to Networking::NetworkReadStream. */ + virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); + + /** Calls the callback when finished. */ + virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO + + /** Calls the callback when finished. */ + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns the StorageInfo struct. */ + virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns storage's saves directory path with the trailing slash. */ + virtual Common::String savesDirectoryPath(); + + /** + * Load token and user id from configs and return BoxStorage for those. + * @return pointer to the newly created BoxStorage or 0 if some problem occured. + */ + static BoxStorage *loadFromConfig(Common::String keyPrefix); + + /** + * Returns Box auth link. + */ + static Common::String getAuthLink(); + + /** + * Gets new access_token. If passed is "", refresh_token is used. + * Use "" in order to refresh token and pass a callback, so you could + * continue your work when new token is available. + */ + void getAccessToken(BoolCallback callback, Common::String code = ""); + + Common::String accessToken() { return _token; } +}; + +} // End of namespace Box +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index dfe65e7f44..e5b2c2a69d 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -21,6 +21,7 @@ */ #include "backends/cloud/cloudmanager.h" +#include "backends/cloud/box/boxstorage.h" #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/onedrive/onedrivestorage.h" #include "backends/cloud/googledrive/googledrivestorage.h" @@ -52,6 +53,7 @@ Common::String CloudManager::getStorageConfigName(uint32 index) const { case kStorageDropboxId: return "Dropbox"; case kStorageOneDriveId: return "OneDrive"; case kStorageGoogleDriveId: return "GoogleDrive"; + case kStorageBoxId: return "Box"; } assert(false); // Unhandled StorageID value return ""; @@ -68,6 +70,9 @@ void CloudManager::loadStorage() { case kStorageGoogleDriveId: _activeStorage = GoogleDrive::GoogleDriveStorage::loadFromConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); break; + case kStorageBoxId: + _activeStorage = Box::BoxStorage::loadFromConfig(kStoragePrefix + getStorageConfigName(_currentStorageIndex) + "_"); + break; default: _activeStorage = nullptr; } @@ -207,6 +212,7 @@ void CloudManager::connectStorage(uint32 index, Common::String code) { case kStorageDropboxId: storage = new Dropbox::DropboxStorage(code); break; case kStorageOneDriveId: storage = new OneDrive::OneDriveStorage(code); break; case kStorageGoogleDriveId: storage = new GoogleDrive::GoogleDriveStorage(code); break; + case kStorageBoxId: storage = new Box::BoxStorage(code); break; } //these would automatically request replaceStorage() when they receive the token } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 1cdbbccdb9..1098bddaa6 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -42,6 +42,7 @@ enum StorageID { kStorageDropboxId = 1, kStorageOneDriveId = 2, kStorageGoogleDriveId = 3, + kStorageBoxId = 4, kStorageTotal }; -- cgit v1.2.3 From 85f1ce8ece7d4f4c6e54cfe29eaebe2c4ec13aec Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 12:52:04 +0600 Subject: CLOUD: Add BoxTokenRefresher and BoxStorage::info() BoxTokenRefresher does refresh if HTTP 401 is returned by the server. To test refresher, BoxStorage::info() was added. --- backends/cloud/box/boxstorage.cpp | 39 ++++----- backends/cloud/box/boxtokenrefresher.cpp | 134 +++++++++++++++++++++++++++++++ backends/cloud/box/boxtokenrefresher.h | 53 ++++++++++++ 3 files changed, 208 insertions(+), 18 deletions(-) create mode 100644 backends/cloud/box/boxtokenrefresher.cpp create mode 100644 backends/cloud/box/boxtokenrefresher.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 8a2e004e53..85bbf34221 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -22,6 +22,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/box/boxstorage.h" +#include "backends/cloud/box/boxtokenrefresher.h" #include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" @@ -141,20 +142,25 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking Common::JSONObject info = json->asObject(); Common::String uid, name, email; - uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one - - if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { - Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); - if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { - Common::JSONObject user = createdBy.getVal("user")->asObject(); - uid = user.getVal("id")->asString(); - name = user.getVal("displayName")->asString(); - } - } + uint64 quotaUsed = 0, quotaAllocated = 0; - if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { - quotaUsed = info.getVal("size")->asIntegerNumber(); - } + // can check that "type": "user" + // there is also "max_upload_size", "phone" and "avatar_url" + + if (info.contains("id") && info.getVal("id")->isString()) + uid = info.getVal("id")->asString(); + + if (info.contains("name") && info.getVal("name")->isString()) + name = info.getVal("name")->asString(); + + if (info.contains("login") && info.getVal("login")->isString()) + email = info.getVal("login")->asString(); + + if (info.contains("space_amount") && info.getVal("space_amount")->isIntegerNumber()) + quotaAllocated = info.getVal("space_amount")->asIntegerNumber(); + + if (info.contains("space_used") && info.getVal("space_used")->isIntegerNumber()) + quotaUsed = info.getVal("space_used")->asIntegerNumber(); Common::String username = email; if (username == "") username = name; @@ -254,13 +260,10 @@ Networking::Request *BoxStorage::createDirectory(Common::String path, BoolCallba } Networking::Request *BoxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { - /* Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::infoInnerCallback, callback); - Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.Box.com/v1.0/drive/special/approot"); - request->addHeader("Authorization: bearer " + _token); + Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.box.com/2.0/users/me"); + request->addHeader("Authorization: Bearer " + _token); return addRequest(request); - */ - return nullptr; //TODO } Common::String BoxStorage::savesDirectoryPath() { return "saves/"; } diff --git a/backends/cloud/box/boxtokenrefresher.cpp b/backends/cloud/box/boxtokenrefresher.cpp new file mode 100644 index 0000000000..9dfbef537f --- /dev/null +++ b/backends/cloud/box/boxtokenrefresher.cpp @@ -0,0 +1,134 @@ +/* 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. +* +*/ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/box/boxtokenrefresher.h" +#include "backends/cloud/box/boxstorage.h" +#include "backends/networking/curl/networkreadstream.h" +#include "common/debug.h" +#include "common/json.h" +#include + +namespace Cloud { +namespace Box { + +BoxTokenRefresher::BoxTokenRefresher(BoxStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url): + CurlJsonRequest(callback, ecb, url), _parentStorage(parent) {} + +BoxTokenRefresher::~BoxTokenRefresher() {} + +void BoxTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { + if (!response.value) { + //failed to refresh token, notify user with NULL in original callback + warning("BoxTokenRefresher: failed to refresh token"); + finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; + } + + //update headers: first change header with token, then pass those to request + for (uint32 i = 0; i < _headers.size(); ++i) { + if (_headers[i].contains("Authorization")) { + _headers[i] = "Authorization: Bearer " + _parentStorage->accessToken(); + } + } + setHeaders(_headers); + + //successfully received refreshed token, can restart the original request now + retry(0); +} + +void BoxTokenRefresher::finishJson(Common::JSONValue *json) { + if (!json) { + //that's probably not an error (200 OK) + CurlJsonRequest::finishJson(nullptr); + return; + } + + Common::JSONObject result = json->asObject(); + if (result.contains("type") && result.getVal("type")->isString() && result.getVal("type")->asString() == "error") { + //new token needed => request token & then retry original request + long httpCode = -1; + if (_stream) { + httpCode = _stream->httpResponseCode(); + debug("code %ld", httpCode); + } + + bool irrecoverable = true; + + Common::String code, message; + if (result.contains("code")) { + code = result.getVal("code")->asString(); + debug("code = %s", code.c_str()); + } + + if (result.contains("message")) { + message = result.getVal("message")->asString(); + debug("message = %s", message.c_str()); + } + + //TODO: decide when token refreshment will help + //if (code == "unauthenticated") irrecoverable = false; + + if (irrecoverable) { + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpCode)); + delete json; + return; + } + + pause(); + delete json; + _parentStorage->getAccessToken(new Common::Callback(this, &BoxTokenRefresher::tokenRefreshed)); + return; + } + + //notify user of success + CurlJsonRequest::finishJson(json); +} + +void BoxTokenRefresher::finishError(Networking::ErrorResponse error) { + if (error.httpResponseCode == 401) { // invalid_token + pause(); + _parentStorage->getAccessToken(new Common::Callback(this, &BoxTokenRefresher::tokenRefreshed)); + return; + } + + // there are also 400 == invalid_request and 403 == insufficient_scope + // but TokenRefresher is there to refresh token when it's invalid only + + Request::finishError(error); +} + +void BoxTokenRefresher::setHeaders(Common::Array &headers) { + _headers = headers; + curl_slist_free_all(_headersList); + _headersList = 0; + for (uint32 i = 0; i < headers.size(); ++i) + CurlJsonRequest::addHeader(headers[i]); +} + +void BoxTokenRefresher::addHeader(Common::String header) { + _headers.push_back(header); + CurlJsonRequest::addHeader(header); +} + +} // End of namespace Box +} // End of namespace Cloud diff --git a/backends/cloud/box/boxtokenrefresher.h b/backends/cloud/box/boxtokenrefresher.h new file mode 100644 index 0000000000..7dedefdbe5 --- /dev/null +++ b/backends/cloud/box/boxtokenrefresher.h @@ -0,0 +1,53 @@ +/* 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_BOX_BOXTOKENREFRESHER_H +#define BACKENDS_CLOUD_BOX_BOXTOKENREFRESHER_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace Box { + +class BoxStorage; + +class BoxTokenRefresher: public Networking::CurlJsonRequest { + BoxStorage *_parentStorage; + Common::Array _headers; + + void tokenRefreshed(Storage::BoolResponse response); + + virtual void finishJson(Common::JSONValue *json); + virtual void finishError(Networking::ErrorResponse error); +public: + BoxTokenRefresher(BoxStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); + virtual ~BoxTokenRefresher(); + + virtual void setHeaders(Common::Array &headers); + virtual void addHeader(Common::String header); +}; + +} // End of namespace Box +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From eb269e137f8a494a670bd4f2ee3370fdfb81e113 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 13:54:45 +0600 Subject: CLOUD: Add BoxListDirectoryByIdRequest Similarly to Google Drive, Box uses only ids of files. That means id resolving would be slow. --- backends/cloud/box/boxlistdirectorybyidrequest.cpp | 169 +++++++++++++++++++++ backends/cloud/box/boxlistdirectorybyidrequest.h | 63 ++++++++ backends/cloud/box/boxstorage.cpp | 9 ++ backends/cloud/box/boxstorage.h | 1 + backends/cloud/iso8601.cpp | 19 ++- 5 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 backends/cloud/box/boxlistdirectorybyidrequest.cpp create mode 100644 backends/cloud/box/boxlistdirectorybyidrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp new file mode 100644 index 0000000000..d4606b1851 --- /dev/null +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -0,0 +1,169 @@ +/* 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/box/boxlistdirectorybyidrequest.h" +#include "backends/cloud/box/boxstorage.h" +#include "backends/cloud/box/boxtokenrefresher.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" + +namespace Cloud { +namespace Box { + +#define BOX_LIST_DIRECTORY_LIMIT 1000 + +BoxListDirectoryByIdRequest::BoxListDirectoryByIdRequest(BoxStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _requestedId(id), _storage(storage), _listDirectoryCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +BoxListDirectoryByIdRequest::~BoxListDirectoryByIdRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _listDirectoryCallback; +} + +void BoxListDirectoryByIdRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _files.clear(); + _ignoreCallback = false; + + makeRequest(0); +} + +void BoxListDirectoryByIdRequest::makeRequest(uint32 offset) { + Common::String url = Common::String::format( + "https://api.box.com/2.0/folders/%s/items?offset=%u&limit=%u&fields=%s", + _requestedId.c_str(), + offset, + BOX_LIST_DIRECTORY_LIMIT, + "id,type,name,size,modified_at" + ); + + Networking::JsonCallback callback = new Common::Callback(this, &BoxListDirectoryByIdRequest::responseCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &BoxListDirectoryByIdRequest::errorCallback); + Networking::CurlJsonRequest *request = new BoxTokenRefresher(_storage, callback, failureCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); + _workingRequest = ConnMan.addRequest(request); +} + +void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { + _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()) + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + + Common::JSONValue *json = response.value; + if (json) { + Common::JSONObject responseObject = json->asObject(); + + //debug("%s", json->stringify(true).c_str()); + + //TODO: check that error is returned the right way + /* + if (responseObject.contains("error") || responseObject.contains("error_summary")) { + warning("Box returned error: %s", responseObject.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 (responseObject.contains("entries") && responseObject.getVal("entries")->isArray()) { + Common::JSONArray items = responseObject.getVal("entries")->asArray(); + for (uint32 i = 0; i < items.size(); ++i) { + Common::JSONObject item = items[i]->asObject(); + Common::String id = item.getVal("id")->asString(); + Common::String name = item.getVal("name")->asString(); + bool isDirectory = (item.getVal("type")->asString() == "folder"); + uint32 size = 0, timestamp = 0; + if (item.contains("size")) { + if (item.getVal("size")->isString()) + size = item.getVal("size")->asString().asUint64(); + else if (item.getVal("size")->isIntegerNumber()) + size = item.getVal("size")->asIntegerNumber(); + else + warning("strange type for field 'size'"); + } + if (item.contains("modified_at") && item.getVal("modified_at")->isString()) + timestamp = ISO8601::convertToTimestamp(item.getVal("modified_at")->asString()); + + //as we list directory by id, we can't determine full path for the file, so we leave it empty + _files.push_back(StorageFile(id, "", name, size, timestamp, isDirectory)); + } + } + + uint32 received = 0; + uint32 totalCount = 0; + if (responseObject.contains("total_count") && responseObject.getVal("total_count")->isIntegerNumber()) + totalCount = responseObject.getVal("total_count")->asIntegerNumber(); + if (responseObject.contains("offset") && responseObject.getVal("offset")->isIntegerNumber()) + received = responseObject.getVal("offset")->asIntegerNumber(); + if (responseObject.contains("limit") && responseObject.getVal("limit")->isIntegerNumber()) + received += responseObject.getVal("limit")->asIntegerNumber(); + bool hasMore = (received < totalCount); + + if (hasMore) makeRequest(received); + else finishListing(_files); + } else { + warning("null, not json"); + error.failed = true; + finishError(error); + } + + delete json; +} + +void BoxListDirectoryByIdRequest::errorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + finishError(error); +} + +void BoxListDirectoryByIdRequest::handle() {} + +void BoxListDirectoryByIdRequest::restart() { start(); } + +Common::String BoxListDirectoryByIdRequest::date() const { return _date; } + +void BoxListDirectoryByIdRequest::finishListing(Common::Array &files) { + Request::finishSuccess(); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); +} + +} // End of namespace Box +} // End of namespace Cloud diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.h b/backends/cloud/box/boxlistdirectorybyidrequest.h new file mode 100644 index 0000000000..ccf8d2e342 --- /dev/null +++ b/backends/cloud/box/boxlistdirectorybyidrequest.h @@ -0,0 +1,63 @@ +/* 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_BOX_BOXLISTDIRECTORYBYIDREQUEST_H +#define BACKENDS_CLOUD_BOX_BOXLISTDIRECTORYBYIDREQUEST_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 Box { + +class BoxStorage; + +class BoxListDirectoryByIdRequest: public Networking::Request { + Common::String _requestedId; + BoxStorage *_storage; + + Storage::ListDirectoryCallback _listDirectoryCallback; + Common::Array _files; + Request *_workingRequest; + bool _ignoreCallback; + Common::String _date; + + void start(); + void makeRequest(uint32 offset); + void responseCallback(Networking::JsonResponse response); + void errorCallback(Networking::ErrorResponse error); + void finishListing(Common::Array &files); +public: + BoxListDirectoryByIdRequest(BoxStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb); + virtual ~BoxListDirectoryByIdRequest(); + + virtual void handle(); + virtual void restart(); + virtual Common::String date() const; +}; + +} // End of namespace Box +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 85bbf34221..9842ed2796 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -22,6 +22,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/box/boxstorage.h" +#include "backends/cloud/box/boxlistdirectorybyidrequest.h" #include "backends/cloud/box/boxtokenrefresher.h" #include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" @@ -210,10 +211,18 @@ void BoxStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCal } Networking::Request *BoxStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &BoxStorage::printFiles); //return addRequest(new BoxListDirectoryRequest(this, path, callback, errorCallback, recursive)); return nullptr; //TODO } +Networking::Request *BoxStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &BoxStorage::printFiles); + return addRequest(new BoxListDirectoryByIdRequest(this, id, callback, errorCallback)); +} + Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { //return addRequest(new BoxUploadRequest(this, path, contents, callback, errorCallback)); return nullptr; //TODO diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index b58608c7f0..3ce7a37f10 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -81,6 +81,7 @@ public: /** Returns ListDirectoryStatus struct with list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback); /** Returns UploadStatus struct with info about uploaded file. */ virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); diff --git a/backends/cloud/iso8601.cpp b/backends/cloud/iso8601.cpp index 3bc169ae85..1675c7ce54 100644 --- a/backends/cloud/iso8601.cpp +++ b/backends/cloud/iso8601.cpp @@ -33,6 +33,12 @@ Common::String getSubstring(const Common::String &s, uint32 beginning, uint32 en return result; } +int find(const char *cstr, uint32 startPosition, char needle) { + const char *res = strchr(cstr + startPosition, needle); + if (res == nullptr) return -1; + return res - cstr; +} + } namespace Cloud { @@ -41,12 +47,13 @@ namespace ISO8601 { uint32 convertToTimestamp(const Common::String &iso8601Date) { //2015-05-12T15:50:38Z const char *cstr = iso8601Date.c_str(); - uint32 firstHyphen = strchr(cstr, '-') - cstr; - uint32 secondHyphen = strchr(cstr + firstHyphen + 1, '-') - cstr; - uint32 tSeparator = strchr(cstr + secondHyphen + 1, 'T') - cstr; - uint32 firstColon = strchr(cstr + tSeparator + 1, ':') - cstr; - uint32 secondColon = strchr(cstr + firstColon + 1, ':') - cstr; - uint32 zSeparator = strchr(cstr + secondColon + 1, 'Z') - cstr; + int firstHyphen = find(cstr, 0, '-'); + int secondHyphen = find(cstr, firstHyphen + 1, '-'); + int tSeparator = find(cstr, secondHyphen + 1, 'T'); + int firstColon = find(cstr, tSeparator + 1, ':'); + int secondColon = find(cstr, firstColon + 1, ':'); + int zSeparator = find(cstr, secondColon + 1, 'Z'); + if (zSeparator == -1) zSeparator = find(cstr, secondColon + 1, '-'); // Box's RFC 3339 //now note '+1' which means if there ever was '-1' result of find(), we still did a valid find() from 0th char Common::String year = getSubstring(iso8601Date, 0, firstHyphen); -- cgit v1.2.3 From e0a6b2135de6a83f2ed4177c96fabf216412e5fb Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 14:13:23 +0600 Subject: CLOUD: Add BoxListDirectoryRequest And used in it BoxResolveIdRequest. TODO: make some generic ResolveIdRequest and ListDirectoryRequest for id-based storages. It's really similar, I just had to change a few details in GoogleDrive ListDirectory and ResolveId requests. --- backends/cloud/box/boxlistdirectoryrequest.cpp | 129 +++++++++++++++++++++++++ backends/cloud/box/boxlistdirectoryrequest.h | 66 +++++++++++++ backends/cloud/box/boxresolveidrequest.cpp | 125 ++++++++++++++++++++++++ backends/cloud/box/boxresolveidrequest.h | 60 ++++++++++++ backends/cloud/box/boxstorage.cpp | 11 ++- backends/cloud/box/boxstorage.h | 3 + 6 files changed, 392 insertions(+), 2 deletions(-) create mode 100644 backends/cloud/box/boxlistdirectoryrequest.cpp create mode 100644 backends/cloud/box/boxlistdirectoryrequest.h create mode 100644 backends/cloud/box/boxresolveidrequest.cpp create mode 100644 backends/cloud/box/boxresolveidrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectoryrequest.cpp b/backends/cloud/box/boxlistdirectoryrequest.cpp new file mode 100644 index 0000000000..b35c8c80d5 --- /dev/null +++ b/backends/cloud/box/boxlistdirectoryrequest.cpp @@ -0,0 +1,129 @@ +/* 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/box/boxlistdirectoryrequest.h" +#include "backends/cloud/box/boxstorage.h" + +namespace Cloud { +namespace Box { + +BoxListDirectoryRequest::BoxListDirectoryRequest(BoxStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), + _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +BoxListDirectoryRequest::~BoxListDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _listDirectoryCallback; +} + +void BoxListDirectoryRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _files.clear(); + _directoriesQueue.clear(); + _currentDirectory = StorageFile(); + _ignoreCallback = false; + + //find out that directory's id + Storage::UploadCallback innerCallback = new Common::Callback(this, &BoxListDirectoryRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &BoxListDirectoryRequest::idResolveErrorCallback); + _workingRequest = _storage->resolveFileId(_requestedPath, innerCallback, innerErrorCallback); +} + +void BoxListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + + StorageFile directory = response.value; + directory.setPath(_requestedPath); + _directoriesQueue.push_back(directory); + listNextDirectory(); +} + +void BoxListDirectoryRequest::idResolveErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + finishError(error); +} + +void BoxListDirectoryRequest::listNextDirectory() { + if (_directoriesQueue.empty()) { + finishListing(_files); + return; + } + + _currentDirectory = _directoriesQueue.back(); + _directoriesQueue.pop_back(); + + Storage::FileArrayCallback callback = new Common::Callback(this, &BoxListDirectoryRequest::listedDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &BoxListDirectoryRequest::listedDirectoryErrorCallback); + _workingRequest = _storage->listDirectoryById(_currentDirectory.id(), callback, failureCallback); +} + +void BoxListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + + for (uint32 i = 0; i < response.value.size(); ++i) { + StorageFile &file = response.value[i]; + Common::String path = _currentDirectory.path(); + if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') path += '/'; + path += file.name(); + file.setPath(path); + _files.push_back(file); + if (_requestedRecursive && file.isDirectory()) { + _directoriesQueue.push_back(file); + } + } + + listNextDirectory(); +} + +void BoxListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + finishError(error); +} + +void BoxListDirectoryRequest::handle() {} + +void BoxListDirectoryRequest::restart() { start(); } + +Common::String BoxListDirectoryRequest::date() const { return _date; } + +void BoxListDirectoryRequest::finishListing(Common::Array &files) { + Request::finishSuccess(); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); +} + +} // End of namespace Box +} // End of namespace Cloud diff --git a/backends/cloud/box/boxlistdirectoryrequest.h b/backends/cloud/box/boxlistdirectoryrequest.h new file mode 100644 index 0000000000..7392cdd84c --- /dev/null +++ b/backends/cloud/box/boxlistdirectoryrequest.h @@ -0,0 +1,66 @@ +/* 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_BOX_BOXLISTDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_BOX_BOXLISTDIRECTORYREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace Box { + +class BoxStorage; + +class BoxListDirectoryRequest: public Networking::Request { + Common::String _requestedPath; + bool _requestedRecursive; + BoxStorage *_storage; + Storage::ListDirectoryCallback _listDirectoryCallback; + Common::Array _files; + Common::Array _directoriesQueue; + StorageFile _currentDirectory; + Request *_workingRequest; + bool _ignoreCallback; + Common::String _date; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveErrorCallback(Networking::ErrorResponse error); + void listNextDirectory(); + void listedDirectoryCallback(Storage::FileArrayResponse response); + void listedDirectoryErrorCallback(Networking::ErrorResponse error); + void finishListing(Common::Array &files); +public: + BoxListDirectoryRequest(BoxStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); + virtual ~BoxListDirectoryRequest(); + + virtual void handle(); + virtual void restart(); + virtual Common::String date() const; +}; + +} // End of namespace Box +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/box/boxresolveidrequest.cpp b/backends/cloud/box/boxresolveidrequest.cpp new file mode 100644 index 0000000000..f07a94b92b --- /dev/null +++ b/backends/cloud/box/boxresolveidrequest.cpp @@ -0,0 +1,125 @@ +/* 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/box/boxresolveidrequest.h" +#include "backends/cloud/box/boxstorage.h" + +namespace Cloud { +namespace Box { + +BoxResolveIdRequest::BoxResolveIdRequest(BoxStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), + _requestedPath(path), _storage(storage), _uploadCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +BoxResolveIdRequest::~BoxResolveIdRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _uploadCallback; +} + +void BoxResolveIdRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _currentDirectory = ""; + _currentDirectoryId = "0"; + _ignoreCallback = false; + + listNextDirectory(StorageFile(_currentDirectoryId, 0, 0, true)); +} + +void BoxResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { + if (_currentDirectory.equalsIgnoreCase(_requestedPath)) { + finishFile(fileToReturn); + return; + } + + Storage::FileArrayCallback callback = new Common::Callback(this, &BoxResolveIdRequest::listedDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &BoxResolveIdRequest::listedDirectoryErrorCallback); + _workingRequest = _storage->listDirectoryById(_currentDirectoryId, callback, failureCallback); +} + +void BoxResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Common::String currentLevelName = _requestedPath; + ///debug("'%s'", currentLevelName.c_str()); + if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); + if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) currentLevelName.erase(0, 1); + ///debug("'%s'", currentLevelName.c_str()); + for (uint32 i = 0; i < currentLevelName.size(); ++i) { + if (currentLevelName[i] == '/' || currentLevelName[i] == '\\') { + currentLevelName.erase(i); + ///debug("'%s'", currentLevelName.c_str()); + break; + } + } + + Common::String path = _currentDirectory; + if (path != "") path += "/"; + path += currentLevelName; + bool lastLevel = (path.equalsIgnoreCase(_requestedPath)); + + ///debug("so, searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); + + Common::Array &files = response.value; + bool found = false; + for (uint32 i = 0; i < files.size(); ++i) { + if ((files[i].isDirectory() || lastLevel) && files[i].name().equalsIgnoreCase(currentLevelName)) { + if (_currentDirectory != "") _currentDirectory += "/"; + _currentDirectory += files[i].name(); + _currentDirectoryId = files[i].id(); + ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); + listNextDirectory(files[i]); + found = true; + break; + } + } + + if (!found) { + if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); + else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); + } +} + +void BoxResolveIdRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void BoxResolveIdRequest::handle() {} + +void BoxResolveIdRequest::restart() { start(); } + +void BoxResolveIdRequest::finishFile(StorageFile file) { + Request::finishSuccess(); + if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); +} + +} // End of namespace Box +} // End of namespace Cloud diff --git a/backends/cloud/box/boxresolveidrequest.h b/backends/cloud/box/boxresolveidrequest.h new file mode 100644 index 0000000000..3807549002 --- /dev/null +++ b/backends/cloud/box/boxresolveidrequest.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_BOX_BOXRESOLVEIDREQUEST_H +#define BACKENDS_CLOUD_BOX_BOXRESOLVEIDREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace Box { + +class BoxStorage; + +class BoxResolveIdRequest: public Networking::Request { + Common::String _requestedPath; + BoxStorage *_storage; + Storage::UploadCallback _uploadCallback; + Common::String _currentDirectory; + Common::String _currentDirectoryId; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void listNextDirectory(StorageFile fileToReturn); + void listedDirectoryCallback(Storage::FileArrayResponse response); + void listedDirectoryErrorCallback(Networking::ErrorResponse error); + void finishFile(StorageFile file); +public: + BoxResolveIdRequest(BoxStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive = false); //TODO: why upload? + virtual ~BoxResolveIdRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace Box +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 9842ed2796..65f90a51d2 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -23,6 +23,8 @@ #include "backends/cloud/box/boxstorage.h" #include "backends/cloud/box/boxlistdirectorybyidrequest.h" +#include "backends/cloud/box/boxlistdirectoryrequest.h" +#include "backends/cloud/box/boxresolveidrequest.h" #include "backends/cloud/box/boxtokenrefresher.h" #include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" @@ -210,11 +212,16 @@ void BoxStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCal delete response.value; } +Networking::Request *BoxStorage::resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &BoxStorage::printFile); + return addRequest(new BoxResolveIdRequest(this, path, callback, errorCallback)); +} + Networking::Request *BoxStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); if (!callback) callback = new Common::Callback(this, &BoxStorage::printFiles); - //return addRequest(new BoxListDirectoryRequest(this, path, callback, errorCallback, recursive)); - return nullptr; //TODO + return addRequest(new BoxListDirectoryRequest(this, path, callback, errorCallback, recursive)); } Networking::Request *BoxStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 3ce7a37f10..d0b4d1aa84 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -79,6 +79,9 @@ public: /** Public Cloud API comes down there. */ + /** Returns StorageFile with the resolved file's id. */ + virtual Networking::Request *resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback); + /** Returns ListDirectoryStatus struct with list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback); -- cgit v1.2.3 From 2b3caf1efadd2a68384978e77cfceab158c703f3 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 14:57:01 +0600 Subject: CLOUD: Add IdStorage This is a special base class for Storages which are using ids instead of paths in their APIs, like Box or Google Drive. This commit makes Box derived from IdStorage. --- backends/cloud/box/boxlistdirectoryrequest.cpp | 129 ------------------------- backends/cloud/box/boxlistdirectoryrequest.h | 66 ------------- backends/cloud/box/boxresolveidrequest.cpp | 125 ------------------------ backends/cloud/box/boxresolveidrequest.h | 60 ------------ backends/cloud/box/boxstorage.cpp | 49 +--------- backends/cloud/box/boxstorage.h | 15 +-- backends/cloud/id/idlistdirectoryrequest.cpp | 129 +++++++++++++++++++++++++ backends/cloud/id/idlistdirectoryrequest.h | 66 +++++++++++++ backends/cloud/id/idresolveidrequest.cpp | 125 ++++++++++++++++++++++++ backends/cloud/id/idresolveidrequest.h | 60 ++++++++++++ backends/cloud/id/idstorage.cpp | 86 +++++++++++++++++ backends/cloud/id/idstorage.h | 73 ++++++++++++++ 12 files changed, 548 insertions(+), 435 deletions(-) delete mode 100644 backends/cloud/box/boxlistdirectoryrequest.cpp delete mode 100644 backends/cloud/box/boxlistdirectoryrequest.h delete mode 100644 backends/cloud/box/boxresolveidrequest.cpp delete mode 100644 backends/cloud/box/boxresolveidrequest.h create mode 100644 backends/cloud/id/idlistdirectoryrequest.cpp create mode 100644 backends/cloud/id/idlistdirectoryrequest.h create mode 100644 backends/cloud/id/idresolveidrequest.cpp create mode 100644 backends/cloud/id/idresolveidrequest.h create mode 100644 backends/cloud/id/idstorage.cpp create mode 100644 backends/cloud/id/idstorage.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectoryrequest.cpp b/backends/cloud/box/boxlistdirectoryrequest.cpp deleted file mode 100644 index b35c8c80d5..0000000000 --- a/backends/cloud/box/boxlistdirectoryrequest.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* 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/box/boxlistdirectoryrequest.h" -#include "backends/cloud/box/boxstorage.h" - -namespace Cloud { -namespace Box { - -BoxListDirectoryRequest::BoxListDirectoryRequest(BoxStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): - Networking::Request(nullptr, ecb), - _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { - start(); -} - -BoxListDirectoryRequest::~BoxListDirectoryRequest() { - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - delete _listDirectoryCallback; -} - -void BoxListDirectoryRequest::start() { - //cleanup - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - _workingRequest = nullptr; - _files.clear(); - _directoriesQueue.clear(); - _currentDirectory = StorageFile(); - _ignoreCallback = false; - - //find out that directory's id - Storage::UploadCallback innerCallback = new Common::Callback(this, &BoxListDirectoryRequest::idResolvedCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &BoxListDirectoryRequest::idResolveErrorCallback); - _workingRequest = _storage->resolveFileId(_requestedPath, innerCallback, innerErrorCallback); -} - -void BoxListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); - - StorageFile directory = response.value; - directory.setPath(_requestedPath); - _directoriesQueue.push_back(directory); - listNextDirectory(); -} - -void BoxListDirectoryRequest::idResolveErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); - finishError(error); -} - -void BoxListDirectoryRequest::listNextDirectory() { - if (_directoriesQueue.empty()) { - finishListing(_files); - return; - } - - _currentDirectory = _directoriesQueue.back(); - _directoriesQueue.pop_back(); - - Storage::FileArrayCallback callback = new Common::Callback(this, &BoxListDirectoryRequest::listedDirectoryCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &BoxListDirectoryRequest::listedDirectoryErrorCallback); - _workingRequest = _storage->listDirectoryById(_currentDirectory.id(), callback, failureCallback); -} - -void BoxListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); - - for (uint32 i = 0; i < response.value.size(); ++i) { - StorageFile &file = response.value[i]; - Common::String path = _currentDirectory.path(); - if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') path += '/'; - path += file.name(); - file.setPath(path); - _files.push_back(file); - if (_requestedRecursive && file.isDirectory()) { - _directoriesQueue.push_back(file); - } - } - - listNextDirectory(); -} - -void BoxListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); - finishError(error); -} - -void BoxListDirectoryRequest::handle() {} - -void BoxListDirectoryRequest::restart() { start(); } - -Common::String BoxListDirectoryRequest::date() const { return _date; } - -void BoxListDirectoryRequest::finishListing(Common::Array &files) { - Request::finishSuccess(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); -} - -} // End of namespace Box -} // End of namespace Cloud diff --git a/backends/cloud/box/boxlistdirectoryrequest.h b/backends/cloud/box/boxlistdirectoryrequest.h deleted file mode 100644 index 7392cdd84c..0000000000 --- a/backends/cloud/box/boxlistdirectoryrequest.h +++ /dev/null @@ -1,66 +0,0 @@ -/* 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_BOX_BOXLISTDIRECTORYREQUEST_H -#define BACKENDS_CLOUD_BOX_BOXLISTDIRECTORYREQUEST_H - -#include "backends/cloud/storage.h" -#include "backends/networking/curl/request.h" -#include "common/callback.h" - -namespace Cloud { -namespace Box { - -class BoxStorage; - -class BoxListDirectoryRequest: public Networking::Request { - Common::String _requestedPath; - bool _requestedRecursive; - BoxStorage *_storage; - Storage::ListDirectoryCallback _listDirectoryCallback; - Common::Array _files; - Common::Array _directoriesQueue; - StorageFile _currentDirectory; - Request *_workingRequest; - bool _ignoreCallback; - Common::String _date; - - void start(); - void idResolvedCallback(Storage::UploadResponse response); - void idResolveErrorCallback(Networking::ErrorResponse error); - void listNextDirectory(); - void listedDirectoryCallback(Storage::FileArrayResponse response); - void listedDirectoryErrorCallback(Networking::ErrorResponse error); - void finishListing(Common::Array &files); -public: - BoxListDirectoryRequest(BoxStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); - virtual ~BoxListDirectoryRequest(); - - virtual void handle(); - virtual void restart(); - virtual Common::String date() const; -}; - -} // End of namespace Box -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/box/boxresolveidrequest.cpp b/backends/cloud/box/boxresolveidrequest.cpp deleted file mode 100644 index f07a94b92b..0000000000 --- a/backends/cloud/box/boxresolveidrequest.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* 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/box/boxresolveidrequest.h" -#include "backends/cloud/box/boxstorage.h" - -namespace Cloud { -namespace Box { - -BoxResolveIdRequest::BoxResolveIdRequest(BoxStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive): - Networking::Request(nullptr, ecb), - _requestedPath(path), _storage(storage), _uploadCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { - start(); -} - -BoxResolveIdRequest::~BoxResolveIdRequest() { - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - delete _uploadCallback; -} - -void BoxResolveIdRequest::start() { - //cleanup - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - _workingRequest = nullptr; - _currentDirectory = ""; - _currentDirectoryId = "0"; - _ignoreCallback = false; - - listNextDirectory(StorageFile(_currentDirectoryId, 0, 0, true)); -} - -void BoxResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { - if (_currentDirectory.equalsIgnoreCase(_requestedPath)) { - finishFile(fileToReturn); - return; - } - - Storage::FileArrayCallback callback = new Common::Callback(this, &BoxResolveIdRequest::listedDirectoryCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &BoxResolveIdRequest::listedDirectoryErrorCallback); - _workingRequest = _storage->listDirectoryById(_currentDirectoryId, callback, failureCallback); -} - -void BoxResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - - Common::String currentLevelName = _requestedPath; - ///debug("'%s'", currentLevelName.c_str()); - if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); - if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) currentLevelName.erase(0, 1); - ///debug("'%s'", currentLevelName.c_str()); - for (uint32 i = 0; i < currentLevelName.size(); ++i) { - if (currentLevelName[i] == '/' || currentLevelName[i] == '\\') { - currentLevelName.erase(i); - ///debug("'%s'", currentLevelName.c_str()); - break; - } - } - - Common::String path = _currentDirectory; - if (path != "") path += "/"; - path += currentLevelName; - bool lastLevel = (path.equalsIgnoreCase(_requestedPath)); - - ///debug("so, searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); - - Common::Array &files = response.value; - bool found = false; - for (uint32 i = 0; i < files.size(); ++i) { - if ((files[i].isDirectory() || lastLevel) && files[i].name().equalsIgnoreCase(currentLevelName)) { - if (_currentDirectory != "") _currentDirectory += "/"; - _currentDirectory += files[i].name(); - _currentDirectoryId = files[i].id(); - ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); - listNextDirectory(files[i]); - found = true; - break; - } - } - - if (!found) { - if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); - else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); - } -} - -void BoxResolveIdRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishError(error); -} - -void BoxResolveIdRequest::handle() {} - -void BoxResolveIdRequest::restart() { start(); } - -void BoxResolveIdRequest::finishFile(StorageFile file) { - Request::finishSuccess(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); -} - -} // End of namespace Box -} // End of namespace Cloud diff --git a/backends/cloud/box/boxresolveidrequest.h b/backends/cloud/box/boxresolveidrequest.h deleted file mode 100644 index 3807549002..0000000000 --- a/backends/cloud/box/boxresolveidrequest.h +++ /dev/null @@ -1,60 +0,0 @@ -/* 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_BOX_BOXRESOLVEIDREQUEST_H -#define BACKENDS_CLOUD_BOX_BOXRESOLVEIDREQUEST_H - -#include "backends/cloud/storage.h" -#include "backends/networking/curl/request.h" -#include "common/callback.h" - -namespace Cloud { -namespace Box { - -class BoxStorage; - -class BoxResolveIdRequest: public Networking::Request { - Common::String _requestedPath; - BoxStorage *_storage; - Storage::UploadCallback _uploadCallback; - Common::String _currentDirectory; - Common::String _currentDirectoryId; - Request *_workingRequest; - bool _ignoreCallback; - - void start(); - void listNextDirectory(StorageFile fileToReturn); - void listedDirectoryCallback(Storage::FileArrayResponse response); - void listedDirectoryErrorCallback(Networking::ErrorResponse error); - void finishFile(StorageFile file); -public: - BoxResolveIdRequest(BoxStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive = false); //TODO: why upload? - virtual ~BoxResolveIdRequest(); - - virtual void handle(); - virtual void restart(); -}; - -} // End of namespace Box -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 65f90a51d2..3681cbfaa8 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -23,8 +23,6 @@ #include "backends/cloud/box/boxstorage.h" #include "backends/cloud/box/boxlistdirectorybyidrequest.h" -#include "backends/cloud/box/boxlistdirectoryrequest.h" -#include "backends/cloud/box/boxresolveidrequest.h" #include "backends/cloud/box/boxtokenrefresher.h" #include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" @@ -178,17 +176,6 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking delete json; } -void BoxStorage::printJson(Networking::JsonResponse response) { - Common::JSONValue *json = response.value; - if (!json) { - warning("printJson: NULL"); - return; - } - - debug("%s", json->stringify().c_str()); - delete json; -} - void BoxStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { if (!response.value) { warning("fileInfoCallback: NULL"); @@ -212,21 +199,9 @@ void BoxStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCal delete response.value; } -Networking::Request *BoxStorage::resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &BoxStorage::printFile); - return addRequest(new BoxResolveIdRequest(this, path, callback, errorCallback)); -} - -Networking::Request *BoxStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &BoxStorage::printFiles); - return addRequest(new BoxListDirectoryRequest(this, path, callback, errorCallback, recursive)); -} - Networking::Request *BoxStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &BoxStorage::printFiles); + if (!callback) callback = getPrintFilesCallback(); return addRequest(new BoxListDirectoryByIdRequest(this, id, callback, errorCallback)); } @@ -251,24 +226,6 @@ void BoxStorage::fileDownloaded(BoolResponse response) { else debug("download failed!"); } -void BoxStorage::printFiles(FileArrayResponse response) { - debug("files:"); - Common::Array &files = response.value; - for (uint32 i = 0; i < files.size(); ++i) - debug("\t%s", files[i].path().c_str()); -} - -void BoxStorage::printBool(BoolResponse response) { - debug("bool: %s", response.value ? "true" : "false"); -} - -void BoxStorage::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()); -} - Networking::Request *BoxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); //return addRequest(new BoxCreateDirectoryRequest(this, path, callback, errorCallback)); @@ -307,5 +264,9 @@ Common::String BoxStorage::getAuthLink() { return ""; } +Common::String BoxStorage::getRootDirectoryId() { + return "0"; +} + } // End of namespace Box } // End of namespace Cloud diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index d0b4d1aa84..865358c845 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -23,14 +23,14 @@ #ifndef BACKENDS_CLOUD_BOX_BOXSTORAGE_H #define BACKENDS_CLOUD_BOX_BOXSTORAGE_H -#include "backends/cloud/storage.h" +#include "backends/cloud/id/idstorage.h" #include "common/callback.h" #include "backends/networking/curl/curljsonrequest.h" namespace Cloud { namespace Box { -class BoxStorage: public Cloud::Storage { +class BoxStorage: public Id::IdStorage { static char *KEY, *SECRET; static void loadKeyAndSecret(); @@ -46,11 +46,7 @@ class BoxStorage: public Cloud::Storage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); - void printJson(Networking::JsonResponse response); void fileDownloaded(BoolResponse response); - void printFiles(FileArrayResponse response); - void printBool(BoolResponse response); - void printFile(UploadResponse response); void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); public: @@ -79,11 +75,6 @@ public: /** Public Cloud API comes down there. */ - /** Returns StorageFile with the resolved file's id. */ - virtual Networking::Request *resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback); - - /** Returns ListDirectoryStatus struct with list of files. */ - virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback); /** Returns UploadStatus struct with info about uploaded file. */ @@ -115,6 +106,8 @@ public: */ static Common::String getAuthLink(); + virtual Common::String getRootDirectoryId(); + /** * Gets new access_token. If passed is "", refresh_token is used. * Use "" in order to refresh token and pass a callback, so you could diff --git a/backends/cloud/id/idlistdirectoryrequest.cpp b/backends/cloud/id/idlistdirectoryrequest.cpp new file mode 100644 index 0000000000..012065dc77 --- /dev/null +++ b/backends/cloud/id/idlistdirectoryrequest.cpp @@ -0,0 +1,129 @@ +/* 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/id/idlistdirectoryrequest.h" +#include "backends/cloud/id/idstorage.h" + +namespace Cloud { +namespace Id { + +IdListDirectoryRequest::IdListDirectoryRequest(IdStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), + _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +IdListDirectoryRequest::~IdListDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _listDirectoryCallback; +} + +void IdListDirectoryRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _files.clear(); + _directoriesQueue.clear(); + _currentDirectory = StorageFile(); + _ignoreCallback = false; + + //find out that directory's id + Storage::UploadCallback innerCallback = new Common::Callback(this, &IdListDirectoryRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdListDirectoryRequest::idResolveErrorCallback); + _workingRequest = _storage->resolveFileId(_requestedPath, innerCallback, innerErrorCallback); +} + +void IdListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + + StorageFile directory = response.value; + directory.setPath(_requestedPath); + _directoriesQueue.push_back(directory); + listNextDirectory(); +} + +void IdListDirectoryRequest::idResolveErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + finishError(error); +} + +void IdListDirectoryRequest::listNextDirectory() { + if (_directoriesQueue.empty()) { + finishListing(_files); + return; + } + + _currentDirectory = _directoriesQueue.back(); + _directoriesQueue.pop_back(); + + Storage::FileArrayCallback callback = new Common::Callback(this, &IdListDirectoryRequest::listedDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &IdListDirectoryRequest::listedDirectoryErrorCallback); + _workingRequest = _storage->listDirectoryById(_currentDirectory.id(), callback, failureCallback); +} + +void IdListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + + for (uint32 i = 0; i < response.value.size(); ++i) { + StorageFile &file = response.value[i]; + Common::String path = _currentDirectory.path(); + if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') path += '/'; + path += file.name(); + file.setPath(path); + _files.push_back(file); + if (_requestedRecursive && file.isDirectory()) { + _directoriesQueue.push_back(file); + } + } + + listNextDirectory(); +} + +void IdListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + finishError(error); +} + +void IdListDirectoryRequest::handle() {} + +void IdListDirectoryRequest::restart() { start(); } + +Common::String IdListDirectoryRequest::date() const { return _date; } + +void IdListDirectoryRequest::finishListing(Common::Array &files) { + Request::finishSuccess(); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); +} + +} // End of namespace Id +} // End of namespace Cloud diff --git a/backends/cloud/id/idlistdirectoryrequest.h b/backends/cloud/id/idlistdirectoryrequest.h new file mode 100644 index 0000000000..58c5d2c864 --- /dev/null +++ b/backends/cloud/id/idlistdirectoryrequest.h @@ -0,0 +1,66 @@ +/* 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_ID_IDLISTDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_ID_IDLISTDIRECTORYREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace Id { + +class IdStorage; + +class IdListDirectoryRequest: public Networking::Request { + Common::String _requestedPath; + bool _requestedRecursive; + IdStorage *_storage; + Storage::ListDirectoryCallback _listDirectoryCallback; + Common::Array _files; + Common::Array _directoriesQueue; + StorageFile _currentDirectory; + Request *_workingRequest; + bool _ignoreCallback; + Common::String _date; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveErrorCallback(Networking::ErrorResponse error); + void listNextDirectory(); + void listedDirectoryCallback(Storage::FileArrayResponse response); + void listedDirectoryErrorCallback(Networking::ErrorResponse error); + void finishListing(Common::Array &files); +public: + IdListDirectoryRequest(IdStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); + virtual ~IdListDirectoryRequest(); + + virtual void handle(); + virtual void restart(); + virtual Common::String date() const; +}; + +} // End of namespace Id +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/id/idresolveidrequest.cpp b/backends/cloud/id/idresolveidrequest.cpp new file mode 100644 index 0000000000..fc61137088 --- /dev/null +++ b/backends/cloud/id/idresolveidrequest.cpp @@ -0,0 +1,125 @@ +/* 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/id/idresolveidrequest.h" +#include "backends/cloud/id/idstorage.h" + +namespace Cloud { +namespace Id { + +IdResolveIdRequest::IdResolveIdRequest(IdStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive): + Networking::Request(nullptr, ecb), + _requestedPath(path), _storage(storage), _uploadCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +IdResolveIdRequest::~IdResolveIdRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _uploadCallback; +} + +void IdResolveIdRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _currentDirectory = ""; + _currentDirectoryId = _storage->getRootDirectoryId(); + _ignoreCallback = false; + + listNextDirectory(StorageFile(_currentDirectoryId, 0, 0, true)); +} + +void IdResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { + if (_currentDirectory.equalsIgnoreCase(_requestedPath)) { + finishFile(fileToReturn); + return; + } + + Storage::FileArrayCallback callback = new Common::Callback(this, &IdResolveIdRequest::listedDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &IdResolveIdRequest::listedDirectoryErrorCallback); + _workingRequest = _storage->listDirectoryById(_currentDirectoryId, callback, failureCallback); +} + +void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Common::String currentLevelName = _requestedPath; + ///debug("'%s'", currentLevelName.c_str()); + if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); + if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) currentLevelName.erase(0, 1); + ///debug("'%s'", currentLevelName.c_str()); + for (uint32 i = 0; i < currentLevelName.size(); ++i) { + if (currentLevelName[i] == '/' || currentLevelName[i] == '\\') { + currentLevelName.erase(i); + ///debug("'%s'", currentLevelName.c_str()); + break; + } + } + + Common::String path = _currentDirectory; + if (path != "") path += "/"; + path += currentLevelName; + bool lastLevel = (path.equalsIgnoreCase(_requestedPath)); + + ///debug("so, searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); + + Common::Array &files = response.value; + bool found = false; + for (uint32 i = 0; i < files.size(); ++i) { + if ((files[i].isDirectory() || lastLevel) && files[i].name().equalsIgnoreCase(currentLevelName)) { + if (_currentDirectory != "") _currentDirectory += "/"; + _currentDirectory += files[i].name(); + _currentDirectoryId = files[i].id(); + ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); + listNextDirectory(files[i]); + found = true; + break; + } + } + + if (!found) { + if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); + else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); + } +} + +void IdResolveIdRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void IdResolveIdRequest::handle() {} + +void IdResolveIdRequest::restart() { start(); } + +void IdResolveIdRequest::finishFile(StorageFile file) { + Request::finishSuccess(); + if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); +} + +} // End of namespace Id +} // End of namespace Cloud diff --git a/backends/cloud/id/idresolveidrequest.h b/backends/cloud/id/idresolveidrequest.h new file mode 100644 index 0000000000..94d4af5030 --- /dev/null +++ b/backends/cloud/id/idresolveidrequest.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_ID_IDRESOLVEIDREQUEST_H +#define BACKENDS_CLOUD_ID_IDRESOLVEIDREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace Id { + +class IdStorage; + +class IdResolveIdRequest: public Networking::Request { + Common::String _requestedPath; + IdStorage *_storage; + Storage::UploadCallback _uploadCallback; + Common::String _currentDirectory; + Common::String _currentDirectoryId; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void listNextDirectory(StorageFile fileToReturn); + void listedDirectoryCallback(Storage::FileArrayResponse response); + void listedDirectoryErrorCallback(Networking::ErrorResponse error); + void finishFile(StorageFile file); +public: + IdResolveIdRequest(IdStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive = false); //TODO: why upload? + virtual ~IdResolveIdRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace Id +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp new file mode 100644 index 0000000000..aed1738d4f --- /dev/null +++ b/backends/cloud/id/idstorage.cpp @@ -0,0 +1,86 @@ +/* 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. +* +*/ +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/cloud/id/idstorage.h" +#include "backends/cloud/id/idlistdirectoryrequest.h" +#include "backends/cloud/id/idresolveidrequest.h" +#include "common/debug.h" +#include "common/json.h" + +namespace Cloud { +namespace Id { + +IdStorage::~IdStorage() {} + +void IdStorage::printJson(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("printJson: NULL"); + return; + } + + debug("%s", json->stringify().c_str()); + delete json; +} + +void IdStorage::printFiles(FileArrayResponse response) { + debug("files:"); + Common::Array &files = response.value; + for (uint32 i = 0; i < files.size(); ++i) { + debug("\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); + debug("\t%s", files[i].path().c_str()); + debug("\t%s", files[i].id().c_str()); + debug(" "); + } +} + +void IdStorage::printBool(BoolResponse response) { + debug("bool: %s", response.value ? "true" : "false"); +} + +void IdStorage::printFile(UploadResponse response) { + debug("\nuploaded file info:"); + debug("\tid: %s", response.value.path().c_str()); + debug("\tname: %s", response.value.name().c_str()); + debug("\tsize: %u", response.value.size()); + debug("\ttimestamp: %u", response.value.timestamp()); +} + +Storage::ListDirectoryCallback IdStorage::getPrintFilesCallback() { + return new Common::Callback(this, &IdStorage::printFiles); +} + +Networking::Request *IdStorage::resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &IdStorage::printFile); + return addRequest(new IdResolveIdRequest(this, path, callback, errorCallback)); +} + +Networking::Request *IdStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &IdStorage::printFiles); + return addRequest(new IdListDirectoryRequest(this, path, callback, errorCallback, recursive)); +} + +} // End of namespace Id +} // End of namespace Cloud diff --git a/backends/cloud/id/idstorage.h b/backends/cloud/id/idstorage.h new file mode 100644 index 0000000000..a5e1c1e22c --- /dev/null +++ b/backends/cloud/id/idstorage.h @@ -0,0 +1,73 @@ +/* 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_ID_IDSTORAGE_H +#define BACKENDS_CLOUD_ID_IDSTORAGE_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/curljsonrequest.h" + +/* + * Id::IdStorage is a special base class, which is created + * to simplify adding new storages which use ids instead of + * paths in their API. + * + * Some Requests are already implemented, and Storage based + * on IdStorage needs to override/implement a few basic things. + * + * For example, ListDirectoryRequest and ResolveIdRequests are + * based on listDirectoryById() and getRootDirectoryId() methods. + * Implementing these you'll get id resolving and directory + * listing by path. + */ + +namespace Cloud { +namespace Id { + +class IdStorage: public Cloud::Storage { +protected: + void printJson(Networking::JsonResponse response); + void printFiles(FileArrayResponse response); + void printBool(BoolResponse response); + void printFile(UploadResponse response); + + ListDirectoryCallback getPrintFilesCallback(); + +public: + virtual ~IdStorage(); + + /** Public Cloud API comes down there. */ + + /** Returns StorageFile with the resolved file's id. */ + virtual Networking::Request *resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback); + + /** Returns ListDirectoryStatus struct with list of files. */ + virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); + virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) = 0; + + virtual Common::String getRootDirectoryId() = 0; +}; + +} // End of namespace Id +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From d943d7c3a805afb14755cb95ea29bbf91358bbd6 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 15:20:15 +0600 Subject: CLOUD: Add IdCreateDirectoryRequest Box gets createDirectoryWithParentId(), so now creating directories works there. --- backends/cloud/box/boxstorage.cpp | 47 ++++++-- backends/cloud/box/boxstorage.h | 5 +- backends/cloud/id/idcreatedirectoryrequest.cpp | 146 +++++++++++++++++++++++++ backends/cloud/id/idcreatedirectoryrequest.h | 65 +++++++++++ backends/cloud/id/idstorage.cpp | 19 ++++ backends/cloud/id/idstorage.h | 4 + 6 files changed, 276 insertions(+), 10 deletions(-) create mode 100644 backends/cloud/id/idcreatedirectoryrequest.cpp create mode 100644 backends/cloud/id/idcreatedirectoryrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 3681cbfaa8..5bbe377163 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -205,6 +205,45 @@ Networking::Request *BoxStorage::listDirectoryById(Common::String id, ListDirect return addRequest(new BoxListDirectoryByIdRequest(this, id, callback, errorCallback)); } +void BoxStorage::createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + if (!json) { + warning("NULL passed instead of JSON"); + delete outerCallback; + return; + } + + if (outerCallback) { + Common::JSONObject info = json->asObject(); + (*outerCallback)(BoolResponse(nullptr, info.contains("id"))); + delete outerCallback; + } + + delete json; +} + +Networking::Request *BoxStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + + Common::String url = "https://api.box.com/2.0/folders"; + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::createDirectoryInnerCallback, callback); + Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + accessToken()); + request->addHeader("Content-Type: application/json"); + + Common::JSONObject parentObject; + parentObject.setVal("id", new Common::JSONValue(parentId)); + + Common::JSONObject jsonRequestParameters; + jsonRequestParameters.setVal("name", new Common::JSONValue(name)); + jsonRequestParameters.setVal("parent", new Common::JSONValue(parentObject)); + + Common::JSONValue value(jsonRequestParameters); + request->addPostField(Common::JSON::stringify(&value)); + + return addRequest(request); +} + Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { //return addRequest(new BoxUploadRequest(this, path, contents, callback, errorCallback)); return nullptr; //TODO @@ -226,12 +265,6 @@ void BoxStorage::fileDownloaded(BoolResponse response) { else debug("download failed!"); } -Networking::Request *BoxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - //return addRequest(new BoxCreateDirectoryRequest(this, path, callback, errorCallback)); - return nullptr; //TODO -} - Networking::Request *BoxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::infoInnerCallback, callback); Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.box.com/2.0/users/me"); @@ -239,7 +272,7 @@ Networking::Request *BoxStorage::info(StorageInfoCallback callback, Networking:: return addRequest(request); } -Common::String BoxStorage::savesDirectoryPath() { return "saves/"; } +Common::String BoxStorage::savesDirectoryPath() { return "scummvm/saves/"; } BoxStorage *BoxStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 865358c845..3b02f88212 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -49,6 +49,7 @@ class BoxStorage: public Id::IdStorage { void fileDownloaded(BoolResponse response); void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); + void createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response); public: /** This constructor uses OAuth code flow to get tokens. */ BoxStorage(Common::String code); @@ -76,6 +77,7 @@ public: /** Public Cloud API comes down there. */ virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Returns UploadStatus struct with info about uploaded file. */ virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); @@ -86,9 +88,6 @@ public: /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Calls the callback when finished. */ - virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); - /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); diff --git a/backends/cloud/id/idcreatedirectoryrequest.cpp b/backends/cloud/id/idcreatedirectoryrequest.cpp new file mode 100644 index 0000000000..7968a4b126 --- /dev/null +++ b/backends/cloud/id/idcreatedirectoryrequest.cpp @@ -0,0 +1,146 @@ +/* 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/id/idcreatedirectoryrequest.h" +#include "backends/cloud/id/idstorage.h" +#include "common/debug.h" + +namespace Cloud { +namespace Id { + +IdCreateDirectoryRequest::IdCreateDirectoryRequest(IdStorage *storage, Common::String parentPath, Common::String directoryName, Storage::BoolCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), + _requestedParentPath(parentPath), _requestedDirectoryName(directoryName), _storage(storage), _boolCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +IdCreateDirectoryRequest::~IdCreateDirectoryRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; +} + +void IdCreateDirectoryRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _ignoreCallback = false; + + //the only exception when we create parent folder - is when it's ScummVM/ base folder + Common::String prefix = _requestedParentPath; + if (prefix.size() > 7) prefix.erase(7); + if (prefix.equalsIgnoreCase("ScummVM")) { + Storage::BoolCallback callback = new Common::Callback(this, &IdCreateDirectoryRequest::createdBaseDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &IdCreateDirectoryRequest::createdBaseDirectoryErrorCallback); + _workingRequest = _storage->createDirectory("ScummVM", callback, failureCallback); + return; + } + + resolveId(); +} + +void IdCreateDirectoryRequest::createdBaseDirectoryCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + resolveId(); +} + +void IdCreateDirectoryRequest::createdBaseDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + finishError(error); +} + +void IdCreateDirectoryRequest::resolveId() { + //check whether such folder already exists + Storage::UploadCallback innerCallback = new Common::Callback(this, &IdCreateDirectoryRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdCreateDirectoryRequest::idResolveFailedCallback); + Common::String path = _requestedParentPath; + if (_requestedParentPath != "") path += "/"; + path += _requestedDirectoryName; + _workingRequest = _storage->resolveFileId(path, innerCallback, innerErrorCallback); +} + +void IdCreateDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + + //resolved => folder already exists + finishCreation(false); +} + +void IdCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + + //not resolved => folder not exists + if (error.response.contains("no such file found in its parent directory")) { + //parent's id after the '\n' + Common::String parentId = error.response; + for (uint32 i = 0; i < parentId.size(); ++i) + if (parentId[i] == '\n') { + parentId.erase(0, i+1); + break; + } + + Storage::BoolCallback callback = new Common::Callback(this, &IdCreateDirectoryRequest::createdDirectoryCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &IdCreateDirectoryRequest::createdDirectoryErrorCallback); + _workingRequest = _storage->createDirectoryWithParentId(parentId, _requestedDirectoryName, callback, failureCallback); + return; + } + + finishError(error); +} + +void IdCreateDirectoryRequest::createdDirectoryCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (response.request) _date = response.request->date(); + finishCreation(response.value); +} + +void IdCreateDirectoryRequest::createdDirectoryErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + if (error.request) _date = error.request->date(); + finishError(error); +} + +void IdCreateDirectoryRequest::handle() {} + +void IdCreateDirectoryRequest::restart() { start(); } + +Common::String IdCreateDirectoryRequest::date() const { return _date; } + +void IdCreateDirectoryRequest::finishCreation(bool success) { + Request::finishSuccess(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +} // End of namespace Id +} // End of namespace Cloud diff --git a/backends/cloud/id/idcreatedirectoryrequest.h b/backends/cloud/id/idcreatedirectoryrequest.h new file mode 100644 index 0000000000..241bcd30be --- /dev/null +++ b/backends/cloud/id/idcreatedirectoryrequest.h @@ -0,0 +1,65 @@ +/* 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_ID_IDCREATEDIRECTORYREQUEST_H +#define BACKENDS_CLOUD_ID_IDCREATEDIRECTORYREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace Id { + +class IdStorage; + +class IdCreateDirectoryRequest: public Networking::Request { + Common::String _requestedParentPath; + Common::String _requestedDirectoryName; + IdStorage *_storage; + Storage::BoolCallback _boolCallback; + Request *_workingRequest; + bool _ignoreCallback; + Common::String _date; + + void start(); + void createdBaseDirectoryCallback(Storage::BoolResponse response); + void createdBaseDirectoryErrorCallback(Networking::ErrorResponse error); + void resolveId(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void createdDirectoryCallback(Storage::BoolResponse response); + void createdDirectoryErrorCallback(Networking::ErrorResponse error); + void finishCreation(bool success); +public: + IdCreateDirectoryRequest(IdStorage *storage, Common::String parentPath, Common::String directoryName, Storage::BoolCallback cb, Networking::ErrorCallback ecb); + virtual ~IdCreateDirectoryRequest(); + + virtual void handle(); + virtual void restart(); + virtual Common::String date() const; +}; + +} // End of namespace Id +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index aed1738d4f..f26dee4692 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -22,6 +22,7 @@ #define FORBIDDEN_SYMBOL_ALLOW_ALL #include "backends/cloud/id/idstorage.h" +#include "backends/cloud/id/idcreatedirectoryrequest.h" #include "backends/cloud/id/idlistdirectoryrequest.h" #include "backends/cloud/id/idresolveidrequest.h" #include "common/debug.h" @@ -82,5 +83,23 @@ Networking::Request *IdStorage::listDirectory(Common::String path, ListDirectory return addRequest(new IdListDirectoryRequest(this, path, callback, errorCallback, recursive)); } +Networking::Request *IdStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &IdStorage::printBool); + + //find out the parent path and directory name + Common::String parentPath = "", directoryName = path; + for (uint32 i = path.size(); i > 0; --i) { + if (path[i - 1] == '/' || path[i - 1] == '\\') { + parentPath = path; + parentPath.erase(i - 1); + directoryName.erase(0, i); + break; + } + } + + return addRequest(new IdCreateDirectoryRequest(this, parentPath, directoryName, callback, errorCallback)); +} + } // End of namespace Id } // End of namespace Cloud diff --git a/backends/cloud/id/idstorage.h b/backends/cloud/id/idstorage.h index a5e1c1e22c..a657f5cd95 100644 --- a/backends/cloud/id/idstorage.h +++ b/backends/cloud/id/idstorage.h @@ -64,6 +64,10 @@ public: virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) = 0; + /** Calls the callback when finished. */ + virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; + virtual Common::String getRootDirectoryId() = 0; }; -- cgit v1.2.3 From 34ee1d29d5597e4914f5e06c7770137f4dd856d7 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 15:47:28 +0600 Subject: CLOUD: Fix Storage::streamFile() --- backends/cloud/storage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 4e3dc435a6..2cf851f3ba 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -87,7 +87,7 @@ Networking::Request *Storage::upload(Common::String remotePath, Common::String l Networking::Request *Storage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { //most Storages use paths instead of ids, so this should work - return streamFile(path, callback, errorCallback); + return streamFileById(path, callback, errorCallback); } Networking::Request *Storage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { -- cgit v1.2.3 From 19ae61dffc2541e855c1376a52e461f199af2f99 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 15:48:55 +0600 Subject: CLOUD: Add IdDownloadRequest and IdStreamFileRequest Used for downloading files in Box. --- backends/cloud/box/boxstorage.cpp | 21 ++++--- backends/cloud/id/iddownloadrequest.cpp | 91 +++++++++++++++++++++++++++++++ backends/cloud/id/iddownloadrequest.h | 59 ++++++++++++++++++++ backends/cloud/id/idstorage.cpp | 10 ++++ backends/cloud/id/idstorage.h | 7 +++ backends/cloud/id/idstreamfilerequest.cpp | 91 +++++++++++++++++++++++++++++++ backends/cloud/id/idstreamfilerequest.h | 59 ++++++++++++++++++++ 7 files changed, 329 insertions(+), 9 deletions(-) create mode 100644 backends/cloud/id/iddownloadrequest.cpp create mode 100644 backends/cloud/id/iddownloadrequest.h create mode 100644 backends/cloud/id/idstreamfilerequest.cpp create mode 100644 backends/cloud/id/idstreamfilerequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 5bbe377163..1fbe2f17aa 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -249,15 +249,18 @@ Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableRea return nullptr; //TODO } -Networking::Request *BoxStorage::streamFileById(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { - /* - Common::String url = "https://api.Box.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(path); - Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::fileInfoCallback, outerCallback); - Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, url.c_str()); - request->addHeader("Authorization: Bearer " + _token); - return addRequest(request); - */ - return nullptr; //TODO +Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { + if (callback) { + Common::String url = "https://api.box.com/2.0/files/" + id + "/content"; + debug("%s", url.c_str()); + Common::String header = "Authorization: Bearer " + _token; + curl_slist *headersList = curl_slist_append(nullptr, header.c_str()); + Networking::NetworkReadStream *stream = new Networking::NetworkReadStream(url.c_str(), headersList, ""); + (*callback)(Networking::NetworkReadStreamResponse(nullptr, stream)); + } + delete callback; + delete errorCallback; + return nullptr; } void BoxStorage::fileDownloaded(BoolResponse response) { diff --git a/backends/cloud/id/iddownloadrequest.cpp b/backends/cloud/id/iddownloadrequest.cpp new file mode 100644 index 0000000000..154bd16edd --- /dev/null +++ b/backends/cloud/id/iddownloadrequest.cpp @@ -0,0 +1,91 @@ +/* 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/id/iddownloadrequest.h" +#include "backends/cloud/id/idstorage.h" + +namespace Cloud { +namespace Id { + +IdDownloadRequest::IdDownloadRequest(IdStorage *storage, Common::String remotePath, Common::String localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _requestedFile(remotePath), _requestedLocalFile(localPath), _storage(storage), _boolCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +IdDownloadRequest::~IdDownloadRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _boolCallback; +} + +void IdDownloadRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _ignoreCallback = false; + + //find file's id + Storage::UploadCallback innerCallback = new Common::Callback(this, &IdDownloadRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdDownloadRequest::idResolveFailedCallback); + _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); +} + +void IdDownloadRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Storage::BoolCallback innerCallback = new Common::Callback(this, &IdDownloadRequest::downloadCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdDownloadRequest::downloadErrorCallback); + _workingRequest = _storage->downloadById(response.value.id(), _requestedLocalFile, innerCallback, innerErrorCallback); +} + +void IdDownloadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void IdDownloadRequest::downloadCallback(Storage::BoolResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishDownload(response.value); +} + +void IdDownloadRequest::downloadErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void IdDownloadRequest::handle() {} + +void IdDownloadRequest::restart() { start(); } + +void IdDownloadRequest::finishDownload(bool success) { + Request::finishSuccess(); + if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); +} + +} // End of namespace Id +} // End of namespace Cloud diff --git a/backends/cloud/id/iddownloadrequest.h b/backends/cloud/id/iddownloadrequest.h new file mode 100644 index 0000000000..70397696a8 --- /dev/null +++ b/backends/cloud/id/iddownloadrequest.h @@ -0,0 +1,59 @@ +/* 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_ID_IDDOWNLOADREQUEST_H +#define BACKENDS_CLOUD_ID_IDDOWNLOADREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace Id { + +class IdStorage; + +class IdDownloadRequest: public Networking::Request { + Common::String _requestedFile, _requestedLocalFile; + IdStorage *_storage; + Storage::BoolCallback _boolCallback; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void downloadCallback(Storage::BoolResponse response); + void downloadErrorCallback(Networking::ErrorResponse error); + void finishDownload(bool success); +public: + IdDownloadRequest(IdStorage *storage, Common::String remotePath, Common::String localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb); + virtual ~IdDownloadRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace Id +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index f26dee4692..3aeb5146cd 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -23,8 +23,10 @@ #include "backends/cloud/id/idstorage.h" #include "backends/cloud/id/idcreatedirectoryrequest.h" +#include "backends/cloud/id/iddownloadrequest.h" #include "backends/cloud/id/idlistdirectoryrequest.h" #include "backends/cloud/id/idresolveidrequest.h" +#include "backends/cloud/id/idstreamfilerequest.h" #include "common/debug.h" #include "common/json.h" @@ -101,5 +103,13 @@ Networking::Request *IdStorage::createDirectory(Common::String path, BoolCallbac return addRequest(new IdCreateDirectoryRequest(this, parentPath, directoryName, callback, errorCallback)); } +Networking::Request *IdStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { + return addRequest(new IdStreamFileRequest(this, path, outerCallback, errorCallback)); +} + +Networking::Request *IdStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { + return addRequest(new IdDownloadRequest(this, remotePath, localPath, callback, errorCallback)); +} + } // End of namespace Id } // End of namespace Cloud diff --git a/backends/cloud/id/idstorage.h b/backends/cloud/id/idstorage.h index a657f5cd95..88853e4ad8 100644 --- a/backends/cloud/id/idstorage.h +++ b/backends/cloud/id/idstorage.h @@ -68,6 +68,13 @@ public: virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); virtual Networking::Request *createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; + /** Returns pointer to Networking::NetworkReadStream. */ + virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); + virtual Networking::Request *streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0; + + /** Calls the callback when finished. */ + virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); + virtual Common::String getRootDirectoryId() = 0; }; diff --git a/backends/cloud/id/idstreamfilerequest.cpp b/backends/cloud/id/idstreamfilerequest.cpp new file mode 100644 index 0000000000..08060b9e40 --- /dev/null +++ b/backends/cloud/id/idstreamfilerequest.cpp @@ -0,0 +1,91 @@ +/* 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/id/idstreamfilerequest.h" +#include "backends/cloud/id/idstorage.h" + +namespace Cloud { +namespace Id { + +IdStreamFileRequest::IdStreamFileRequest(IdStorage *storage, Common::String path, Networking::NetworkReadStreamCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _requestedFile(path), _storage(storage), _streamCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +IdStreamFileRequest::~IdStreamFileRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _streamCallback; +} + +void IdStreamFileRequest::start() { + //cleanup + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _workingRequest = nullptr; + _ignoreCallback = false; + + //find file's id + Storage::UploadCallback innerCallback = new Common::Callback(this, &IdStreamFileRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdStreamFileRequest::idResolveFailedCallback); + _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); +} + +void IdStreamFileRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Networking::NetworkReadStreamCallback innerCallback = new Common::Callback(this, &IdStreamFileRequest::streamFileCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdStreamFileRequest::streamFileErrorCallback); + _workingRequest = _storage->streamFileById(response.value.id(), innerCallback, innerErrorCallback); +} + +void IdStreamFileRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void IdStreamFileRequest::streamFileCallback(Networking::NetworkReadStreamResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishStream(response.value); +} + +void IdStreamFileRequest::streamFileErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void IdStreamFileRequest::handle() {} + +void IdStreamFileRequest::restart() { start(); } + +void IdStreamFileRequest::finishStream(Networking::NetworkReadStream *stream) { + Request::finishSuccess(); + if (_streamCallback) (*_streamCallback)(Networking::NetworkReadStreamResponse(this, stream)); +} + +} // End of namespace Id +} // End of namespace Cloud diff --git a/backends/cloud/id/idstreamfilerequest.h b/backends/cloud/id/idstreamfilerequest.h new file mode 100644 index 0000000000..20d7c0c25b --- /dev/null +++ b/backends/cloud/id/idstreamfilerequest.h @@ -0,0 +1,59 @@ +/* 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_ID_IDSTREAMFILEREQUEST_H +#define BACKENDS_CLOUD_ID_IDSTREAMFILEREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "common/callback.h" + +namespace Cloud { +namespace Id { + +class IdStorage; + +class IdStreamFileRequest: public Networking::Request { + Common::String _requestedFile; + IdStorage *_storage; + Networking::NetworkReadStreamCallback _streamCallback; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void streamFileCallback(Networking::NetworkReadStreamResponse response); + void streamFileErrorCallback(Networking::ErrorResponse error); + void finishStream(Networking::NetworkReadStream *stream); +public: + IdStreamFileRequest(IdStorage *storage, Common::String path, Networking::NetworkReadStreamCallback cb, Networking::ErrorCallback ecb); + virtual ~IdStreamFileRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace Id +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From 16ed625dfefd7cc71e5d4088d0714fb09332a9c3 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 15:49:40 +0600 Subject: CLOUD: Remove BoxStorage::streamFileById debug() call --- backends/cloud/box/boxstorage.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 1fbe2f17aa..e14157ccf2 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -252,7 +252,6 @@ Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableRea Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { if (callback) { Common::String url = "https://api.box.com/2.0/files/" + id + "/content"; - debug("%s", url.c_str()); Common::String header = "Authorization: Bearer " + _token; curl_slist *headersList = curl_slist_append(nullptr, header.c_str()); Networking::NetworkReadStream *stream = new Networking::NetworkReadStream(url.c_str(), headersList, ""); -- cgit v1.2.3 From d96cdacb38afd9394ab442e7b5a74cc87a495092 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 13 Jul 2016 20:05:56 +0600 Subject: CLOUD: Add BoxUploadRequest --- backends/cloud/box/boxstorage.cpp | 10 +- backends/cloud/box/boxstorage.h | 1 + backends/cloud/box/boxuploadrequest.cpp | 213 ++++++++++++++++++++++++++++++++ backends/cloud/box/boxuploadrequest.h | 63 ++++++++++ 4 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 backends/cloud/box/boxuploadrequest.cpp create mode 100644 backends/cloud/box/boxuploadrequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index e14157ccf2..628d18b89a 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -24,6 +24,7 @@ #include "backends/cloud/box/boxstorage.h" #include "backends/cloud/box/boxlistdirectorybyidrequest.h" #include "backends/cloud/box/boxtokenrefresher.h" +#include "backends/cloud/box/boxuploadrequest.h" #include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" @@ -244,9 +245,14 @@ Networking::Request *BoxStorage::createDirectoryWithParentId(Common::String pare return addRequest(request); } +Networking::Request *BoxStorage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + return addRequest(new BoxUploadRequest(this, remotePath, localPath, callback, errorCallback)); +} + Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { - //return addRequest(new BoxUploadRequest(this, path, contents, callback, errorCallback)); - return nullptr; //TODO + warning("BoxStorage::upload(ReadStream) not implemented"); + return nullptr; } Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 3b02f88212..93afe4fabb 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -80,6 +80,7 @@ public: virtual Networking::Request *createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback); /** Returns UploadStatus struct with info about uploaded file. */ + virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback); virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); /** Returns pointer to Networking::NetworkReadStream. */ diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp new file mode 100644 index 0000000000..c94494efac --- /dev/null +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -0,0 +1,213 @@ +/* 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/box/boxuploadrequest.h" +#include "backends/cloud/box/boxstorage.h" +#include "backends/cloud/box/boxtokenrefresher.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" + +namespace Cloud { +namespace Box { + +BoxUploadRequest::BoxUploadRequest(BoxStorage *storage, Common::String path, Common::String localPath, Storage::UploadCallback callback, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _storage(storage), _savePath(path), _localPath(localPath), _uploadCallback(callback), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +BoxUploadRequest::~BoxUploadRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _uploadCallback; +} + +void BoxUploadRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _resolvedId = ""; //used to update file contents + _parentId = ""; //used to create file within parent directory + _ignoreCallback = false; + + resolveId(); +} + +void BoxUploadRequest::resolveId() { + //check whether such file already exists + Storage::UploadCallback innerCallback = new Common::Callback(this, &BoxUploadRequest::idResolvedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &BoxUploadRequest::idResolveFailedCallback); + _workingRequest = _storage->resolveFileId(_savePath, innerCallback, innerErrorCallback); +} + +void BoxUploadRequest::idResolvedCallback(Storage::UploadResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + _resolvedId = response.value.id(); + upload(); +} + +void BoxUploadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + //not resolved => error or no such file + if (error.response.contains("no such file found in its parent directory")) { + //parent's id after the '\n' + Common::String parentId = error.response; + for (uint32 i = 0; i < parentId.size(); ++i) + if (parentId[i] == '\n') { + parentId.erase(0, i + 1); + break; + } + + _parentId = parentId; + upload(); + return; + } + + finishError(error); +} + +void BoxUploadRequest::upload() { + Common::String name = _savePath; + for (uint32 i = name.size(); i > 0; --i) { + if (name[i - 1] == '/' || name[i - 1] == '\\') { + name.erase(0, i); + break; + } + } + + Common::String url = "https://upload.box.com/api/2.0/files"; + if (_resolvedId != "") url += "/" + _resolvedId; + url += "/content"; + Networking::JsonCallback callback = new Common::Callback(this, &BoxUploadRequest::uploadedCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &BoxUploadRequest::notUploadedCallback); + Networking::CurlJsonRequest *request = new BoxTokenRefresher(_storage, callback, failureCallback, url.c_str()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); + + Common::JSONObject jsonRequestParameters; + if (_resolvedId == "") { + Common::JSONObject parentObject; + parentObject.setVal("id", new Common::JSONValue(_parentId)); + jsonRequestParameters.setVal("parent", new Common::JSONValue(parentObject)); + jsonRequestParameters.setVal("name", new Common::JSONValue(name)); + } + + Common::JSONValue value(jsonRequestParameters); + request->addFormField("attributes", Common::JSON::stringify(&value)); + request->addFormFile("file", _localPath); + + _workingRequest = ConnMan.addRequest(request); +} + +void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + + Networking::ErrorResponse error(this, false, true, "", -1); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + if (rq) { + const Networking::NetworkReadStream *stream = rq->getNetworkReadStream(); + if (stream) { + long code = stream->httpResponseCode(); + error.httpResponseCode = code; + } + } + + if (error.httpResponseCode != 200 && error.httpResponseCode != 201) + warning("looks like an error"); + + Common::JSONValue *json = response.value; + if (json) { + if (json->isObject()) { + Common::JSONObject object = json->asObject(); + if (object.contains("entries") && object.getVal("entries")->isArray()) { + Common::JSONArray entries = object.getVal("entries")->asArray(); + if (entries.size() > 0) { + Common::JSONObject entry = entries[0]->asObject(); + + //finished + Common::String id = entry.getVal("id")->asString(); + Common::String name = entry.getVal("name")->asString(); + bool isDirectory = (entry.getVal("type")->asString() == "folder"); + uint32 size = 0, timestamp = 0; + if (entry.contains("size")) { + if (entry.getVal("size")->isString()) + size = entry.getVal("size")->asString().asUint64(); + else if (entry.getVal("size")->isIntegerNumber()) + size = entry.getVal("size")->asIntegerNumber(); + else + warning("strange type for field 'size'"); + } + if (entry.contains("modified_at") && entry.getVal("modified_at")->isString()) + timestamp = ISO8601::convertToTimestamp(entry.getVal("modified_at")->asString()); + + //as we list directory by id, we can't determine full path for the file, so we leave it empty + finishUpload(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); + return; + } + } + + //TODO: check errors + /* + if (object.contains("error")) { + warning("Box returned error: %s", json->stringify(true).c_str()); + delete json; + error.response = json->stringify(true); + finishError(error); + return; + } + */ + } + + warning("no file info to return"); + finishUpload(StorageFile(_savePath, 0, 0, false)); + } else { + warning("null, not json"); + finishError(error); + } + + delete json; +} + +void BoxUploadRequest::notUploadedCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void BoxUploadRequest::handle() {} + +void BoxUploadRequest::restart() { start(); } + +void BoxUploadRequest::finishUpload(StorageFile file) { + Request::finishSuccess(); + if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); +} + +} // End of namespace Box +} // End of namespace Cloud diff --git a/backends/cloud/box/boxuploadrequest.h b/backends/cloud/box/boxuploadrequest.h new file mode 100644 index 0000000000..3d15aa70b3 --- /dev/null +++ b/backends/cloud/box/boxuploadrequest.h @@ -0,0 +1,63 @@ +/* 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_BOX_BOXUPLOADREQUEST_H +#define BACKENDS_CLOUD_BOX_BOXUPLOADREQUEST_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 Box { +class BoxStorage; + +class BoxUploadRequest: public Networking::Request { + BoxStorage *_storage; + Common::String _savePath, _localPath; + Storage::UploadCallback _uploadCallback; + Request *_workingRequest; + bool _ignoreCallback; + Common::String _resolvedId, _parentId; + + void start(); + void resolveId(); + void idResolvedCallback(Storage::UploadResponse response); + void idResolveFailedCallback(Networking::ErrorResponse error); + void upload(); + void uploadedCallback(Networking::JsonResponse response); + void notUploadedCallback(Networking::ErrorResponse error); + void finishUpload(StorageFile status); + +public: + BoxUploadRequest(BoxStorage *storage, Common::String path, Common::String localPath, Storage::UploadCallback callback, Networking::ErrorCallback ecb); + virtual ~BoxUploadRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace Box +} // End of namespace Cloud + +#endif -- cgit v1.2.3 From 5cbb3e8705f51337c6455ecb5dc7004abf82bd89 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 07:44:58 +0600 Subject: CLOUD: Add Storage::uploadStreamSupported() Box uses POST multipart/form requests for uploading. Such requests could be sent with libcurl if we either have a file available or a buffer with this file's contents. SavesSyncRequest was using Storage::upload(ReadStream *), which couldn't be implemented in BoxStorage. Thus I've added a method to test whether such upload is supported and, if it's not, SavesSyncRequest uses the other. --- backends/cloud/box/boxstorage.cpp | 7 +++++++ backends/cloud/box/boxstorage.h | 3 +++ backends/cloud/savessyncrequest.cpp | 15 +++++++++++---- backends/cloud/storage.cpp | 4 ++++ backends/cloud/storage.h | 3 +++ 5 files changed, 28 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 628d18b89a..35e86409c3 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -252,9 +252,16 @@ Networking::Request *BoxStorage::upload(Common::String remotePath, Common::Strin Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { warning("BoxStorage::upload(ReadStream) not implemented"); + if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "BoxStorage::upload(ReadStream) not implemented", -1)); + delete callback; + delete errorCallback; return nullptr; } +bool BoxStorage::uploadStreamSupported() { + return false; +} + Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { if (callback) { Common::String url = "https://api.box.com/2.0/files/" + id + "/content"; diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 93afe4fabb..a737e9d4a1 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -83,6 +83,9 @@ public: virtual Networking::Request *upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback); virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); + /** Returns whether Storage supports upload(ReadStream). */ + virtual bool uploadStreamSupported(); + /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index e12f5af7cc..32b22edcaa 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -279,10 +279,17 @@ void SavesSyncRequest::uploadNextFile() { /////// debug("uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress()*100)); /////// - _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), - new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), - new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) - ); + if (_storage->uploadStreamSupported()) { + _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), + new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), + new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) + ); + } else { + _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, DefaultSaveFileManager::concatWithSavesPath(_currentUploadingFile), + new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), + new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) + ); + } if (!_workingRequest) finishError(Networking::ErrorResponse(this)); } diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 2cf851f3ba..110c97ad9c 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -85,6 +85,10 @@ Networking::Request *Storage::upload(Common::String remotePath, Common::String l return upload(remotePath, f, callback, errorCallback); } +bool Storage::uploadStreamSupported() { + return true; +} + Networking::Request *Storage::streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { //most Storages use paths instead of ids, so this should work return streamFileById(path, callback, errorCallback); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 62b42697e6..273b93c764 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -126,6 +126,9 @@ public: 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); + /** Returns whether Storage supports upload(ReadStream). */ + virtual bool uploadStreamSupported(); + /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); virtual Networking::Request *streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) = 0; -- cgit v1.2.3 From 0b5bd18d8525e16749ad422913800b2120021240 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 08:50:31 +0600 Subject: CLOUD: Update GoogleDriveStorage It now derives from IdStorage, so lots of GoogleDrive*Request classes are removed and replaced with generic IdStorage*Request ones. --- .../googledrivecreatedirectoryrequest.cpp | 146 --------------------- .../googledrivecreatedirectoryrequest.h | 65 --------- .../googledrive/googledrivedownloadrequest.cpp | 91 ------------- .../cloud/googledrive/googledrivedownloadrequest.h | 59 --------- .../googledrivelistdirectoryrequest.cpp | 129 ------------------ .../googledrive/googledrivelistdirectoryrequest.h | 67 ---------- .../googledrive/googledriveresolveidrequest.cpp | 130 ------------------ .../googledrive/googledriveresolveidrequest.h | 61 --------- backends/cloud/googledrive/googledrivestorage.cpp | 88 ++----------- backends/cloud/googledrive/googledrivestorage.h | 23 +--- .../googledrive/googledrivestreamfilerequest.cpp | 91 ------------- .../googledrive/googledrivestreamfilerequest.h | 59 --------- .../cloud/googledrive/googledriveuploadrequest.cpp | 10 +- 13 files changed, 19 insertions(+), 1000 deletions(-) delete mode 100644 backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp delete mode 100644 backends/cloud/googledrive/googledrivecreatedirectoryrequest.h delete mode 100644 backends/cloud/googledrive/googledrivedownloadrequest.cpp delete mode 100644 backends/cloud/googledrive/googledrivedownloadrequest.h delete mode 100644 backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp delete mode 100644 backends/cloud/googledrive/googledrivelistdirectoryrequest.h delete mode 100644 backends/cloud/googledrive/googledriveresolveidrequest.cpp delete mode 100644 backends/cloud/googledrive/googledriveresolveidrequest.h delete mode 100644 backends/cloud/googledrive/googledrivestreamfilerequest.cpp delete mode 100644 backends/cloud/googledrive/googledrivestreamfilerequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp deleted file mode 100644 index 9e339fd999..0000000000 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* 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/googledrive/googledrivecreatedirectoryrequest.h" -#include "backends/cloud/googledrive/googledrivestorage.h" -#include "common/debug.h" - -namespace Cloud { -namespace GoogleDrive { - -GoogleDriveCreateDirectoryRequest::GoogleDriveCreateDirectoryRequest(GoogleDriveStorage *storage, Common::String parentPath, Common::String directoryName, Storage::BoolCallback cb, Networking::ErrorCallback ecb): - Networking::Request(nullptr, ecb), - _requestedParentPath(parentPath), _requestedDirectoryName(directoryName), _storage(storage), _boolCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { - start(); -} - -GoogleDriveCreateDirectoryRequest::~GoogleDriveCreateDirectoryRequest() { - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - delete _boolCallback; -} - -void GoogleDriveCreateDirectoryRequest::start() { - //cleanup - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - _workingRequest = nullptr; - _ignoreCallback = false; - - //the only exception when we create parent folder - is when it's ScummVM/ base folder - Common::String prefix = _requestedParentPath; - if (prefix.size() > 7) prefix.erase(7); - if (prefix.equalsIgnoreCase("ScummVM")) { - Storage::BoolCallback callback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdBaseDirectoryCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdBaseDirectoryErrorCallback); - _workingRequest = _storage->createDirectory("ScummVM", callback, failureCallback); - return; - } - - resolveId(); -} - -void GoogleDriveCreateDirectoryRequest::createdBaseDirectoryCallback(Storage::BoolResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); - resolveId(); -} - -void GoogleDriveCreateDirectoryRequest::createdBaseDirectoryErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); - finishError(error); -} - -void GoogleDriveCreateDirectoryRequest::resolveId() { - //check whether such folder already exists - Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::idResolvedCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::idResolveFailedCallback); - Common::String path = _requestedParentPath; - if (_requestedParentPath != "") path += "/"; - path += _requestedDirectoryName; - _workingRequest = _storage->resolveFileId(path, innerCallback, innerErrorCallback); -} - -void GoogleDriveCreateDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); - - //resolved => folder already exists - finishCreation(false); -} - -void GoogleDriveCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); - - //not resolved => folder not exists - if (error.response.contains("no such file found in its parent directory")) { - //parent's id after the '\n' - Common::String parentId = error.response; - for (uint32 i = 0; i < parentId.size(); ++i) - if (parentId[i] == '\n') { - parentId.erase(0, i+1); - break; - } - - Storage::BoolCallback callback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdDirectoryCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveCreateDirectoryRequest::createdDirectoryErrorCallback); - _workingRequest = _storage->createDirectoryWithParentId(parentId, _requestedDirectoryName, callback, failureCallback); - return; - } - - finishError(error); -} - -void GoogleDriveCreateDirectoryRequest::createdDirectoryCallback(Storage::BoolResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); - finishCreation(response.value); -} - -void GoogleDriveCreateDirectoryRequest::createdDirectoryErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); - finishError(error); -} - -void GoogleDriveCreateDirectoryRequest::handle() {} - -void GoogleDriveCreateDirectoryRequest::restart() { start(); } - -Common::String GoogleDriveCreateDirectoryRequest::date() const { return _date; } - -void GoogleDriveCreateDirectoryRequest::finishCreation(bool success) { - Request::finishSuccess(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); -} - -} // End of namespace GoogleDrive -} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h b/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h deleted file mode 100644 index 7a6ffaca1b..0000000000 --- a/backends/cloud/googledrive/googledrivecreatedirectoryrequest.h +++ /dev/null @@ -1,65 +0,0 @@ -/* 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_GOOGLEDRIVE_GOOGLEDRIVECREATEDIRECTORYREQUEST_H -#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVECREATEDIRECTORYREQUEST_H - -#include "backends/cloud/storage.h" -#include "backends/networking/curl/request.h" -#include "common/callback.h" - -namespace Cloud { -namespace GoogleDrive { - -class GoogleDriveStorage; - -class GoogleDriveCreateDirectoryRequest: public Networking::Request { - Common::String _requestedParentPath; - Common::String _requestedDirectoryName; - GoogleDriveStorage *_storage; - Storage::BoolCallback _boolCallback; - Request *_workingRequest; - bool _ignoreCallback; - Common::String _date; - - void start(); - void createdBaseDirectoryCallback(Storage::BoolResponse response); - void createdBaseDirectoryErrorCallback(Networking::ErrorResponse error); - void resolveId(); - void idResolvedCallback(Storage::UploadResponse response); - void idResolveFailedCallback(Networking::ErrorResponse error); - void createdDirectoryCallback(Storage::BoolResponse response); - void createdDirectoryErrorCallback(Networking::ErrorResponse error); - void finishCreation(bool success); -public: - GoogleDriveCreateDirectoryRequest(GoogleDriveStorage *storage, Common::String parentPath, Common::String directoryName, Storage::BoolCallback cb, Networking::ErrorCallback ecb); - virtual ~GoogleDriveCreateDirectoryRequest(); - - virtual void handle(); - virtual void restart(); - virtual Common::String date() const; -}; - -} // End of namespace GoogleDrive -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/googledrive/googledrivedownloadrequest.cpp b/backends/cloud/googledrive/googledrivedownloadrequest.cpp deleted file mode 100644 index df28c8b27f..0000000000 --- a/backends/cloud/googledrive/googledrivedownloadrequest.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* 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/googledrive/googledrivedownloadrequest.h" -#include "backends/cloud/googledrive/googledrivestorage.h" - -namespace Cloud { -namespace GoogleDrive { - -GoogleDriveDownloadRequest::GoogleDriveDownloadRequest(GoogleDriveStorage *storage, Common::String remotePath, Common::String localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb): - Networking::Request(nullptr, ecb), _requestedFile(remotePath), _requestedLocalFile(localPath), _storage(storage), _boolCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { - start(); -} - -GoogleDriveDownloadRequest::~GoogleDriveDownloadRequest() { - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - delete _boolCallback; -} - -void GoogleDriveDownloadRequest::start() { - //cleanup - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - _workingRequest = nullptr; - _ignoreCallback = false; - - //find file's id - Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::idResolvedCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::idResolveFailedCallback); - _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); -} - -void GoogleDriveDownloadRequest::idResolvedCallback(Storage::UploadResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - - Storage::BoolCallback innerCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::downloadCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveDownloadRequest::downloadErrorCallback); - _workingRequest = _storage->downloadById(response.value.id(), _requestedLocalFile, innerCallback, innerErrorCallback); -} - -void GoogleDriveDownloadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishError(error); -} - -void GoogleDriveDownloadRequest::downloadCallback(Storage::BoolResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishDownload(response.value); -} - -void GoogleDriveDownloadRequest::downloadErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishError(error); -} - -void GoogleDriveDownloadRequest::handle() {} - -void GoogleDriveDownloadRequest::restart() { start(); } - -void GoogleDriveDownloadRequest::finishDownload(bool success) { - Request::finishSuccess(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); -} - -} // End of namespace GoogleDrive -} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivedownloadrequest.h b/backends/cloud/googledrive/googledrivedownloadrequest.h deleted file mode 100644 index 202a393d7a..0000000000 --- a/backends/cloud/googledrive/googledrivedownloadrequest.h +++ /dev/null @@ -1,59 +0,0 @@ -/* 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_GOOGLEDRIVE_GOOGLEDRIVEDOWNLOADREQUEST_H -#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVEDOWNLOADREQUEST_H - -#include "backends/cloud/storage.h" -#include "backends/networking/curl/request.h" -#include "common/callback.h" - -namespace Cloud { -namespace GoogleDrive { - -class GoogleDriveStorage; - -class GoogleDriveDownloadRequest: public Networking::Request { - Common::String _requestedFile, _requestedLocalFile; - GoogleDriveStorage *_storage; - Storage::BoolCallback _boolCallback; - Request *_workingRequest; - bool _ignoreCallback; - - void start(); - void idResolvedCallback(Storage::UploadResponse response); - void idResolveFailedCallback(Networking::ErrorResponse error); - void downloadCallback(Storage::BoolResponse response); - void downloadErrorCallback(Networking::ErrorResponse error); - void finishDownload(bool success); -public: - GoogleDriveDownloadRequest(GoogleDriveStorage *storage, Common::String remotePath, Common::String localPath, Storage::BoolCallback cb, Networking::ErrorCallback ecb); - virtual ~GoogleDriveDownloadRequest(); - - virtual void handle(); - virtual void restart(); -}; - -} // End of namespace GoogleDrive -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp deleted file mode 100644 index f645041eb3..0000000000 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* 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/googledrive/googledrivelistdirectoryrequest.h" -#include "backends/cloud/googledrive/googledrivestorage.h" - -namespace Cloud { -namespace GoogleDrive { - -GoogleDriveListDirectoryRequest::GoogleDriveListDirectoryRequest(GoogleDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): - Networking::Request(nullptr, ecb), - _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { - start(); -} - -GoogleDriveListDirectoryRequest::~GoogleDriveListDirectoryRequest() { - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - delete _listDirectoryCallback; -} - -void GoogleDriveListDirectoryRequest::start() { - //cleanup - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - _workingRequest = nullptr; - _files.clear(); - _directoriesQueue.clear(); - _currentDirectory = StorageFile(); - _ignoreCallback = false; - - //find out that directory's id - Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::idResolvedCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::idResolveErrorCallback); - _workingRequest = _storage->resolveFileId(_requestedPath, innerCallback, innerErrorCallback); -} - -void GoogleDriveListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); - - StorageFile directory = response.value; - directory.setPath(_requestedPath); - _directoriesQueue.push_back(directory); - listNextDirectory(); -} - -void GoogleDriveListDirectoryRequest::idResolveErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); - finishError(error); -} - -void GoogleDriveListDirectoryRequest::listNextDirectory() { - if (_directoriesQueue.empty()) { - finishListing(_files); - return; - } - - _currentDirectory = _directoriesQueue.back(); - _directoriesQueue.pop_back(); - - Storage::FileArrayCallback callback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::listedDirectoryCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveListDirectoryRequest::listedDirectoryErrorCallback); - _workingRequest = _storage->listDirectoryById(_currentDirectory.id(), callback, failureCallback); -} - -void GoogleDriveListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); - - for (uint32 i = 0; i < response.value.size(); ++i) { - StorageFile &file = response.value[i]; - Common::String path = _currentDirectory.path(); - if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') path += '/'; - path += file.name(); - file.setPath(path); - _files.push_back(file); - if (_requestedRecursive && file.isDirectory()) { - _directoriesQueue.push_back(file); - } - } - - listNextDirectory(); -} - -void GoogleDriveListDirectoryRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - if (error.request) _date = error.request->date(); - finishError(error); -} - -void GoogleDriveListDirectoryRequest::handle() {} - -void GoogleDriveListDirectoryRequest::restart() { start(); } - -Common::String GoogleDriveListDirectoryRequest::date() const { return _date; } - -void GoogleDriveListDirectoryRequest::finishListing(Common::Array &files) { - Request::finishSuccess(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); -} - -} // End of namespace GoogleDrive -} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h b/backends/cloud/googledrive/googledrivelistdirectoryrequest.h deleted file mode 100644 index d76338b7fc..0000000000 --- a/backends/cloud/googledrive/googledrivelistdirectoryrequest.h +++ /dev/null @@ -1,67 +0,0 @@ -/* 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_GOOGLEDRIVE_GOOGLEDRIVELISTDIRECTORYREQUEST_H -#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVELISTDIRECTORYREQUEST_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 GoogleDrive { - -class GoogleDriveStorage; - -class GoogleDriveListDirectoryRequest: public Networking::Request { - Common::String _requestedPath; - bool _requestedRecursive; - GoogleDriveStorage *_storage; - Storage::ListDirectoryCallback _listDirectoryCallback; - Common::Array _files; - Common::Array _directoriesQueue; - StorageFile _currentDirectory; - Request *_workingRequest; - bool _ignoreCallback; - Common::String _date; - - void start(); - void idResolvedCallback(Storage::UploadResponse response); - void idResolveErrorCallback(Networking::ErrorResponse error); - void listNextDirectory(); - void listedDirectoryCallback(Storage::FileArrayResponse response); - void listedDirectoryErrorCallback(Networking::ErrorResponse error); - void finishListing(Common::Array &files); -public: - GoogleDriveListDirectoryRequest(GoogleDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false); - virtual ~GoogleDriveListDirectoryRequest(); - - virtual void handle(); - virtual void restart(); - virtual Common::String date() const; -}; - -} // End of namespace GoogleDrive -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.cpp b/backends/cloud/googledrive/googledriveresolveidrequest.cpp deleted file mode 100644 index 6d8da8383d..0000000000 --- a/backends/cloud/googledrive/googledriveresolveidrequest.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* 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/googledrive/googledriveresolveidrequest.h" -#include "backends/cloud/googledrive/googledrivestorage.h" -#include "backends/cloud/googledrive/googledrivetokenrefresher.h" -#include "backends/cloud/iso8601.h" -#include "backends/networking/curl/connectionmanager.h" -#include "backends/networking/curl/networkreadstream.h" -#include "common/json.h" - -namespace Cloud { -namespace GoogleDrive { - -GoogleDriveResolveIdRequest::GoogleDriveResolveIdRequest(GoogleDriveStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive): - Networking::Request(nullptr, ecb), - _requestedPath(path), _storage(storage), _uploadCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { - start(); -} - -GoogleDriveResolveIdRequest::~GoogleDriveResolveIdRequest() { - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - delete _uploadCallback; -} - -void GoogleDriveResolveIdRequest::start() { - //cleanup - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - _workingRequest = nullptr; - _currentDirectory = ""; - _currentDirectoryId = "root"; - _ignoreCallback = false; - - listNextDirectory(StorageFile(_currentDirectoryId, 0, 0, true)); -} - -void GoogleDriveResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { - if (_currentDirectory.equalsIgnoreCase(_requestedPath)) { - finishFile(fileToReturn); - return; - } - - Storage::FileArrayCallback callback = new Common::Callback(this, &GoogleDriveResolveIdRequest::listedDirectoryCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveResolveIdRequest::listedDirectoryErrorCallback); - _workingRequest = _storage->listDirectoryById(_currentDirectoryId, callback, failureCallback); -} - -void GoogleDriveResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - - Common::String currentLevelName = _requestedPath; - ///debug("'%s'", currentLevelName.c_str()); - if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); - if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) currentLevelName.erase(0, 1); - ///debug("'%s'", currentLevelName.c_str()); - for (uint32 i = 0; i < currentLevelName.size(); ++i) { - if (currentLevelName[i] == '/' || currentLevelName[i] == '\\') { - currentLevelName.erase(i); - ///debug("'%s'", currentLevelName.c_str()); - break; - } - } - - Common::String path = _currentDirectory; - if (path != "") path += "/"; - path += currentLevelName; - bool lastLevel = (path.equalsIgnoreCase(_requestedPath)); - - ///debug("so, searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); - - Common::Array &files = response.value; - bool found = false; - for (uint32 i = 0; i < files.size(); ++i) { - if ((files[i].isDirectory() || lastLevel) && files[i].name().equalsIgnoreCase(currentLevelName)) { - if (_currentDirectory != "") _currentDirectory += "/"; - _currentDirectory += files[i].name(); - _currentDirectoryId = files[i].id(); - ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); - listNextDirectory(files[i]); - found = true; - break; - } - } - - if (!found) { - if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); - else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); - } -} - -void GoogleDriveResolveIdRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishError(error); -} - -void GoogleDriveResolveIdRequest::handle() {} - -void GoogleDriveResolveIdRequest::restart() { start(); } - -void GoogleDriveResolveIdRequest::finishFile(StorageFile file) { - Request::finishSuccess(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); -} - -} // End of namespace GoogleDrive -} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledriveresolveidrequest.h b/backends/cloud/googledrive/googledriveresolveidrequest.h deleted file mode 100644 index cd6f244a94..0000000000 --- a/backends/cloud/googledrive/googledriveresolveidrequest.h +++ /dev/null @@ -1,61 +0,0 @@ -/* 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_GOOGLEDRIVE_GOOGLEDRIVERESOLVEIDREQUEST_H -#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVERESOLVEIDREQUEST_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 GoogleDrive { - -class GoogleDriveStorage; - -class GoogleDriveResolveIdRequest: public Networking::Request { - Common::String _requestedPath; - GoogleDriveStorage *_storage; - Storage::UploadCallback _uploadCallback; - Common::String _currentDirectory; - Common::String _currentDirectoryId; - Request *_workingRequest; - bool _ignoreCallback; - - void start(); - void listNextDirectory(StorageFile fileToReturn); - void listedDirectoryCallback(Storage::FileArrayResponse response); - void listedDirectoryErrorCallback(Networking::ErrorResponse error); - void finishFile(StorageFile file); -public: - GoogleDriveResolveIdRequest(GoogleDriveStorage *storage, Common::String path, Storage::UploadCallback cb, Networking::ErrorCallback ecb, bool recursive = false); //TODO: why upload? - virtual ~GoogleDriveResolveIdRequest(); - - virtual void handle(); - virtual void restart(); -}; - -} // End of namespace GoogleDrive -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 327c9ee8eb..eeae2f2ee3 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -24,20 +24,15 @@ #include "backends/cloud/googledrive/googledrivestorage.h" #include "backends/cloud/cloudmanager.h" #include "backends/cloud/googledrive/googledrivetokenrefresher.h" +#include "backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h" +#include "backends/cloud/googledrive/googledriveuploadrequest.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" +#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include -#include "googledrivelistdirectorybyidrequest.h" -#include "googledriveresolveidrequest.h" -#include "googledrivecreatedirectoryrequest.h" -#include "googledrivelistdirectoryrequest.h" -#include "googledrivestreamfilerequest.h" -#include "googledrivedownloadrequest.h" -#include "googledriveuploadrequest.h" -#include "common/config-manager.h" namespace Cloud { namespace GoogleDrive { @@ -198,29 +193,6 @@ void GoogleDriveStorage::createDirectoryInnerCallback(BoolCallback outerCallback delete json; } -void GoogleDriveStorage::printJson(Networking::JsonResponse response) { - Common::JSONValue *json = response.value; - if (!json) { - warning("printJson: NULL"); - return; - } - - debug("%s", json->stringify().c_str()); - delete json; -} - -Networking::Request *GoogleDriveStorage::resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFile); - return addRequest(new GoogleDriveResolveIdRequest(this, path, callback, errorCallback)); -} - -Networking::Request *GoogleDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFiles); - return addRequest(new GoogleDriveListDirectoryRequest(this, path, callback, errorCallback, recursive)); -} - Networking::Request *GoogleDriveStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFiles); @@ -231,10 +203,6 @@ Networking::Request *GoogleDriveStorage::upload(Common::String path, Common::See return addRequest(new GoogleDriveUploadRequest(this, path, contents, callback, errorCallback)); } -Networking::Request *GoogleDriveStorage::streamFile(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { - return addRequest(new GoogleDriveStreamFileRequest(this, path, outerCallback, errorCallback)); -} - Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { if (callback) { Common::String url = "https://www.googleapis.com/drive/v3/files/" + ConnMan.urlEncode(id) + "?alt=media"; @@ -248,38 +216,11 @@ Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Netwo return nullptr; } -Networking::Request *GoogleDriveStorage::download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback) { - return addRequest(new GoogleDriveDownloadRequest(this, remotePath, localPath, callback, errorCallback)); -} - void GoogleDriveStorage::fileDownloaded(BoolResponse response) { if (response.value) debug("file downloaded!"); else debug("download failed!"); } -void GoogleDriveStorage::printFiles(FileArrayResponse response) { - debug("files:"); - Common::Array &files = response.value; - for (uint32 i = 0; i < files.size(); ++i) { - debug("\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); - debug("\t%s", files[i].path().c_str()); - debug("\t%s", files[i].id().c_str()); - debug(" "); - } -} - -void GoogleDriveStorage::printBool(BoolResponse response) { - debug("bool: %s", response.value ? "true" : "false"); -} - -void GoogleDriveStorage::printFile(UploadResponse response) { - debug("\nuploaded file info:"); - debug("\tid: %s", response.value.path().c_str()); - debug("\tname: %s", response.value.name().c_str()); - debug("\tsize: %u", response.value.size()); - debug("\ttimestamp: %u", response.value.timestamp()); -} - void GoogleDriveStorage::printInfo(StorageInfoResponse response) { debug("\nuser info:"); debug("\tname: %s", response.value.name().c_str()); @@ -287,24 +228,6 @@ void GoogleDriveStorage::printInfo(StorageInfoResponse response) { debug("\tdisk usage: %llu/%llu", response.value.used(), response.value.available()); } -Networking::Request *GoogleDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printBool); - - //find out the parent path and directory name - Common::String parentPath = "", directoryName = path; - for (uint32 i = path.size(); i > 0; --i) { - if (path[i-1] == '/' || path[i-1] == '\\') { - parentPath = path; - parentPath.erase(i-1); - directoryName.erase(0, i); - break; - } - } - - return addRequest(new GoogleDriveCreateDirectoryRequest(this, parentPath, directoryName, callback, errorCallback)); -} - Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); @@ -366,6 +289,11 @@ Common::String GoogleDriveStorage::getAuthLink() { return url; } +Common::String GoogleDriveStorage::getRootDirectoryId() { + return "root"; +} + + void GoogleDriveStorage::authThroughConsole() { if (!ConfMan.hasKey("GOOGLE_DRIVE_KEY", ConfMan.kCloudDomain) || !ConfMan.hasKey("GOOGLE_DRIVE_SECRET", ConfMan.kCloudDomain)) { warning("No Google Drive keys available, cannot do auth"); diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 8093ef1938..435f9998a3 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -23,14 +23,14 @@ #ifndef BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVESTORAGE_H #define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVESTORAGE_H -#include "backends/cloud/storage.h" +#include "backends/cloud/id/idstorage.h" #include "common/callback.h" #include "backends/networking/curl/curljsonrequest.h" namespace Cloud { namespace GoogleDrive { -class GoogleDriveStorage: public Cloud::Storage { +class GoogleDriveStorage: public Id::IdStorage { static char *KEY, *SECRET; static void loadKeyAndSecret(); @@ -49,11 +49,7 @@ class GoogleDriveStorage: public Cloud::Storage { /** Returns bool based on JSON response from cloud. */ void createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse json); - void printJson(Networking::JsonResponse response); void fileDownloaded(BoolResponse response); - void printFiles(FileArrayResponse response); - void printBool(BoolResponse response); - void printFile(UploadResponse response); void printInfo(StorageInfoResponse response); public: /** This constructor uses OAuth code flow to get tokens. */ @@ -81,12 +77,6 @@ public: /** Public Cloud API comes down there. */ - /** Returns StorageFile with the resolved file's id. */ - virtual Networking::Request *resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback); - - /** Returns Array - the list of files. */ - virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); - /** Returns Array - the list of files. */ virtual Networking::Request *listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback); @@ -94,18 +84,11 @@ public: virtual Networking::Request *upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback); /** Returns pointer to Networking::NetworkReadStream. */ - virtual Networking::Request *streamFile(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); virtual Networking::Request *streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *download(Common::String remotePath, Common::String localPath, BoolCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Calls the callback when finished. */ - virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ virtual Networking::Request *createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback); @@ -126,6 +109,8 @@ public: */ static Common::String getAuthLink(); + virtual Common::String getRootDirectoryId(); + /** * Show message with GoogleDrive auth instructions. (Temporary) */ diff --git a/backends/cloud/googledrive/googledrivestreamfilerequest.cpp b/backends/cloud/googledrive/googledrivestreamfilerequest.cpp deleted file mode 100644 index 424e52c6cb..0000000000 --- a/backends/cloud/googledrive/googledrivestreamfilerequest.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* 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/googledrive/googledrivestreamfilerequest.h" -#include "backends/cloud/googledrive/googledrivestorage.h" - -namespace Cloud { -namespace GoogleDrive { - -GoogleDriveStreamFileRequest::GoogleDriveStreamFileRequest(GoogleDriveStorage *storage, Common::String path, Networking::NetworkReadStreamCallback cb, Networking::ErrorCallback ecb): - Networking::Request(nullptr, ecb), _requestedFile(path), _storage(storage), _streamCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { - start(); -} - -GoogleDriveStreamFileRequest::~GoogleDriveStreamFileRequest() { - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - delete _streamCallback; -} - -void GoogleDriveStreamFileRequest::start() { - //cleanup - _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); - _workingRequest = nullptr; - _ignoreCallback = false; - - //find file's id - Storage::UploadCallback innerCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::idResolvedCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::idResolveFailedCallback); - _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); -} - -void GoogleDriveStreamFileRequest::idResolvedCallback(Storage::UploadResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - - Networking::NetworkReadStreamCallback innerCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::streamFileCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &GoogleDriveStreamFileRequest::streamFileErrorCallback); - _workingRequest = _storage->streamFileById(response.value.id(), innerCallback, innerErrorCallback); -} - -void GoogleDriveStreamFileRequest::idResolveFailedCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishError(error); -} - -void GoogleDriveStreamFileRequest::streamFileCallback(Networking::NetworkReadStreamResponse response) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishStream(response.value); -} - -void GoogleDriveStreamFileRequest::streamFileErrorCallback(Networking::ErrorResponse error) { - _workingRequest = nullptr; - if (_ignoreCallback) return; - finishError(error); -} - -void GoogleDriveStreamFileRequest::handle() {} - -void GoogleDriveStreamFileRequest::restart() { start(); } - -void GoogleDriveStreamFileRequest::finishStream(Networking::NetworkReadStream *stream) { - Request::finishSuccess(); - if (_streamCallback) (*_streamCallback)(Networking::NetworkReadStreamResponse(this, stream)); -} - -} // End of namespace GoogleDrive -} // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivestreamfilerequest.h b/backends/cloud/googledrive/googledrivestreamfilerequest.h deleted file mode 100644 index aa5596154e..0000000000 --- a/backends/cloud/googledrive/googledrivestreamfilerequest.h +++ /dev/null @@ -1,59 +0,0 @@ -/* 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_GOOGLEDRIVE_GOOGLEDRIVESTREAMFILEREQUEST_H -#define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVESTREAMFILEREQUEST_H - -#include "backends/cloud/storage.h" -#include "backends/networking/curl/request.h" -#include "common/callback.h" - -namespace Cloud { -namespace GoogleDrive { - -class GoogleDriveStorage; - -class GoogleDriveStreamFileRequest: public Networking::Request { - Common::String _requestedFile; - GoogleDriveStorage *_storage; - Networking::NetworkReadStreamCallback _streamCallback; - Request *_workingRequest; - bool _ignoreCallback; - - void start(); - void idResolvedCallback(Storage::UploadResponse response); - void idResolveFailedCallback(Networking::ErrorResponse error); - void streamFileCallback(Networking::NetworkReadStreamResponse response); - void streamFileErrorCallback(Networking::ErrorResponse error); - void finishStream(Networking::NetworkReadStream *stream); -public: - GoogleDriveStreamFileRequest(GoogleDriveStorage *storage, Common::String path, Networking::NetworkReadStreamCallback cb, Networking::ErrorCallback ecb); - virtual ~GoogleDriveStreamFileRequest(); - - virtual void handle(); - virtual void restart(); -}; - -} // End of namespace GoogleDrive -} // End of namespace Cloud - -#endif diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index d9ba2815e0..ce7d59a50c 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -198,11 +198,15 @@ void GoogleDriveUploadRequest::uploadNextPart() { byte *buffer = new byte[UPLOAD_PER_ONE_REQUEST]; uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST); - request->setBuffer(buffer, size); + if (size != 0) 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())); ; + if (_uploadUrl != "") { + if (_contentsStream->pos() == 0) + request->addHeader(Common::String::format("Content-Length: 0")); + else + request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos() - 1, _contentsStream->size())); + } _workingRequest = ConnMan.addRequest(request); } -- cgit v1.2.3 From b4e9e35e07538a118588742aff6fd4a7a2b4d600 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 09:19:12 +0600 Subject: CLOUD: Cleanup in Storages --- backends/cloud/box/boxstorage.cpp | 33 ------------ backends/cloud/box/boxstorage.h | 8 --- backends/cloud/dropbox/dropboxstorage.cpp | 27 ---------- backends/cloud/dropbox/dropboxstorage.h | 9 ---- backends/cloud/googledrive/googledrivestorage.cpp | 37 ------------- backends/cloud/googledrive/googledrivestorage.h | 11 ---- backends/cloud/id/idstorage.cpp | 11 ---- backends/cloud/id/idstorage.h | 1 - backends/cloud/onedrive/onedrivestorage.cpp | 65 ----------------------- backends/cloud/onedrive/onedrivestorage.h | 20 ------- backends/cloud/storage.h | 3 -- 11 files changed, 225 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 35e86409c3..9e036b1187 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -177,29 +177,6 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking delete json; } -void BoxStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { - if (!response.value) { - warning("fileInfoCallback: NULL"); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); - return; - } - - Common::JSONObject result = response.value->asObject(); - if (result.contains("@content.downloadUrl")) { - const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); - if (outerCallback) - (*outerCallback)(Networking::NetworkReadStreamResponse( - response.request, - new Networking::NetworkReadStream(url, 0, "") - )); - } else { - warning("downloadUrl not found in passed JSON"); - debug("%s", response.value->stringify().c_str()); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); - } - delete response.value; -} - Networking::Request *BoxStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); if (!callback) callback = getPrintFilesCallback(); @@ -275,11 +252,6 @@ Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::N return nullptr; } -void BoxStorage::fileDownloaded(BoolResponse response) { - if (response.value) debug("file downloaded!"); - else debug("download failed!"); -} - Networking::Request *BoxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::infoInnerCallback, callback); Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.box.com/2.0/users/me"); @@ -307,11 +279,6 @@ BoxStorage *BoxStorage::loadFromConfig(Common::String keyPrefix) { return new BoxStorage(accessToken, refreshToken); } -Common::String BoxStorage::getAuthLink() { - // now we only specify short "scummvm.org/c/bx" with actual redirect to the auth page - return ""; -} - Common::String BoxStorage::getRootDirectoryId() { return "0"; } diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index a737e9d4a1..51f2a9591c 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -46,9 +46,6 @@ class BoxStorage: public Id::IdStorage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); - void fileDownloaded(BoolResponse response); - - void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); void createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response); public: /** This constructor uses OAuth code flow to get tokens. */ @@ -104,11 +101,6 @@ public: */ static BoxStorage *loadFromConfig(Common::String keyPrefix); - /** - * Returns Box auth link. - */ - static Common::String getAuthLink(); - virtual Common::String getRootDirectoryId(); /** diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 6d73e52c43..8343b74aa0 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -105,24 +105,6 @@ Common::String DropboxStorage::name() const { return "Dropbox"; } -void DropboxStorage::printFiles(FileArrayResponse response) { - debug("files:"); - Common::Array &files = response.value; - for (uint32 i = 0; i < files.size(); ++i) - debug("\t%s", files[i].name().c_str()); -} - -void DropboxStorage::printBool(BoolResponse response) { - debug("bool: %s", (response.value?"true":"false")); -} - -void DropboxStorage::printStorageFile(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()); -} - Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, Networking::ErrorCallback errorCallback, bool recursive) { return addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive)); } @@ -218,14 +200,5 @@ DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { return new DropboxStorage(accessToken, userId); } -Common::String DropboxStorage::getAuthLink() { - Common::String url = "https://www.dropbox.com/1/oauth2/authorize"; - url += "?response_type=code"; - url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting - //url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening - url += "&client_id="; url += KEY; - return url; -} - } // End of namespace Dropbox } // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index d256e0562b..b3dc64139c 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -46,10 +46,6 @@ class DropboxStorage: public Cloud::Storage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); - void printFiles(FileArrayResponse response); - void printBool(BoolResponse response); - void printStorageFile(UploadResponse response); - public: /** This constructor uses OAuth code flow to get tokens. */ DropboxStorage(Common::String code); @@ -105,11 +101,6 @@ public: * @return pointer to the newly created DropboxStorage or 0 if some problem occured. */ static DropboxStorage *loadFromConfig(Common::String keyPrefix); - - /** - * Returns Dropbox auth link. - */ - static Common::String getAuthLink(); }; } // End of namespace Dropbox diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index eeae2f2ee3..2816301cac 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -216,11 +216,6 @@ Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Netwo return nullptr; } -void GoogleDriveStorage::fileDownloaded(BoolResponse response) { - if (response.value) debug("file downloaded!"); - else debug("download failed!"); -} - void GoogleDriveStorage::printInfo(StorageInfoResponse response) { debug("\nuser info:"); debug("\tname: %s", response.value.name().c_str()); @@ -279,41 +274,9 @@ GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) return new GoogleDriveStorage(accessToken, refreshToken); } -Common::String GoogleDriveStorage::getAuthLink() { - Common::String url = "https://accounts.google.com/o/oauth2/auth"; - url += "?response_type=code"; - url += "&redirect_uri=http://localhost"; //that's for copy-pasting - //url += "&redirect_uri=http%3A%2F%2Flocalhost"; //that's "http://localhost" for automatic opening - url += "&client_id="; url += KEY; - url += "&scope=https://www.googleapis.com/auth/drive"; //for copy-pasting - return url; -} - Common::String GoogleDriveStorage::getRootDirectoryId() { return "root"; } - -void GoogleDriveStorage::authThroughConsole() { - if (!ConfMan.hasKey("GOOGLE_DRIVE_KEY", ConfMan.kCloudDomain) || !ConfMan.hasKey("GOOGLE_DRIVE_SECRET", ConfMan.kCloudDomain)) { - warning("No Google Drive keys available, cannot do auth"); - return; - } - - loadKeyAndSecret(); - - if (ConfMan.hasKey("googledrive_code", ConfMan.kCloudDomain)) { - //phase 2: get access_token using specified code - new GoogleDriveStorage(ConfMan.get("googledrive_code", ConfMan.kCloudDomain)); - return; - } - - debug("Navigate to this URL and press \"Allow\":"); - debug("%s\n", getAuthLink().c_str()); - debug("Then, add googledrive_code key in [cloud] section of configuration file. You should copy the value from URL and put it as value for that key.\n"); - debug("Navigate to this URL to get more information on ScummVM's configuration files:"); - debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); -} - } // End of namespace GoogleDrive } // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 435f9998a3..4a7dbab99f 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -49,7 +49,6 @@ class GoogleDriveStorage: public Id::IdStorage { /** Returns bool based on JSON response from cloud. */ void createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse json); - void fileDownloaded(BoolResponse response); void printInfo(StorageInfoResponse response); public: /** This constructor uses OAuth code flow to get tokens. */ @@ -104,18 +103,8 @@ public: */ static GoogleDriveStorage *loadFromConfig(Common::String keyPrefix); - /** - * Returns GoogleDrive auth link. - */ - static Common::String getAuthLink(); - virtual Common::String getRootDirectoryId(); - /** - * Show message with GoogleDrive auth instructions. (Temporary) - */ - static void authThroughConsole(); - /** * Gets new access_token. If passed is "", refresh_token is used. * Use "" in order to refresh token and pass a callback, so you could diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index 3aeb5146cd..28f880522e 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -35,17 +35,6 @@ namespace Id { IdStorage::~IdStorage() {} -void IdStorage::printJson(Networking::JsonResponse response) { - Common::JSONValue *json = response.value; - if (!json) { - warning("printJson: NULL"); - return; - } - - debug("%s", json->stringify().c_str()); - delete json; -} - void IdStorage::printFiles(FileArrayResponse response) { debug("files:"); Common::Array &files = response.value; diff --git a/backends/cloud/id/idstorage.h b/backends/cloud/id/idstorage.h index 88853e4ad8..ccadc0e455 100644 --- a/backends/cloud/id/idstorage.h +++ b/backends/cloud/id/idstorage.h @@ -45,7 +45,6 @@ namespace Id { class IdStorage: public Cloud::Storage { protected: - void printJson(Networking::JsonResponse response); void printFiles(FileArrayResponse response); void printBool(BoolResponse response); void printFile(UploadResponse response); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 0d2f91c3a8..3c8ea5fe81 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -174,17 +174,6 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo delete json; } -void OneDriveStorage::printJson(Networking::JsonResponse response) { - Common::JSONValue *json = response.value; - if (!json) { - warning("printJson: NULL"); - return; - } - - debug("%s", json->stringify().c_str()); - delete json; -} - void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { if (!response.value) { warning("fileInfoCallback: NULL"); @@ -224,29 +213,6 @@ Networking::Request *OneDriveStorage::streamFileById(Common::String path, Networ return addRequest(request); } -void OneDriveStorage::fileDownloaded(BoolResponse response) { - if (response.value) debug("file downloaded!"); - else debug("download failed!"); -} - -void OneDriveStorage::printFiles(FileArrayResponse response) { - debug("files:"); - Common::Array &files = response.value; - for (uint32 i = 0; i < files.size(); ++i) - debug("\t%s", files[i].path().c_str()); -} - -void OneDriveStorage::printBool(BoolResponse response) { - 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()); -} - Networking::Request *OneDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); return addRequest(new OneDriveCreateDirectoryRequest(this, path, callback, errorCallback)); @@ -285,36 +251,5 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { return new OneDriveStorage(accessToken, userId, refreshToken); } -Common::String OneDriveStorage::getAuthLink() { - Common::String url = "https://login.live.com/oauth20_authorize.srf"; - url += "?response_type=code"; - url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting - //url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening - url += "&client_id="; url += KEY; - url += "&scope=onedrive.appfolder%20offline_access"; //TODO - return url; -} - -void OneDriveStorage::authThroughConsole() { - if (!ConfMan.hasKey("ONEDRIVE_KEY", ConfMan.kCloudDomain) || !ConfMan.hasKey("ONEDRIVE_SECRET", ConfMan.kCloudDomain)) { - warning("No OneDrive keys available, cannot do auth"); - return; - } - - loadKeyAndSecret(); - - if (ConfMan.hasKey("onedrive_code", ConfMan.kCloudDomain)) { - //phase 2: get access_token using specified code - new OneDriveStorage(ConfMan.get("onedrive_code", ConfMan.kCloudDomain)); - return; - } - - debug("Navigate to this URL and press \"Allow\":"); - debug("%s\n", getAuthLink().c_str()); - debug("Then, add onedrive_code key in [cloud] section of configuration file. You should copy the value from URL and put it as value for that key.\n"); - debug("Navigate to this URL to get more information on ScummVM's configuration files:"); - debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n"); -} - } // End of namespace OneDrive } // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 061d0fa172..650c240aef 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -24,7 +24,6 @@ #define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVESTORAGE_H #include "backends/cloud/storage.h" -#include "common/callback.h" #include "backends/networking/curl/curljsonrequest.h" namespace Cloud { @@ -46,12 +45,6 @@ class OneDriveStorage: public Cloud::Storage { /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); - void printJson(Networking::JsonResponse response); - void fileDownloaded(BoolResponse response); - void printFiles(FileArrayResponse response); - void printBool(BoolResponse response); - void printFile(UploadResponse response); - void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); public: /** This constructor uses OAuth code flow to get tokens. */ @@ -88,9 +81,6 @@ public: /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); @@ -106,16 +96,6 @@ public: */ static OneDriveStorage *loadFromConfig(Common::String keyPrefix); - /** - * Returns OneDrive auth link. - */ - static Common::String getAuthLink(); - - /** - * Show message with OneDrive auth instructions. (Temporary) - */ - static void authThroughConsole(); - /** * Gets new access_token. If passed is "", refresh_token is used. * Use "" in order to refresh token and pass a callback, so you could diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 273b93c764..414a722c64 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -140,9 +140,6 @@ public: /** Returns Common::Array with list of files, which were not downloaded. */ virtual Networking::Request *downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); - /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; - /** Calls the callback when finished. */ virtual SavesSyncRequest *syncSaves(BoolCallback callback, Networking::ErrorCallback errorCallback); -- cgit v1.2.3 From 1a53dccf51aaf02ca4d0d7a176cca20d385d1ac4 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 09:27:08 +0600 Subject: CLOUD: Update DownloadRequest It now uses a dynamically allocated 1 MB buffer. --- backends/cloud/downloadrequest.cpp | 9 ++++----- backends/cloud/downloadrequest.h | 3 +++ 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index c95b8b81af..43bb02a756 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -29,7 +29,7 @@ namespace Cloud { DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFileId, Common::DumpFile *dumpFile): Request(nullptr, ecb), _boolCallback(callback), _localFile(dumpFile), _remoteFileId(remoteFileId), _storage(storage), - _remoteFileStream(nullptr), _workingRequest(nullptr), _ignoreCallback(false) { + _remoteFileStream(nullptr), _workingRequest(nullptr), _ignoreCallback(false), _buffer(new byte[DOWNLOAD_REQUEST_BUFFER_SIZE]) { start(); } @@ -38,6 +38,7 @@ DownloadRequest::~DownloadRequest() { if (_workingRequest) _workingRequest->finish(); delete _boolCallback; delete _localFile; + delete[] _buffer; } void DownloadRequest::start() { @@ -84,12 +85,10 @@ void DownloadRequest::handle() { return; } - const int kBufSize = 640 * 1024; //640 KB is enough to everyone?.. - char buf[kBufSize]; - uint32 readBytes = _remoteFileStream->read(buf, kBufSize); + uint32 readBytes = _remoteFileStream->read(_buffer, DOWNLOAD_REQUEST_BUFFER_SIZE); if (readBytes != 0) - if (_localFile->write(buf, readBytes) != readBytes) { + if (_localFile->write(_buffer, readBytes) != readBytes) { warning("DownloadRequest: unable to write all received bytes into output file"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); return; diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index d8e18f9171..99b7de37f0 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -30,6 +30,8 @@ namespace Cloud { +#define DOWNLOAD_REQUEST_BUFFER_SIZE 1 * 1024 * 1024 + class DownloadRequest: public Networking::Request { Storage::BoolCallback _boolCallback; Common::DumpFile *_localFile; @@ -38,6 +40,7 @@ class DownloadRequest: public Networking::Request { Networking::NetworkReadStream *_remoteFileStream; Request *_workingRequest; bool _ignoreCallback; + byte *_buffer; void start(); void streamCallback(Networking::NetworkReadStreamResponse response); -- cgit v1.2.3 From dfd68306de6f655a7bd2c68cea0b9299956ce8fc Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 10:17:26 +0600 Subject: CLOUD: Upgrade FolderDownloadRequest::getProgress() Now NetworkReadStream, which is used in DownloadRequest, which is used in FolderDownloadRequest, returns progress information provided by libcurl. --- backends/cloud/downloadrequest.cpp | 6 ++++++ backends/cloud/downloadrequest.h | 3 +++ backends/cloud/folderdownloadrequest.cpp | 17 ++++++++++++++--- backends/cloud/folderdownloadrequest.h | 2 +- backends/cloud/id/iddownloadrequest.cpp | 7 +++++++ backends/cloud/id/iddownloadrequest.h | 3 +++ 6 files changed, 34 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 43bb02a756..5efb87e0c8 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -122,4 +122,10 @@ void DownloadRequest::finishError(Networking::ErrorResponse error) { Request::finishError(error); } +double DownloadRequest::getProgress() const { + if (_remoteFileStream) + return _remoteFileStream->getProgress(); + return 0; +} + } // End of namespace Cloud diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index 99b7de37f0..138616a04b 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -54,6 +54,9 @@ public: virtual void handle(); virtual void restart(); + + /** Returns a number in range [0, 1], where 1 is "complete". */ + double getProgress() const; }; } // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 6cf55b28cf..bbb3c646ac 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -21,6 +21,8 @@ */ #include "backends/cloud/folderdownloadrequest.h" +#include "backends/cloud/downloadrequest.h" +#include "backends/cloud/id/iddownloadrequest.h" #include "common/debug.h" #include "gui/downloaddialog.h" @@ -133,9 +135,18 @@ void FolderDownloadRequest::finishDownload(Common::Array &files) { if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); } -double FolderDownloadRequest::getProgress() { - if (_totalFiles == 0) return 0; - return (double)(_totalFiles - _files.size()) / (double)(_totalFiles); +double FolderDownloadRequest::getProgress() const { + if (_totalFiles == 0) return 0; + + double currentFileProgress = 0; + DownloadRequest *downloadRequest = dynamic_cast(_workingRequest); + if (downloadRequest != nullptr) currentFileProgress = downloadRequest->getProgress(); + else { + Id::IdDownloadRequest *idDownloadRequest = dynamic_cast(_workingRequest); + if (idDownloadRequest != nullptr) currentFileProgress = idDownloadRequest->getProgress(); + } + + return (double)(_totalFiles - _files.size() + currentFileProgress) / (double)(_totalFiles); } } // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 41eacc2afe..a5f13b740b 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -56,7 +56,7 @@ public: virtual void restart(); /** Returns a number in range [0, 1], where 1 is "complete". */ - double getProgress(); + double getProgress() const; /** Returns remote directory path. */ Common::String getRemotePath() { return _remoteDirectoryPath; } diff --git a/backends/cloud/id/iddownloadrequest.cpp b/backends/cloud/id/iddownloadrequest.cpp index 154bd16edd..ac62284d46 100644 --- a/backends/cloud/id/iddownloadrequest.cpp +++ b/backends/cloud/id/iddownloadrequest.cpp @@ -22,6 +22,7 @@ #include "backends/cloud/id/iddownloadrequest.h" #include "backends/cloud/id/idstorage.h" +#include "backends/cloud/downloadrequest.h" namespace Cloud { namespace Id { @@ -87,5 +88,11 @@ void IdDownloadRequest::finishDownload(bool success) { if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); } +double IdDownloadRequest::getProgress() const { + DownloadRequest *downloadRequest = dynamic_cast(_workingRequest); + if (downloadRequest == nullptr) return 0.02; // resolving id still + return 0.1 + 0.9 * downloadRequest->getProgress(); // downloading +} + } // End of namespace Id } // End of namespace Cloud diff --git a/backends/cloud/id/iddownloadrequest.h b/backends/cloud/id/iddownloadrequest.h index 70397696a8..65e05c00b3 100644 --- a/backends/cloud/id/iddownloadrequest.h +++ b/backends/cloud/id/iddownloadrequest.h @@ -51,6 +51,9 @@ public: virtual void handle(); virtual void restart(); + + /** Returns a number in range [0, 1], where 1 is "complete". */ + double getProgress() const; }; } // End of namespace Id -- cgit v1.2.3 From 7951a2ea167dee8c380ade40fefa95bb4d9baec1 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Thu, 14 Jul 2016 10:00:34 +0200 Subject: CLOUD: Rename _files to _pendingFiles in FolderDownloadRequest --- backends/cloud/folderdownloadrequest.cpp | 14 +++++++------- backends/cloud/folderdownloadrequest.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index bbb3c646ac..1d42f27d3f 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -47,7 +47,7 @@ void FolderDownloadRequest::start() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); _currentFile = StorageFile(); - _files.clear(); + _pendingFiles.clear(); _failedFiles.clear(); _ignoreCallback = false; _totalFiles = 0; @@ -64,8 +64,8 @@ void FolderDownloadRequest::start() { void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - _files = response.value; - _totalFiles = _files.size(); + _pendingFiles = response.value; + _totalFiles = _pendingFiles.size(); downloadNextFile(); } @@ -90,13 +90,13 @@ void FolderDownloadRequest::fileDownloadedErrorCallback(Networking::ErrorRespons void FolderDownloadRequest::downloadNextFile() { do { - if (_files.empty()) { + if (_pendingFiles.empty()) { finishDownload(_failedFiles); return; } - _currentFile = _files.back(); - _files.pop_back(); + _currentFile = _pendingFiles.back(); + _pendingFiles.pop_back(); } while (_currentFile.isDirectory()); //TODO: may be create these directories (in case those are empty) sendCommand(GUI::kDownloadProgressCmd, (int)(getProgress() * 100)); @@ -146,7 +146,7 @@ double FolderDownloadRequest::getProgress() const { if (idDownloadRequest != nullptr) currentFileProgress = idDownloadRequest->getProgress(); } - return (double)(_totalFiles - _files.size() + currentFileProgress) / (double)(_totalFiles); + return (double)(_totalFiles - _pendingFiles.size() + currentFileProgress) / (double)(_totalFiles); } } // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index a5f13b740b..ee17de08dc 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -35,7 +35,7 @@ class FolderDownloadRequest: public Networking::Request, public GUI::CommandSend Storage::FileArrayCallback _fileArrayCallback; Common::String _remoteDirectoryPath, _localDirectoryPath; bool _recursive; - Common::Array _files, _failedFiles; + Common::Array _pendingFiles, _failedFiles; StorageFile _currentFile; Request *_workingRequest; bool _ignoreCallback; -- cgit v1.2.3 From d863dad055acbc066d86f7fbfa054e7f4c2dd7b2 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 14:55:03 +0600 Subject: CLOUD: Fix FolderDownloadRequest::getProgress() Now it doesn't stop on 100 % on last file and it ignores the directories, so it doesn't "jump" suddenly as there are no directories to skip. --- backends/cloud/folderdownloadrequest.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 1d42f27d3f..c77fc27b35 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -65,6 +65,14 @@ void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryRespon _workingRequest = nullptr; if (_ignoreCallback) return; _pendingFiles = response.value; + + // remove all directories + for (Common::Array::iterator i = _pendingFiles.begin(); i != _pendingFiles.end(); ) + if (i->isDirectory()) + _pendingFiles.erase(i); + else + ++i; + _totalFiles = _pendingFiles.size(); downloadNextFile(); } @@ -146,7 +154,8 @@ double FolderDownloadRequest::getProgress() const { if (idDownloadRequest != nullptr) currentFileProgress = idDownloadRequest->getProgress(); } - return (double)(_totalFiles - _pendingFiles.size() + currentFileProgress) / (double)(_totalFiles); + uint32 uploadedFiles = _totalFiles - _pendingFiles.size() - 1; // -1 because currently downloaded file is already removed from _pendingFiles + return (double)(uploadedFiles + currentFileProgress) / (double)(_totalFiles); } } // End of namespace Cloud -- cgit v1.2.3 From ca33c0a0a8ce31b13137f74ba15e226b3855b75a Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 14:55:50 +0600 Subject: CLOUD: Fix FolderDownloadRequest It now sends kDownloadEndedCmd on success without waiting to be destructed. --- backends/cloud/folderdownloadrequest.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index c77fc27b35..f5c872b461 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -99,6 +99,7 @@ void FolderDownloadRequest::fileDownloadedErrorCallback(Networking::ErrorRespons void FolderDownloadRequest::downloadNextFile() { do { if (_pendingFiles.empty()) { + sendCommand(GUI::kDownloadEndedCmd, 0); finishDownload(_failedFiles); return; } -- cgit v1.2.3 From 0ca791709329c3e7f24f68fa2da7c86c87dac557 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 15:29:47 +0600 Subject: CLOUD: Update FolderDownloadRequest It now keeps track of downloaded bytes. --- backends/cloud/cloudmanager.cpp | 12 ++++++++++++ backends/cloud/cloudmanager.h | 6 ++++++ backends/cloud/folderdownloadrequest.cpp | 24 +++++++++++++++++++++++- backends/cloud/folderdownloadrequest.h | 7 +++++++ backends/cloud/storage.cpp | 18 ++++++++++++++++++ backends/cloud/storage.h | 6 ++++++ 6 files changed, 72 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index e5b2c2a69d..80ee24808c 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -346,6 +346,18 @@ double CloudManager::getDownloadingProgress() { return 1; } +uint64 CloudManager::getDownloadBytesNumber() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getDownloadBytesNumber(); + return 1; +} + +uint64 CloudManager::getDownloadTotalBytesNumber() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getDownloadTotalBytesNumber(); + return 1; +} + Common::String CloudManager::getDownloadRemoteDirectory() { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadRemoteDirectory(); diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 1098bddaa6..0baede7fe9 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -244,6 +244,12 @@ public: /** Returns a number in [0, 1] range which represents current download progress (1 = complete). */ double getDownloadingProgress(); + /** Returns a number of bytes that is downloaded in current download progress. */ + uint64 getDownloadBytesNumber(); + + /** Returns a total number of bytes to be downloaded in current download progress. */ + uint64 getDownloadTotalBytesNumber(); + /** Returns remote directory path. */ virtual Common::String getDownloadRemoteDirectory(); diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index f5c872b461..ca3f9a1c99 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -51,6 +51,7 @@ void FolderDownloadRequest::start() { _failedFiles.clear(); _ignoreCallback = false; _totalFiles = 0; + _downloadedBytes = _totalBytes = 0; //list directory first _workingRequest = _storage->listDirectory( @@ -70,8 +71,10 @@ void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryRespon for (Common::Array::iterator i = _pendingFiles.begin(); i != _pendingFiles.end(); ) if (i->isDirectory()) _pendingFiles.erase(i); - else + else { + _totalBytes += i->size(); ++i; + } _totalFiles = _pendingFiles.size(); downloadNextFile(); @@ -87,6 +90,7 @@ void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse respons _workingRequest = nullptr; if (_ignoreCallback) return; if (!response.value) _failedFiles.push_back(_currentFile); + _downloadedBytes += _currentFile.size(); downloadNextFile(); } @@ -159,4 +163,22 @@ double FolderDownloadRequest::getProgress() const { return (double)(uploadedFiles + currentFileProgress) / (double)(_totalFiles); } +uint64 FolderDownloadRequest::getDownloadedBytes() const { + if (_totalFiles == 0) return 0; + + double currentFileProgress = 0; + DownloadRequest *downloadRequest = dynamic_cast(_workingRequest); + if (downloadRequest != nullptr) currentFileProgress = downloadRequest->getProgress(); + else { + Id::IdDownloadRequest *idDownloadRequest = dynamic_cast(_workingRequest); + if (idDownloadRequest != nullptr) currentFileProgress = idDownloadRequest->getProgress(); + } + + return _downloadedBytes + (uint64)(currentFileProgress * _currentFile.size()); +} + +uint64 FolderDownloadRequest::getTotalBytesToDownload() const { + return _totalBytes; +} + } // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index ee17de08dc..1a67f32165 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -40,6 +40,7 @@ class FolderDownloadRequest: public Networking::Request, public GUI::CommandSend Request *_workingRequest; bool _ignoreCallback; uint32 _totalFiles; + uint64 _downloadedBytes, _totalBytes; void start(); void directoryListedCallback(Storage::ListDirectoryResponse response); @@ -58,6 +59,12 @@ public: /** Returns a number in range [0, 1], where 1 is "complete". */ double getProgress() const; + /** Returns a number of downloaded bytes. */ + uint64 getDownloadedBytes() const; + + /** Returns a total number of bytes to download. */ + uint64 getTotalBytesToDownload() const; + /** Returns remote directory path. */ Common::String getRemotePath() { return _remoteDirectoryPath; } diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 110c97ad9c..c9843d6188 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -241,6 +241,24 @@ double Storage::getDownloadingProgress() { return result; } +uint64 Storage::getDownloadBytesNumber() { + uint64 result = 0; + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + result = _downloadFolderRequest->getDownloadedBytes(); + _runningRequestsMutex.unlock(); + return result; +} + +uint64 Storage::getDownloadTotalBytesNumber() { + uint64 result = 0; + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + result = _downloadFolderRequest->getTotalBytesToDownload(); + _runningRequestsMutex.unlock(); + return result; +} + Common::String Storage::getDownloadRemoteDirectory() { Common::String result = ""; _runningRequestsMutex.lock(); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 414a722c64..6d9db33bc6 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -198,6 +198,12 @@ public: /** Returns a number in [0, 1] range which represents current download progress (1 = complete). */ virtual double getDownloadingProgress(); + /** Returns a number of bytes that is downloaded in current download progress. */ + virtual uint64 getDownloadBytesNumber(); + + /** Returns a total number of bytes to be downloaded in current download progress. */ + virtual uint64 getDownloadTotalBytesNumber(); + /** Returns remote directory path. */ virtual Common::String getDownloadRemoteDirectory(); -- cgit v1.2.3 From 479c76bbd2752f0bf2d1bab2a00cb7dd1544d1a8 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 15:35:38 +0600 Subject: CLOUD: Fix IdDownloadRequest Wrong value was returned in getProgress() on nullptr there. --- backends/cloud/id/iddownloadrequest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/id/iddownloadrequest.cpp b/backends/cloud/id/iddownloadrequest.cpp index ac62284d46..7166a1e026 100644 --- a/backends/cloud/id/iddownloadrequest.cpp +++ b/backends/cloud/id/iddownloadrequest.cpp @@ -90,7 +90,9 @@ void IdDownloadRequest::finishDownload(bool success) { double IdDownloadRequest::getProgress() const { DownloadRequest *downloadRequest = dynamic_cast(_workingRequest); - if (downloadRequest == nullptr) return 0.02; // resolving id still + if (downloadRequest == nullptr) return 0; // resolving id still + + // id resolve is 10 % and download is the other 90 % return 0.1 + 0.9 * downloadRequest->getProgress(); // downloading } -- cgit v1.2.3 From 85adefdb86e914a789a0db18c767c8ef5902f846 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 15:45:03 +0600 Subject: CLOUD: Update FolderDownloadRequest::getProgress() It now is based on downloaded size, not number of files. --- backends/cloud/folderdownloadrequest.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index ca3f9a1c99..6a7b5d3aaf 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -149,18 +149,8 @@ void FolderDownloadRequest::finishDownload(Common::Array &files) { } double FolderDownloadRequest::getProgress() const { - if (_totalFiles == 0) return 0; - - double currentFileProgress = 0; - DownloadRequest *downloadRequest = dynamic_cast(_workingRequest); - if (downloadRequest != nullptr) currentFileProgress = downloadRequest->getProgress(); - else { - Id::IdDownloadRequest *idDownloadRequest = dynamic_cast(_workingRequest); - if (idDownloadRequest != nullptr) currentFileProgress = idDownloadRequest->getProgress(); - } - - uint32 uploadedFiles = _totalFiles - _pendingFiles.size() - 1; // -1 because currently downloaded file is already removed from _pendingFiles - return (double)(uploadedFiles + currentFileProgress) / (double)(_totalFiles); + if (_totalFiles == 0 || _totalBytes == 0) return 0; + return (double)getDownloadedBytes() / (double)getTotalBytesToDownload(); } uint64 FolderDownloadRequest::getDownloadedBytes() const { -- cgit v1.2.3 From c431ae6d84be1ef73c44b84c58ee3d9edff3d5e3 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 14 Jul 2016 16:01:05 +0600 Subject: CLOUD: Calculate FolderDownload download speed --- backends/cloud/cloudmanager.cpp | 10 ++++++++-- backends/cloud/cloudmanager.h | 3 +++ backends/cloud/folderdownloadrequest.cpp | 15 +++++++++++++-- backends/cloud/folderdownloadrequest.h | 5 ++++- backends/cloud/storage.cpp | 9 +++++++++ backends/cloud/storage.h | 3 +++ 6 files changed, 40 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 80ee24808c..7156197368 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -349,13 +349,19 @@ double CloudManager::getDownloadingProgress() { uint64 CloudManager::getDownloadBytesNumber() { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadBytesNumber(); - return 1; + return 0; } uint64 CloudManager::getDownloadTotalBytesNumber() { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadTotalBytesNumber(); - return 1; + return 0; +} + +uint64 CloudManager::getDownloadSpeed() { + Storage *storage = getCurrentStorage(); + if (storage) return storage->getDownloadSpeed(); + return 0; } Common::String CloudManager::getDownloadRemoteDirectory() { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 0baede7fe9..15409ee3a1 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -250,6 +250,9 @@ public: /** Returns a total number of bytes to be downloaded in current download progress. */ uint64 getDownloadTotalBytesNumber(); + /** Returns download speed of current download progress. */ + uint64 getDownloadSpeed(); + /** Returns remote directory path. */ virtual Common::String getDownloadRemoteDirectory(); diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 6a7b5d3aaf..d506d80c48 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -25,6 +25,7 @@ #include "backends/cloud/id/iddownloadrequest.h" #include "common/debug.h" #include "gui/downloaddialog.h" +#include namespace Cloud { @@ -51,7 +52,7 @@ void FolderDownloadRequest::start() { _failedFiles.clear(); _ignoreCallback = false; _totalFiles = 0; - _downloadedBytes = _totalBytes = 0; + _downloadedBytes = _totalBytes = _wasDownloadedBytes = _currentDownloadSpeed = 0; //list directory first _workingRequest = _storage->listDirectory( @@ -139,7 +140,13 @@ void FolderDownloadRequest::downloadNextFile() { ); } -void FolderDownloadRequest::handle() {} +void FolderDownloadRequest::handle() { + uint32 microsecondsPassed = Networking::ConnectionManager::getCloudRequestsPeriodInMicroseconds(); + uint64 currentDownloadedBytes = getDownloadedBytes(); + uint64 downloadedThisPeriod = currentDownloadedBytes - _wasDownloadedBytes; + _currentDownloadSpeed = downloadedThisPeriod * (1000000L / microsecondsPassed); + _wasDownloadedBytes = currentDownloadedBytes; +} void FolderDownloadRequest::restart() { start(); } @@ -171,4 +178,8 @@ uint64 FolderDownloadRequest::getTotalBytesToDownload() const { return _totalBytes; } +uint64 FolderDownloadRequest::getDownloadSpeed() const { + return _currentDownloadSpeed; +} + } // End of namespace Cloud diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 1a67f32165..9d8dea4d20 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -40,7 +40,7 @@ class FolderDownloadRequest: public Networking::Request, public GUI::CommandSend Request *_workingRequest; bool _ignoreCallback; uint32 _totalFiles; - uint64 _downloadedBytes, _totalBytes; + uint64 _downloadedBytes, _totalBytes, _wasDownloadedBytes, _currentDownloadSpeed; void start(); void directoryListedCallback(Storage::ListDirectoryResponse response); @@ -65,6 +65,9 @@ public: /** Returns a total number of bytes to download. */ uint64 getTotalBytesToDownload() const; + /** Returns average download speed for the last second. */ + uint64 getDownloadSpeed() const; + /** Returns remote directory path. */ Common::String getRemotePath() { return _remoteDirectoryPath; } diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index c9843d6188..c20ad865ad 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -259,6 +259,15 @@ uint64 Storage::getDownloadTotalBytesNumber() { return result; } +uint64 Storage::getDownloadSpeed() { + uint64 result = 0; + _runningRequestsMutex.lock(); + if (_downloadFolderRequest) + result = _downloadFolderRequest->getDownloadSpeed(); + _runningRequestsMutex.unlock(); + return result; +} + Common::String Storage::getDownloadRemoteDirectory() { Common::String result = ""; _runningRequestsMutex.lock(); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 6d9db33bc6..a577b3c468 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -204,6 +204,9 @@ public: /** Returns a total number of bytes to be downloaded in current download progress. */ virtual uint64 getDownloadTotalBytesNumber(); + /** Returns download speed of current download progress. */ + virtual uint64 getDownloadSpeed(); + /** Returns remote directory path. */ virtual Common::String getDownloadRemoteDirectory(); -- cgit v1.2.3 From 55568d757ce2990a285a6193a60242f9932d0797 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 19 Jul 2016 15:27:26 +0600 Subject: CLOUD: Move Dropbox to API v2 We had a few places where their deprecated API v1 was used. --- backends/cloud/cloudmanager.cpp | 2 +- backends/cloud/dropbox/dropboxinforequest.cpp | 143 ++++++++++++++++++++++++++ backends/cloud/dropbox/dropboxinforequest.h | 56 ++++++++++ backends/cloud/dropbox/dropboxstorage.cpp | 50 +-------- backends/cloud/dropbox/dropboxstorage.h | 6 -- 5 files changed, 205 insertions(+), 52 deletions(-) create mode 100644 backends/cloud/dropbox/dropboxinforequest.cpp create mode 100644 backends/cloud/dropbox/dropboxinforequest.h (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 7156197368..b6a721be90 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -245,7 +245,7 @@ Networking::Request *CloudManager::downloadFolder(Common::String remotePath, Com Networking::Request *CloudManager::info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); - if (storage) storage->info(callback, errorCallback); + if (storage) return storage->info(callback, errorCallback); else { delete callback; delete errorCallback; diff --git a/backends/cloud/dropbox/dropboxinforequest.cpp b/backends/cloud/dropbox/dropboxinforequest.cpp new file mode 100644 index 0000000000..f5a14abe1c --- /dev/null +++ b/backends/cloud/dropbox/dropboxinforequest.cpp @@ -0,0 +1,143 @@ +/* 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/dropboxinforequest.h" +#include "backends/cloud/cloudmanager.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" + +namespace Cloud { +namespace Dropbox { + +DropboxInfoRequest::DropboxInfoRequest(Common::String token, Storage::StorageInfoCallback cb, Networking::ErrorCallback ecb): + Networking::Request(nullptr, ecb), _token(token), _infoCallback(cb), + _workingRequest(nullptr), _ignoreCallback(false) { + start(); +} + +DropboxInfoRequest::~DropboxInfoRequest() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + delete _infoCallback; +} + +void DropboxInfoRequest::start() { + _ignoreCallback = true; + if (_workingRequest) _workingRequest->finish(); + _ignoreCallback = false; + + Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxInfoRequest::userResponseCallback); + Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxInfoRequest::errorCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/2/users/get_current_account"); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Content-Type: application/json"); + request->addPostField("null"); //use POST + + _workingRequest = ConnMan.addRequest(request); +} + +void DropboxInfoRequest::userResponseCallback(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + _workingRequest = nullptr; + if (_ignoreCallback) { + delete json; + return; + } + + Networking::ErrorResponse error(this); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + if (rq && rq->getNetworkReadStream()) + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + + if (!json) { + warning("NULL passed instead of JSON"); + finishError(error); + return; + } + + //Dropbox documentation states there are no errors for this API method + Common::JSONObject info = json->asObject(); + Common::JSONObject nameInfo = info.getVal("name")->asObject(); + _uid = info.getVal("account_id")->asString(); + _name = nameInfo.getVal("display_name")->asString(); + _email = info.getVal("email")->asString(); + CloudMan.setStorageUsername(kStorageDropboxId, _email); + delete json; + + Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxInfoRequest::quotaResponseCallback); + Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxInfoRequest::errorCallback); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/2/users/get_space_usage"); + request->addHeader("Authorization: Bearer " + _token); + request->addHeader("Content-Type: application/json"); + request->addPostField("null"); //use POST + + _workingRequest = ConnMan.addRequest(request); +} + +void DropboxInfoRequest::quotaResponseCallback(Networking::JsonResponse response) { + Common::JSONValue *json = response.value; + _workingRequest = nullptr; + if (_ignoreCallback) { + delete json; + return; + } + + Networking::ErrorResponse error(this); + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + if (rq && rq->getNetworkReadStream()) + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + + if (!json) { + warning("NULL passed instead of JSON"); + finishError(error); + return; + } + + //Dropbox documentation states there are no errors for this API method + Common::JSONObject info = json->asObject(); + Common::JSONObject allocation = info.getVal("allocation")->asObject(); + uint64 used = info.getVal("used")->asIntegerNumber(); + uint64 allocated = allocation.getVal("allocated")->asIntegerNumber(); + finishInfo(StorageInfo(_uid, _name, _email, used, allocated)); + delete json; +} + +void DropboxInfoRequest::errorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) return; + finishError(error); +} + +void DropboxInfoRequest::handle() {} + +void DropboxInfoRequest::restart() { start(); } + +void DropboxInfoRequest::finishInfo(StorageInfo info) { + Request::finishSuccess(); + if (_infoCallback) (*_infoCallback)(Storage::StorageInfoResponse(this, info)); +} + +} // End of namespace Dropbox +} // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxinforequest.h b/backends/cloud/dropbox/dropboxinforequest.h new file mode 100644 index 0000000000..a91d016e60 --- /dev/null +++ b/backends/cloud/dropbox/dropboxinforequest.h @@ -0,0 +1,56 @@ +/* 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_DROPBOXINFOREQUEST_H +#define BACKENDS_CLOUD_DROPBOX_DROPBOXINFOREQUEST_H + +#include "backends/cloud/storage.h" +#include "backends/networking/curl/request.h" +#include "backends/networking/curl/curljsonrequest.h" + +namespace Cloud { +namespace Dropbox { + +class DropboxInfoRequest: public Networking::Request { + Common::String _token; + Common::String _uid, _name, _email; + Storage::StorageInfoCallback _infoCallback; + Request *_workingRequest; + bool _ignoreCallback; + + void start(); + void userResponseCallback(Networking::JsonResponse response); + void quotaResponseCallback(Networking::JsonResponse response); + void errorCallback(Networking::ErrorResponse error); + void finishInfo(StorageInfo info); +public: + DropboxInfoRequest(Common::String token, Storage::StorageInfoCallback cb, Networking::ErrorCallback ecb); + virtual ~DropboxInfoRequest(); + + virtual void handle(); + virtual void restart(); +}; + +} // End of namespace Dropbox +} // End of namespace Cloud + +#endif diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 8343b74aa0..e34912ed66 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -23,6 +23,7 @@ #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/dropbox/dropboxcreatedirectoryrequest.h" +#include "backends/cloud/dropbox/dropboxinforequest.h" #include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h" #include "backends/cloud/dropbox/dropboxuploadrequest.h" #include "backends/cloud/cloudmanager.h" @@ -62,7 +63,7 @@ DropboxStorage::~DropboxStorage() {} void DropboxStorage::getAccessToken(Common::String code) { if (!KEY || !SECRET) loadKeyAndSecret(); Networking::JsonCallback callback = new Common::Callback(this, &DropboxStorage::codeFlowComplete); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, nullptr, "https://api.dropboxapi.com/1/oauth2/token"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, nullptr, "https://api.dropboxapi.com/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + Common::String(KEY)); @@ -133,54 +134,13 @@ Networking::Request *DropboxStorage::createDirectory(Common::String path, BoolCa return addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback)); } -Networking::Request *DropboxStorage::info(StorageInfoCallback outerCallback, Networking::ErrorCallback errorCallback) { - Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &DropboxStorage::infoInnerCallback, outerCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/1/account/info"); - request->addHeader("Authorization: Bearer " + _token); - return addRequest(request); - //that callback bridge wraps the outerCallback (passed in arguments from user) into innerCallback - //so, when CurlJsonRequest is finished, it calls the innerCallback - //innerCallback (which is DropboxStorage::infoInnerCallback in this case) processes the void *ptr - //and then calls the outerCallback (which wants to receive StorageInfo, not void *) +Networking::Request *DropboxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { + if (!errorCallback) errorCallback = getErrorPrintingCallback(); + return addRequest(new DropboxInfoRequest(_token, callback, errorCallback)); } Common::String DropboxStorage::savesDirectoryPath() { return "/saves/"; } -void DropboxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { - Common::JSONValue *json = response.value; - if (!json) { - warning("NULL passed instead of JSON"); - delete outerCallback; - return; - } - - //Dropbox documentation states there is no errors for this API method - Common::JSONObject info = json->asObject(); - Common::String uid = Common::String::format("%d", (int)info.getVal("uid")->asIntegerNumber()); - Common::String name = info.getVal("display_name")->asString(); - Common::String email = info.getVal("email")->asString(); - Common::JSONObject quota = info.getVal("quota_info")->asObject(); - uint64 quotaNormal = quota.getVal("normal")->asIntegerNumber(); - uint64 quotaShared = quota.getVal("shared")->asIntegerNumber(); - uint64 quotaAllocated = quota.getVal("quota")->asIntegerNumber(); - - CloudMan.setStorageUsername(kStorageDropboxId, email); - - if (outerCallback) { - (*outerCallback)(StorageInfoResponse(nullptr, StorageInfo(uid, name, email, quotaNormal+quotaShared, quotaAllocated))); - delete outerCallback; - } - - delete json; -} - -void DropboxStorage::infoMethodCallback(StorageInfoResponse response) { - debug("\nStorage info:"); - debug("User name: %s", response.value.name().c_str()); - debug("Email: %s", response.value.email().c_str()); - debug("Disk usage: %u/%u", (uint32)response.value.used(), (uint32)response.value.available()); -} - DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index b3dc64139c..2c9cf163ab 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -43,9 +43,6 @@ class DropboxStorage: public Cloud::Storage { void getAccessToken(Common::String code); void codeFlowComplete(Networking::JsonResponse response); - /** Constructs StorageInfo based on JSON response from cloud. */ - void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); - public: /** This constructor uses OAuth code flow to get tokens. */ DropboxStorage(Common::String code); @@ -90,9 +87,6 @@ public: /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); - /** This method is passed into info(). (Temporary) */ - void infoMethodCallback(StorageInfoResponse response); - /** Returns storage's saves directory path with the trailing slash. */ virtual Common::String savesDirectoryPath(); -- cgit v1.2.3 From d0c54cdd64a174f648321608d29f3c0860837256 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 19 Jul 2016 15:47:46 +0600 Subject: CLOUD: Fix DropboxCreateDirectoryRequest It now calls success callback with `false` on Dropbox's "path/conflict/folder", indicating that the directory already exists. --- backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index a52d41e896..81ace75dda 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -84,6 +84,14 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re Common::JSONObject info = json->asObject(); if (info.contains("id")) finishCreation(true); else { + if (info.contains("error_summary") && info.getVal("error_summary")->isString()) { + Common::String summary = info.getVal("error_summary")->asString(); + if (summary.contains("path") && summary.contains("conflict") && summary.contains("folder")) { + finishCreation(false); + delete json; + return; + } + } error.response = json->stringify(true); finishError(error); } -- cgit v1.2.3 From 0c1c274abdbdb4183d9a08669082227aa912b1ea Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 19 Jul 2016 16:36:48 +0600 Subject: CLOUD: Fix OneDriveUploadRequest OneDrive doesn't accept empty files, so UploadRequest just skips such. --- backends/cloud/onedrive/onedriveuploadrequest.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index fb32443a27..55359f83e7 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -92,9 +92,15 @@ void OneDriveUploadRequest::uploadNextPart() { 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())); ; + request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos()-1, _contentsStream->size())); + else + if (_contentsStream->size() == 0) { + warning("\"Sorry, OneDrive can't upload empty files\""); + finishUpload(StorageFile(_savePath, 0, 0, false)); + delete request; + return; + } _workingRequest = ConnMan.addRequest(request); } -- cgit v1.2.3 From 6753c18d6f182f98db0fe9403991392482d7a9fa Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 20 Jul 2016 12:45:09 +0600 Subject: CLOUD: Add default SavesSync callbacks With OSD messages indicating whether saves sync is complete, cancelled or failed. --- backends/cloud/storage.cpp | 25 ++++++++++++++++++++++++- backends/cloud/storage.h | 8 ++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index c20ad865ad..d4548b84cb 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -128,7 +128,8 @@ SavesSyncRequest *Storage::syncSaves(BoolCallback callback, Networking::ErrorCal _runningRequestsMutex.unlock(); return _savesSyncRequest; } - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!callback) callback = new Common::Callback(this, &Storage::savesSyncDefaultCallback); + if (!errorCallback) errorCallback = new Common::Callback(this, &Storage::savesSyncDefaultErrorCallback); _savesSyncRequest = new SavesSyncRequest(this, callback, errorCallback); _syncRestartRequestsed = false; _runningRequestsMutex.unlock(); @@ -192,6 +193,28 @@ void Storage::setSyncTarget(GUI::CommandReceiver *target) { _runningRequestsMutex.unlock(); } +void Storage::savesSyncDefaultCallback(BoolResponse response) { + _runningRequestsMutex.lock(); + _savesSyncRequest = nullptr; + _runningRequestsMutex.unlock(); + + if (!response.value) warning("SavesSyncRequest called success callback with `false` argument"); + g_system->displayMessageOnOSD(_("Saves sync complete.")); +} + +void Storage::savesSyncDefaultErrorCallback(Networking::ErrorResponse error) { + _runningRequestsMutex.lock(); + _savesSyncRequest = nullptr; + _runningRequestsMutex.unlock(); + + printErrorResponse(error); + + if (error.interrupted) + g_system->displayMessageOnOSD(_("Saves sync was cancelled.")); + else + g_system->displayMessageOnOSD(_("Saves sync failed.\nCheck your Internet connection.")); +} + ///// DownloadFolderRequest-related ///// bool Storage::startDownload(Common::String remotePath, Common::String localPath) { diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index a577b3c468..b33d69e411 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -181,6 +181,14 @@ public: /** Sets SavesSyncRequest's target to given CommandReceiver. */ virtual void setSyncTarget(GUI::CommandReceiver *target); +protected: + /** Finishes the sync. Shows an OSD message. */ + virtual void savesSyncDefaultCallback(BoolResponse response); + + /** Finishes the sync. Shows an OSD message. */ + virtual void savesSyncDefaultErrorCallback(Networking::ErrorResponse error); + +public: ///// DownloadFolderRequest-related ///// /** Starts a folder download. */ -- cgit v1.2.3 From ab0f2d1a03c9ca45dd30440b8a897d9de480bfbe Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 20 Jul 2016 12:45:49 +0600 Subject: CLOUD: Fix OneDriveUploadRequest Segfault when given stream is nullptr. --- backends/cloud/onedrive/onedriveuploadrequest.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 55359f83e7..5b86c6c988 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -50,9 +50,15 @@ OneDriveUploadRequest::~OneDriveUploadRequest() { void OneDriveUploadRequest::start() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); + if (_contentsStream == nullptr) { + warning("OneDriveUploadRequest: cannot restart because no stream given"); + finishError(Networking::ErrorResponse(this, false, true, "No stream given", -1)); + return; + } if (!_contentsStream->seek(0)) { warning("OneDriveUploadRequest: cannot restart because stream couldn't seek(0)"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; } _ignoreCallback = false; -- cgit v1.2.3 From 1d78d20fcf59d772688f9f32d81670548d6569f9 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 20 Jul 2016 12:48:14 +0600 Subject: CLOUD: Fix Dropbox and Google Drive UploadRequests Possible segfault there too. --- backends/cloud/dropbox/dropboxuploadrequest.cpp | 1 + backends/cloud/googledrive/googledriveuploadrequest.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index e530502413..a3d7dd0d6d 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -56,6 +56,7 @@ void DropboxUploadRequest::start() { if (!_contentsStream->seek(0)) { warning("DropboxUploadRequest: cannot restart because stream couldn't seek(0)"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; } _ignoreCallback = false; diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index ce7d59a50c..73a7fbfcac 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -50,9 +50,10 @@ GoogleDriveUploadRequest::~GoogleDriveUploadRequest() { void GoogleDriveUploadRequest::start() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); - if (!_contentsStream->seek(0)) { + if (_contentsStream == nullptr || !_contentsStream->seek(0)) { warning("GoogleDriveUploadRequest: cannot restart because stream couldn't seek(0)"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); + return; } _resolvedId = ""; //used to update file contents _parentId = ""; //used to create file within parent directory -- cgit v1.2.3 From f743b319633dcd57ea08f5ac86d3daec548d1ab0 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 20 Jul 2016 14:44:24 +0600 Subject: CLOUD: Fix CloudManager::connectStorage() memory leak --- backends/cloud/box/boxstorage.cpp | 18 +++++++++++++++--- backends/cloud/box/boxstorage.h | 3 ++- backends/cloud/cloudmanager.cpp | 20 +++++++++++++++++++- backends/cloud/cloudmanager.h | 7 +++++++ backends/cloud/dropbox/dropboxstorage.cpp | 13 +++++++++++-- backends/cloud/dropbox/dropboxstorage.h | 1 + backends/cloud/googledrive/googledrivestorage.cpp | 18 +++++++++++++++--- backends/cloud/googledrive/googledrivestorage.h | 3 ++- backends/cloud/onedrive/onedrivestorage.cpp | 18 +++++++++++++++--- backends/cloud/onedrive/onedrivestorage.h | 3 ++- 10 files changed, 89 insertions(+), 15 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 9e036b1187..8162af299c 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -56,12 +56,16 @@ BoxStorage::BoxStorage(Common::String accessToken, Common::String refreshToken): _token(accessToken), _refreshToken(refreshToken) {} BoxStorage::BoxStorage(Common::String code) { - getAccessToken(new Common::Callback(this, &BoxStorage::codeFlowComplete), code); + getAccessToken( + new Common::Callback(this, &BoxStorage::codeFlowComplete), + new Common::Callback(this, &BoxStorage::codeFlowFailed), + code + ); } BoxStorage::~BoxStorage() {} -void BoxStorage::getAccessToken(BoolCallback callback, Common::String code) { +void BoxStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback, Common::String code) { if (!KEY || !SECRET) loadKeyAndSecret(); bool codeFlow = (code != ""); @@ -72,7 +76,8 @@ void BoxStorage::getAccessToken(BoolCallback callback, Common::String code) { } Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::tokenRefreshed, callback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, getErrorPrintingCallback(), "https://api.box.com/oauth2/token"); + if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.box.com/oauth2/token"); if (codeFlow) { request->addPostField("grant_type=authorization_code"); request->addPostField("code=" + code); @@ -117,6 +122,7 @@ void BoxStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse void BoxStorage::codeFlowComplete(BoolResponse response) { if (!response.value) { warning("BoxStorage: failed to get access token through code flow"); + CloudMan.removeStorage(this); return; } @@ -124,6 +130,12 @@ void BoxStorage::codeFlowComplete(BoolResponse response) { ConfMan.flushToDisk(); } +void BoxStorage::codeFlowFailed(Networking::ErrorResponse error) { + debug("Box's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug("%s", error.response.c_str()); + CloudMan.removeStorage(this); +} + void BoxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 51f2a9591c..826d6bef4e 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -42,6 +42,7 @@ class BoxStorage: public Id::IdStorage { void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); void codeFlowComplete(BoolResponse response); + void codeFlowFailed(Networking::ErrorResponse error); /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); @@ -108,7 +109,7 @@ public: * Use "" in order to refresh token and pass a callback, so you could * continue your work when new token is available. */ - void getAccessToken(BoolCallback callback, Common::String code = ""); + void getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback = nullptr, Common::String code = ""); Common::String accessToken() { return _token; } }; diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index b6a721be90..8b7230fb5c 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -45,6 +45,7 @@ CloudManager::CloudManager() : _currentStorageIndex(0), _activeStorage(nullptr) CloudManager::~CloudManager() { //TODO: do we have to save storages on manager destruction? delete _activeStorage; + freeStorages(); } Common::String CloudManager::getStorageConfigName(uint32 index) const { @@ -124,6 +125,7 @@ void CloudManager::save() { } void CloudManager::replaceStorage(Storage *storage, uint32 index) { + freeStorages(); if (!storage) error("CloudManager::replaceStorage: NULL storage passed"); if (index >= kStorageTotal) error("CloudManager::replaceStorage: invalid index passed"); delete _activeStorage; @@ -138,6 +140,18 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) { } } +void CloudManager::removeStorage(Storage *storage) { + // can't just delete it as it's mostly likely the one who calls the method + // it would be freed on freeStorages() call (on next Storage connect or replace) + _storagesToRemove.push_back(storage); +} + +void CloudManager::freeStorages() { + for (uint32 i = 0; i < _storagesToRemove.size(); ++i) + delete _storagesToRemove[i]; + _storagesToRemove.clear(); +} + Storage *CloudManager::getCurrentStorage() const { return _activeStorage; } @@ -207,6 +221,8 @@ void CloudManager::setStorageLastSync(uint32 index, Common::String date) { } void CloudManager::connectStorage(uint32 index, Common::String code) { + freeStorages(); + Storage *storage = nullptr; switch (index) { case kStorageDropboxId: storage = new Dropbox::DropboxStorage(code); break; @@ -214,7 +230,9 @@ void CloudManager::connectStorage(uint32 index, Common::String code) { case kStorageGoogleDriveId: storage = new GoogleDrive::GoogleDriveStorage(code); break; case kStorageBoxId: storage = new Box::BoxStorage(code); break; } - //these would automatically request replaceStorage() when they receive the token + // in these constructors Storages request token using the passed code + // when the token is received, they call replaceStorage() + // or removeStorage(), if some error occurred } void CloudManager::printBool(Storage::BoolResponse response) const { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 15409ee3a1..4442b9bfbe 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -59,6 +59,7 @@ class CloudManager : public Common::Singleton { Common::Array _storages; uint _currentStorageIndex; Storage *_activeStorage; + Common::Array _storagesToRemove; void printBool(Cloud::Storage::BoolResponse response) const; @@ -66,6 +67,9 @@ class CloudManager : public Common::Singleton { Common::String getStorageConfigName(uint32 index) const; + /** Frees memory used by storages which failed to connect. */ + void freeStorages(); + public: CloudManager(); virtual ~CloudManager(); @@ -91,6 +95,9 @@ public: */ void replaceStorage(Storage *storage, uint32 index); + /** Adds storage in the list of storages to remove later. */ + void removeStorage(Storage *storage); + /** * Returns active Storage, which could be used to interact * with cloud storage. diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index e34912ed66..4171af0443 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -62,8 +62,9 @@ DropboxStorage::~DropboxStorage() {} void DropboxStorage::getAccessToken(Common::String code) { if (!KEY || !SECRET) loadKeyAndSecret(); - Networking::JsonCallback callback = new Common::Callback(this, &DropboxStorage::codeFlowComplete); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, nullptr, "https://api.dropboxapi.com/oauth2/token"); + Networking::JsonCallback callback = new Common::Callback(this, &DropboxStorage::codeFlowComplete); + Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxStorage::codeFlowFailed); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, errorCallback, "https://api.dropboxapi.com/oauth2/token"); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + Common::String(KEY)); @@ -83,6 +84,7 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { if (!result.contains("access_token") || !result.contains("uid")) { warning("%s", json->stringify(true).c_str()); warning("Bad response, no token/uid passed"); + CloudMan.removeStorage(this); } else { _token = result.getVal("access_token")->asString(); _uid = result.getVal("uid")->asString(); @@ -94,9 +96,16 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { delete json; } else { debug("DropboxStorage::codeFlowComplete: got NULL instead of JSON!"); + CloudMan.removeStorage(this); } } +void DropboxStorage::codeFlowFailed(Networking::ErrorResponse error) { + debug("Dropbox's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug("%s", error.response.c_str()); + CloudMan.removeStorage(this); +} + void DropboxStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "user_id", _uid, ConfMan.kCloudDomain); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 2c9cf163ab..9dd28ba810 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -42,6 +42,7 @@ class DropboxStorage: public Cloud::Storage { void getAccessToken(Common::String code); void codeFlowComplete(Networking::JsonResponse response); + void codeFlowFailed(Networking::ErrorResponse error); public: /** This constructor uses OAuth code flow to get tokens. */ diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 2816301cac..c4264099fd 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -56,12 +56,16 @@ GoogleDriveStorage::GoogleDriveStorage(Common::String accessToken, Common::Strin _token(accessToken), _refreshToken(refreshToken) {} GoogleDriveStorage::GoogleDriveStorage(Common::String code) { - getAccessToken(new Common::Callback(this, &GoogleDriveStorage::codeFlowComplete), code); + getAccessToken( + new Common::Callback(this, &GoogleDriveStorage::codeFlowComplete), + new Common::Callback(this, &GoogleDriveStorage::codeFlowFailed), + code + ); } GoogleDriveStorage::~GoogleDriveStorage() {} -void GoogleDriveStorage::getAccessToken(BoolCallback callback, Common::String code) { +void GoogleDriveStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback, Common::String code) { if (!KEY || !SECRET) loadKeyAndSecret(); bool codeFlow = (code != ""); @@ -72,7 +76,8 @@ void GoogleDriveStorage::getAccessToken(BoolCallback callback, Common::String co } Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::tokenRefreshed, callback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, getErrorPrintingCallback(), "https://accounts.google.com/o/oauth2/token"); //TODO + if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://accounts.google.com/o/oauth2/token"); //TODO if (codeFlow) { request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); @@ -118,6 +123,7 @@ void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonR void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { if (!response.value) { warning("GoogleDriveStorage: failed to get access token through code flow"); + CloudMan.removeStorage(this); return; } @@ -126,6 +132,12 @@ void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { ConfMan.flushToDisk(); } +void GoogleDriveStorage::codeFlowFailed(Networking::ErrorResponse error) { + debug("Google Drive's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug("%s", error.response.c_str()); + CloudMan.removeStorage(this); +} + void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 4a7dbab99f..eee4de90b0 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -42,6 +42,7 @@ class GoogleDriveStorage: public Id::IdStorage { void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); void codeFlowComplete(BoolResponse response); + void codeFlowFailed(Networking::ErrorResponse error); /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); @@ -110,7 +111,7 @@ public: * Use "" in order to refresh token and pass a callback, so you could * continue your work when new token is available. */ - void getAccessToken(BoolCallback callback, Common::String code = ""); + void getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback = nullptr, Common::String code = ""); Common::String accessToken() { return _token; } }; diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 3c8ea5fe81..e9165943af 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -57,12 +57,16 @@ OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String user _token(accessToken), _uid(userId), _refreshToken(refreshToken) {} OneDriveStorage::OneDriveStorage(Common::String code) { - getAccessToken(new Common::Callback(this, &OneDriveStorage::codeFlowComplete), code); + getAccessToken( + new Common::Callback(this, &OneDriveStorage::codeFlowComplete), + new Common::Callback(this, &OneDriveStorage::codeFlowFailed), + code + ); } OneDriveStorage::~OneDriveStorage() {} -void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) { +void OneDriveStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback, Common::String code) { if (!KEY || !SECRET) loadKeyAndSecret(); bool codeFlow = (code != ""); @@ -73,7 +77,8 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) } Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, getErrorPrintingCallback(), "https://login.live.com/oauth20_token.srf"); //TODO + if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://login.live.com/oauth20_token.srf"); //TODO if (codeFlow) { request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); @@ -117,6 +122,7 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResp void OneDriveStorage::codeFlowComplete(BoolResponse response) { if (!response.value) { warning("OneDriveStorage: failed to get access token through code flow"); + CloudMan.removeStorage(this); return; } @@ -125,6 +131,12 @@ void OneDriveStorage::codeFlowComplete(BoolResponse response) { ConfMan.flushToDisk(); } +void OneDriveStorage::codeFlowFailed(Networking::ErrorResponse error) { + debug("OneDrive's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug("%s", error.response.c_str()); + CloudMan.removeStorage(this); +} + void OneDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "user_id", _uid, ConfMan.kCloudDomain); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 650c240aef..8ceaaf107e 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -41,6 +41,7 @@ class OneDriveStorage: public Cloud::Storage { void tokenRefreshed(BoolCallback callback, Networking::JsonResponse response); void codeFlowComplete(BoolResponse response); + void codeFlowFailed(Networking::ErrorResponse error); /** Constructs StorageInfo based on JSON response from cloud. */ void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); @@ -101,7 +102,7 @@ public: * Use "" in order to refresh token and pass a callback, so you could * continue your work when new token is available. */ - void getAccessToken(BoolCallback callback, Common::String code = ""); + void getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback = nullptr, Common::String code = ""); Common::String accessToken() { return _token; } }; -- cgit v1.2.3 From b1264df120b6594a79d99cbb1cc5ef944fa2e448 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 20 Jul 2016 15:00:44 +0600 Subject: CLOUD: Check whether Storage is working when replacing it We do that in CloudManager::replaceStorage(), but I've tried to eliminate such possibility by adding a check in the StorageWizardDialog. --- backends/cloud/cloudmanager.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 8b7230fb5c..ed48ec5079 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -128,7 +128,14 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) { freeStorages(); if (!storage) error("CloudManager::replaceStorage: NULL storage passed"); if (index >= kStorageTotal) error("CloudManager::replaceStorage: invalid index passed"); - delete _activeStorage; + if (_activeStorage != nullptr && _activeStorage->isWorking()) { + warning("CloudManager::replaceStorage: replacing Storage while the other is working"); + if (_activeStorage->isDownloading()) _activeStorage->cancelDownload(); + if (_activeStorage->isSyncing()) _activeStorage->cancelSync(); + removeStorage(_activeStorage); + } else { + delete _activeStorage; + } _activeStorage = storage; _currentStorageIndex = index; save(); -- cgit v1.2.3 From a449ddce15c512e809b9aedad334db6b52628e61 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 20 Jul 2016 17:30:19 +0600 Subject: CLOUD: Fix Cppcheck warnings --- backends/cloud/cloudmanager.cpp | 1 + backends/cloud/dropbox/dropboxstorage.cpp | 2 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 4 ++-- backends/cloud/googledrive/googledriveuploadrequest.cpp | 2 +- backends/cloud/onedrive/onedriveuploadrequest.cpp | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index ed48ec5079..3e1c94f909 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -240,6 +240,7 @@ void CloudManager::connectStorage(uint32 index, Common::String code) { // in these constructors Storages request token using the passed code // when the token is received, they call replaceStorage() // or removeStorage(), if some error occurred + // thus, no memory leak happens } void CloudManager::printBool(Storage::BoolResponse response) const { diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 4171af0443..d7aea012af 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -135,7 +135,7 @@ Networking::Request *DropboxStorage::streamFileById(Common::String path, Network Networking::NetworkReadStreamResponse response = request->execute(); if (callback) (*callback)(response); - return response.request; + return response.request; // no leak here, response.request == request } Networking::Request *DropboxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index a3d7dd0d6d..ee6f665665 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -137,10 +137,10 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons //debug("%s", json->stringify(true).c_str()); if (object.contains("error") || object.contains("error_summary")) { - warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); - delete json; + warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); error.response = json->stringify(true); finishError(error); + delete json; return; } diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index 73a7fbfcac..dfff46c0d2 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -266,9 +266,9 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res if (object.contains("error")) { warning("GoogleDrive returned error: %s", json->stringify(true).c_str()); - delete json; error.response = json->stringify(true); finishError(error); + delete json; return; } diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 5b86c6c988..500f875b9d 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -127,9 +127,9 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon if (object.contains("error")) { warning("OneDrive returned error: %s", json->stringify(true).c_str()); - delete json; error.response = json->stringify(true); finishError(error); + delete json; return; } -- cgit v1.2.3 From b180c73675846f45abab2190b39e0b9d0d6addbf Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Wed, 20 Jul 2016 18:47:34 +0600 Subject: CLOUD: Do some refactoring/cleanup Nothing really major. --- backends/cloud/box/boxstorage.cpp | 4 +- backends/cloud/box/boxstorage.h | 2 +- backends/cloud/box/boxtokenrefresher.cpp | 6 +-- backends/cloud/box/boxuploadrequest.cpp | 1 - backends/cloud/cloudmanager.cpp | 44 +++++++++------------- backends/cloud/cloudmanager.h | 41 +++++++++----------- backends/cloud/downloadrequest.cpp | 1 - backends/cloud/dropbox/dropboxstorage.cpp | 4 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 2 +- backends/cloud/folderdownloadrequest.cpp | 2 +- backends/cloud/folderdownloadrequest.h | 5 +-- backends/cloud/googledrive/googledrivestorage.cpp | 12 +++--- backends/cloud/googledrive/googledrivestorage.h | 6 +-- .../googledrive/googledrivetokenrefresher.cpp | 6 +-- .../cloud/googledrive/googledriveuploadrequest.cpp | 2 - backends/cloud/id/idstorage.cpp | 22 +++++------ backends/cloud/onedrive/onedrivestorage.cpp | 12 +++--- backends/cloud/onedrive/onedrivestorage.h | 2 +- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 6 +-- backends/cloud/onedrive/onedriveuploadrequest.cpp | 3 +- backends/cloud/savessyncrequest.cpp | 32 ++++++---------- backends/cloud/savessyncrequest.h | 4 +- backends/cloud/storage.cpp | 4 +- backends/cloud/storage.h | 10 +++-- 24 files changed, 101 insertions(+), 132 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 8162af299c..c31c72b49f 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -278,12 +278,12 @@ BoxStorage *BoxStorage::loadFromConfig(Common::String keyPrefix) { if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { warning("No access_token found"); - return 0; + return nullptr; } if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { warning("No refresh_token found"); - return 0; + return nullptr; } Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 826d6bef4e..1373c2fbeb 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -111,7 +111,7 @@ public: */ void getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback = nullptr, Common::String code = ""); - Common::String accessToken() { return _token; } + Common::String accessToken() const { return _token; } }; } // End of namespace Box diff --git a/backends/cloud/box/boxtokenrefresher.cpp b/backends/cloud/box/boxtokenrefresher.cpp index 9dfbef537f..f100e186be 100644 --- a/backends/cloud/box/boxtokenrefresher.cpp +++ b/backends/cloud/box/boxtokenrefresher.cpp @@ -69,7 +69,7 @@ void BoxTokenRefresher::finishJson(Common::JSONValue *json) { long httpCode = -1; if (_stream) { httpCode = _stream->httpResponseCode(); - debug("code %ld", httpCode); + debug(9, "code %ld", httpCode); } bool irrecoverable = true; @@ -77,12 +77,12 @@ void BoxTokenRefresher::finishJson(Common::JSONValue *json) { Common::String code, message; if (result.contains("code")) { code = result.getVal("code")->asString(); - debug("code = %s", code.c_str()); + debug(9, "code = %s", code.c_str()); } if (result.contains("message")) { message = result.getVal("message")->asString(); - debug("message = %s", message.c_str()); + debug(9, "message = %s", message.c_str()); } //TODO: decide when token refreshment will help diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index c94494efac..c81a3ab439 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -29,7 +29,6 @@ #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" #include "common/json.h" -#include "common/debug.h" namespace Cloud { namespace Box { diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 3e1c94f909..55dbb2b42d 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -25,7 +25,6 @@ #include "backends/cloud/dropbox/dropboxstorage.h" #include "backends/cloud/onedrive/onedrivestorage.h" #include "backends/cloud/googledrive/googledrivestorage.h" -#include "common/debug.h" #include "common/translation.h" #include "common/config-manager.h" #include "common/str.h" @@ -243,10 +242,6 @@ void CloudManager::connectStorage(uint32 index, Common::String code) { // thus, no memory leak happens } -void CloudManager::printBool(Storage::BoolResponse response) const { - debug("bool = %s", (response.value ? "true" : "false")); -} - Networking::Request *CloudManager::listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { Storage *storage = getCurrentStorage(); if (storage) return storage->listDirectory(path, callback, errorCallback, recursive); @@ -295,12 +290,7 @@ SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networ return nullptr; } -void CloudManager::testFeature() { - //Storage *storage = getCurrentStorage(); - //if (storage) storage->info(nullptr, nullptr); -} - -bool CloudManager::isWorking() { +bool CloudManager::isWorking() const { Storage *storage = getCurrentStorage(); if (storage) return storage->isWorking(); return false; @@ -308,95 +298,95 @@ bool CloudManager::isWorking() { ///// SavesSyncRequest-related ///// -bool CloudManager::isSyncing() { +bool CloudManager::isSyncing() const { Storage *storage = getCurrentStorage(); if (storage) return storage->isSyncing(); return false; } -double CloudManager::getSyncDownloadingProgress() { +double CloudManager::getSyncDownloadingProgress() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getSyncDownloadingProgress(); return 1; } -double CloudManager::getSyncProgress() { +double CloudManager::getSyncProgress() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getSyncProgress(); return 1; } -Common::Array CloudManager::getSyncingFiles() { +Common::Array CloudManager::getSyncingFiles() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getSyncingFiles(); return Common::Array(); } -void CloudManager::cancelSync() { +void CloudManager::cancelSync() const { Storage *storage = getCurrentStorage(); if (storage) storage->cancelSync(); } -void CloudManager::setSyncTarget(GUI::CommandReceiver *target) { +void CloudManager::setSyncTarget(GUI::CommandReceiver *target) const { Storage *storage = getCurrentStorage(); if (storage) storage->setSyncTarget(target); } ///// DownloadFolderRequest-related ///// -bool CloudManager::startDownload(Common::String remotePath, Common::String localPath) { +bool CloudManager::startDownload(Common::String remotePath, Common::String localPath) const { Storage *storage = getCurrentStorage(); if (storage) return storage->startDownload(remotePath, localPath); return false; } -void CloudManager::cancelDownload() { +void CloudManager::cancelDownload() const { Storage *storage = getCurrentStorage(); if (storage) storage->cancelDownload(); } -void CloudManager::setDownloadTarget(GUI::CommandReceiver *target) { +void CloudManager::setDownloadTarget(GUI::CommandReceiver *target) const { Storage *storage = getCurrentStorage(); if (storage) storage->setDownloadTarget(target); } -bool CloudManager::isDownloading() { +bool CloudManager::isDownloading() const { Storage *storage = getCurrentStorage(); if (storage) return storage->isDownloading(); return false; } -double CloudManager::getDownloadingProgress() { +double CloudManager::getDownloadingProgress() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadingProgress(); return 1; } -uint64 CloudManager::getDownloadBytesNumber() { +uint64 CloudManager::getDownloadBytesNumber() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadBytesNumber(); return 0; } -uint64 CloudManager::getDownloadTotalBytesNumber() { +uint64 CloudManager::getDownloadTotalBytesNumber() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadTotalBytesNumber(); return 0; } -uint64 CloudManager::getDownloadSpeed() { +uint64 CloudManager::getDownloadSpeed() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadSpeed(); return 0; } -Common::String CloudManager::getDownloadRemoteDirectory() { +Common::String CloudManager::getDownloadRemoteDirectory() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadRemoteDirectory(); return ""; } -Common::String CloudManager::getDownloadLocalDirectory() { +Common::String CloudManager::getDownloadLocalDirectory() const { Storage *storage = getCurrentStorage(); if (storage) return storage->getDownloadLocalDirectory(); return ""; diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 4442b9bfbe..2941ea6331 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -61,8 +61,6 @@ class CloudManager : public Common::Singleton { Storage *_activeStorage; Common::Array _storagesToRemove; - void printBool(Cloud::Storage::BoolResponse response) const; - void loadStorage(); Common::String getStorageConfigName(uint32 index) const; @@ -206,65 +204,60 @@ public: */ SavesSyncRequest *syncSaves(Cloud::Storage::BoolCallback callback = nullptr, Networking::ErrorCallback errorCallback = nullptr); - /** - * Starts feature testing (the one I'm working on currently). (Temporary) - */ - void testFeature(); - /** Returns whether there are any requests running. */ - bool isWorking(); + bool isWorking() const; ///// SavesSyncRequest-related ///// /** Returns whether there is a SavesSyncRequest running. */ - bool isSyncing(); + bool isSyncing() const; /** Returns a number in [0, 1] range which represents current sync downloading progress (1 = complete). */ - double getSyncDownloadingProgress(); + double getSyncDownloadingProgress() const; /** Returns a number in [0, 1] range which represents current sync progress (1 = complete). */ - double getSyncProgress(); + double getSyncProgress() const; /** Returns an array of saves names which are not yet synced (thus cannot be used). */ - Common::Array getSyncingFiles(); + Common::Array getSyncingFiles() const; /** Cancels running sync. */ - void cancelSync(); + void cancelSync() const; /** Sets SavesSyncRequest's target to given CommandReceiver. */ - void setSyncTarget(GUI::CommandReceiver *target); + void setSyncTarget(GUI::CommandReceiver *target) const; ///// DownloadFolderRequest-related ///// /** Starts a folder download. */ - bool startDownload(Common::String remotePath, Common::String localPath); + bool startDownload(Common::String remotePath, Common::String localPath) const; /** Cancels running download. */ - void cancelDownload(); + void cancelDownload() const; /** Sets FolderDownloadRequest's target to given CommandReceiver. */ - void setDownloadTarget(GUI::CommandReceiver *target); + void setDownloadTarget(GUI::CommandReceiver *target) const; /** Returns whether there is a FolderDownloadRequest running. */ - bool isDownloading(); + bool isDownloading() const; /** Returns a number in [0, 1] range which represents current download progress (1 = complete). */ - double getDownloadingProgress(); + double getDownloadingProgress() const; /** Returns a number of bytes that is downloaded in current download progress. */ - uint64 getDownloadBytesNumber(); + uint64 getDownloadBytesNumber() const; /** Returns a total number of bytes to be downloaded in current download progress. */ - uint64 getDownloadTotalBytesNumber(); + uint64 getDownloadTotalBytesNumber() const; /** Returns download speed of current download progress. */ - uint64 getDownloadSpeed(); + uint64 getDownloadSpeed() const; /** Returns remote directory path. */ - virtual Common::String getDownloadRemoteDirectory(); + Common::String getDownloadRemoteDirectory() const; /** Returns local directory path. */ - virtual Common::String getDownloadLocalDirectory(); + Common::String getDownloadLocalDirectory() const; }; /** Shortcut for accessing the connection manager. */ diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 5efb87e0c8..e8c410ae3e 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -22,7 +22,6 @@ #include "backends/cloud/downloadrequest.h" #include "backends/networking/curl/connectionmanager.h" -#include "common/debug.h" #include "common/textconsole.h" namespace Cloud { diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index d7aea012af..7e3521f40e 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -155,12 +155,12 @@ DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { warning("No access_token found"); - return 0; + return nullptr; } if (!ConfMan.hasKey(keyPrefix + "user_id", ConfMan.kCloudDomain)) { warning("No user_id found"); - return 0; + return nullptr; } Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index ee6f665665..29b7f60c8a 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -118,7 +118,7 @@ void DropboxUploadRequest::uploadNextPart() { } void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse response) { - debug("partUploadedCallback"); + debug(9, "partUploadedCallback"); _workingRequest = nullptr; if (_ignoreCallback) return; diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index d506d80c48..9e05202bf7 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -132,7 +132,7 @@ void FolderDownloadRequest::downloadNextFile() { else localPath = _localDirectoryPath + "/" + localPath; } - debug("%s -> %s", remotePath.c_str(), localPath.c_str()); + debug(9, "%s -> %s", remotePath.c_str(), localPath.c_str()); _workingRequest = _storage->downloadById( _currentFile.id(), localPath, new Common::Callback(this, &FolderDownloadRequest::fileDownloadedCallback), diff --git a/backends/cloud/folderdownloadrequest.h b/backends/cloud/folderdownloadrequest.h index 9d8dea4d20..08fa193e07 100644 --- a/backends/cloud/folderdownloadrequest.h +++ b/backends/cloud/folderdownloadrequest.h @@ -24,7 +24,6 @@ #define BACKENDS_CLOUD_FOLDERDOWNLOADREQUEST_H #include "backends/networking/curl/request.h" -#include "backends/networking/curl/networkreadstream.h" #include "backends/cloud/storage.h" #include "gui/object.h" @@ -69,10 +68,10 @@ public: uint64 getDownloadSpeed() const; /** Returns remote directory path. */ - Common::String getRemotePath() { return _remoteDirectoryPath; } + Common::String getRemotePath() const { return _remoteDirectoryPath; } /** Returns local directory path. */ - Common::String getLocalPath() { return _localDirectoryPath; } + Common::String getLocalPath() const { return _localDirectoryPath; } }; } // End of namespace Cloud diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index c4264099fd..77ac8989f1 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -229,10 +229,10 @@ Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Netwo } void GoogleDriveStorage::printInfo(StorageInfoResponse response) { - debug("\nuser info:"); - debug("\tname: %s", response.value.name().c_str()); - debug("\temail: %s", response.value.email().c_str()); - debug("\tdisk usage: %llu/%llu", response.value.used(), response.value.available()); + debug(9, "\nuser info:"); + debug(9, "\tname: %s", response.value.name().c_str()); + debug(9, "\temail: %s", response.value.email().c_str()); + debug(9, "\tdisk usage: %llu/%llu", response.value.used(), response.value.available()); } Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { @@ -273,12 +273,12 @@ GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { warning("No access_token found"); - return 0; + return nullptr; } if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { warning("No refresh_token found"); - return 0; + return nullptr; } Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index eee4de90b0..4c164dd91d 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -24,7 +24,6 @@ #define BACKENDS_CLOUD_GOOGLEDRIVE_GOOGLEDRIVESTORAGE_H #include "backends/cloud/id/idstorage.h" -#include "common/callback.h" #include "backends/networking/curl/curljsonrequest.h" namespace Cloud { @@ -86,9 +85,6 @@ public: /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Calls the callback when finished. */ virtual Networking::Request *createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback); @@ -113,7 +109,7 @@ public: */ void getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback = nullptr, Common::String code = ""); - Common::String accessToken() { return _token; } + Common::String accessToken() const { return _token; } }; } // End of namespace GoogleDrive diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp index 3dfb8436e9..9e26e62149 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.cpp +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -67,7 +67,7 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (result.contains("error")) { //new token needed => request token & then retry original request if (_stream) { - debug("code %ld", _stream->httpResponseCode()); + debug(9, "code %ld", _stream->httpResponseCode()); } Common::JSONObject error = result.getVal("error")->asObject(); @@ -77,12 +77,12 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::String message; if (error.contains("code") && error.getVal("code")->isIntegerNumber()) { code = error.getVal("code")->asIntegerNumber(); - debug("code = %u", code); + debug(9, "code = %u", code); } if (error.contains("message")) { message = error.getVal("message")->asString(); - debug("message = %s", message.c_str()); + debug(9, "message = %s", message.c_str()); } if (code == 401 || message == "Invalid Credentials") diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index dfff46c0d2..b63e989df8 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -28,7 +28,6 @@ #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" #include "common/json.h" -#include "common/debug.h" #include "googledrivetokenrefresher.h" namespace Cloud { @@ -201,7 +200,6 @@ void GoogleDriveUploadRequest::uploadNextPart() { uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST); if (size != 0) request->setBuffer(buffer, size); - //request->addHeader(Common::String::format("Content-Length: %u", size)); if (_uploadUrl != "") { if (_contentsStream->pos() == 0) request->addHeader(Common::String::format("Content-Length: 0")); diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index 28f880522e..5b0f9db347 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -36,26 +36,26 @@ namespace Id { IdStorage::~IdStorage() {} void IdStorage::printFiles(FileArrayResponse response) { - debug("files:"); + debug(9, "files:"); Common::Array &files = response.value; for (uint32 i = 0; i < files.size(); ++i) { - debug("\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); - debug("\t%s", files[i].path().c_str()); - debug("\t%s", files[i].id().c_str()); - debug(" "); + debug(9, "\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); + debug(9, "\t%s", files[i].path().c_str()); + debug(9, "\t%s", files[i].id().c_str()); + debug(9, " "); } } void IdStorage::printBool(BoolResponse response) { - debug("bool: %s", response.value ? "true" : "false"); + debug(9, "bool: %s", response.value ? "true" : "false"); } void IdStorage::printFile(UploadResponse response) { - debug("\nuploaded file info:"); - debug("\tid: %s", response.value.path().c_str()); - debug("\tname: %s", response.value.name().c_str()); - debug("\tsize: %u", response.value.size()); - debug("\ttimestamp: %u", response.value.timestamp()); + debug(9, "\nuploaded file info:"); + debug(9, "\tid: %s", response.value.path().c_str()); + debug(9, "\tname: %s", response.value.name().c_str()); + debug(9, "\tsize: %u", response.value.size()); + debug(9, "\ttimestamp: %u", response.value.timestamp()); } Storage::ListDirectoryCallback IdStorage::getPrintFilesCallback() { diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index e9165943af..39213e82ed 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -189,7 +189,7 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { if (!response.value) { warning("fileInfoCallback: NULL"); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); return; } @@ -199,12 +199,12 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse( response.request, - new Networking::NetworkReadStream(url, 0, "") + new Networking::NetworkReadStream(url, nullptr, "") )); } else { warning("downloadUrl not found in passed JSON"); debug("%s", response.value->stringify().c_str()); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, 0)); + if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); } delete response.value; } @@ -244,17 +244,17 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { warning("No access_token found"); - return 0; + return nullptr; } if (!ConfMan.hasKey(keyPrefix + "user_id", ConfMan.kCloudDomain)) { warning("No user_id found"); - return 0; + return nullptr; } if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { warning("No refresh_token found"); - return 0; + return nullptr; } Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain); diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 8ceaaf107e..60817e6084 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -104,7 +104,7 @@ public: */ void getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback = nullptr, Common::String code = ""); - Common::String accessToken() { return _token; } + Common::String accessToken() const { return _token; } }; } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 04e155c084..9afea3d5bd 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -67,7 +67,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (result.contains("error")) { //new token needed => request token & then retry original request if (_stream) { - debug("code %ld", _stream->httpResponseCode()); + debug(9, "code %ld", _stream->httpResponseCode()); } Common::JSONObject error = result.getVal("error")->asObject(); @@ -76,12 +76,12 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::String code, message; if (error.contains("code")) { code = error.getVal("code")->asString(); - debug("code = %s", code.c_str()); + debug(9, "code = %s", code.c_str()); } if (error.contains("message")) { message = error.getVal("message")->asString(); - debug("message = %s", message.c_str()); + debug(9, "message = %s", message.c_str()); } //determine whether token refreshing would help in this situation diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 500f875b9d..569809d16b 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -28,7 +28,6 @@ #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 { @@ -135,7 +134,7 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon if (object.contains("id") && object.contains("name")) { //finished - Common::String path = _savePath; //object.getVal("name")->asString();; //object.getVal("id")->asString(); + Common::String path = _savePath; uint32 size = object.getVal("size")->asIntegerNumber(); uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("lastModifiedDateTime")->asString()); finishUpload(StorageFile(path, size, timestamp, false)); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 32b22edcaa..014e6a0ae6 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -117,17 +117,15 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re if (i->_value) _filesToUpload.push_back(i->_key); } - /////// - debug("\ndownload files:"); + debug(9, "\ndownload files:"); for (uint32 i = 0; i < _filesToDownload.size(); ++i) { - debug("%s", _filesToDownload[i].name().c_str()); + debug(9, "%s", _filesToDownload[i].name().c_str()); } - debug("\nupload files:"); + debug(9, "\nupload files:"); for (uint32 i = 0; i < _filesToUpload.size(); ++i) { - debug("%s", _filesToUpload[i].c_str()); + debug(9, "%s", _filesToUpload[i].c_str()); } _totalFilesToHandle = _filesToDownload.size() + _filesToUpload.size(); - /////// //start downloading files downloadNextFile(); @@ -162,13 +160,11 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er } } } - - //TODO: Google Drive-related JSON error } delete value; } - //Google Drive-related ScummVM-based error + //Google Drive and Box-related ScummVM-based error if (error.response.contains("subdirectory not found")) { irrecoverable = false; //base "/ScummVM/" folder not found } else if (error.response.contains("no such file found in its parent directory")) { @@ -184,7 +180,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er //we're lucky - user just lacks his "/cloud/" folder - let's create one Common::String dir = _storage->savesDirectoryPath(); if (dir.lastChar() == '/') dir.deleteLastChar(); - debug("creating %s", dir.c_str()); + debug(9, "creating %s", dir.c_str()); _workingRequest = _storage->createDirectory(dir, new Common::Callback(this, &SavesSyncRequest::directoryCreatedCallback), new Common::Callback(this, &SavesSyncRequest::directoryCreatedErrorCallback) @@ -227,10 +223,8 @@ void SavesSyncRequest::downloadNextFile() { _filesToDownload.pop_back(); sendCommand(GUI::kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); - - /////// - debug("downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); - /////// + + debug(9, "downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); _workingRequest = _storage->downloadById(_currentDownloadingFile.id(), DefaultSaveFileManager::concatWithSavesPath(_currentDownloadingFile.name()), new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), new Common::Callback(this, &SavesSyncRequest::fileDownloadedErrorCallback) @@ -275,10 +269,8 @@ void SavesSyncRequest::uploadNextFile() { _currentUploadingFile = _filesToUpload.back(); _filesToUpload.pop_back(); - - /////// - debug("uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress()*100)); - /////// + + debug(9, "uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress()*100)); if (_storage->uploadStreamSupported()) { _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), @@ -318,7 +310,7 @@ void SavesSyncRequest::handle() {} void SavesSyncRequest::restart() { start(); } -double SavesSyncRequest::getDownloadingProgress() { +double SavesSyncRequest::getDownloadingProgress() const { if (_totalFilesToHandle == 0) { if (_state == Networking::FINISHED) return 1; //nothing to upload and download => Request ends soon return 0; //directory not listed yet @@ -331,7 +323,7 @@ double SavesSyncRequest::getDownloadingProgress() { return (double)(totalFilesToDownload - filesLeftToDownload) / (double)(totalFilesToDownload); } -double SavesSyncRequest::getProgress() { +double SavesSyncRequest::getProgress() const { if (_totalFilesToHandle == 0) { if (_state == Networking::FINISHED) return 1; //nothing to upload and download => Request ends soon return 0; //directory not listed yet diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index d1a9d4a44c..304c44407c 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -66,10 +66,10 @@ public: virtual void restart(); /** Returns a number in range [0, 1], where 1 is "complete". */ - double getDownloadingProgress(); + double getDownloadingProgress() const; /** Returns a number in range [0, 1], where 1 is "complete". */ - double getProgress(); + double getProgress() const; /** Returns an array of saves names which are not downloaded yet. */ Common::Array getFilesToDownload(); diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index d4548b84cb..100d72b5be 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -49,7 +49,7 @@ void Storage::printErrorResponse(Networking::ErrorResponse error) { Networking::Request *Storage::addRequest(Networking::Request *request) { _runningRequestsMutex.lock(); ++_runningRequestsCount; - if (_runningRequestsCount == 1) debug("Storage is working now"); + if (_runningRequestsCount == 1) debug(9, "Storage is working now"); _runningRequestsMutex.unlock(); return ConnMan.addRequest(request, new Common::Callback(this, &Storage::requestFinishedCallback)); } @@ -62,7 +62,7 @@ void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer _savesSyncRequest = nullptr; --_runningRequestsCount; if (_syncRestartRequestsed) restartSync = true; - if (_runningRequestsCount == 0 && !restartSync) debug("Storage is not working now"); + if (_runningRequestsCount == 0 && !restartSync) debug(9, "Storage is not working now"); _runningRequestsMutex.unlock(); if (restartSync) diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index b33d69e411..eaa6e9cea0 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -62,8 +62,12 @@ protected: /** Keeps track of running requests. */ uint32 _runningRequestsCount; Common::Mutex _runningRequestsMutex; + + /** SavesSyncRequest-related */ SavesSyncRequest *_savesSyncRequest; bool _syncRestartRequestsed; + + /** FolderDownloadRequest-related */ FolderDownloadRequest *_downloadFolderRequest; /** Returns default error callback (printErrorResponse). */ @@ -122,7 +126,7 @@ public: /** Returns ListDirectoryResponse with list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false) = 0; - /** Returns UploadStatus struct with info about uploaded file. */ + /** Returns StorageFile 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 remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback); @@ -147,8 +151,8 @@ public: virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) = 0; /** - * Return the StorageInfo struct via . - * Call the if failed to get information. + * Returns the StorageInfo struct via . + * Calls the if failed to get information. * * @note on success Storage should also call * CloudMan.setStorageUsername(). -- 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/box/boxlistdirectorybyidrequest.cpp | 6 ++--- backends/cloud/box/boxlistdirectorybyidrequest.h | 4 ++-- backends/cloud/box/boxstorage.cpp | 6 ++--- backends/cloud/box/boxstorage.h | 4 ++-- backends/cloud/box/boxtokenrefresher.cpp | 10 ++++---- backends/cloud/box/boxtokenrefresher.h | 6 ++--- backends/cloud/box/boxuploadrequest.cpp | 8 +++---- backends/cloud/box/boxuploadrequest.h | 2 +- backends/cloud/cloudmanager.cpp | 2 +- backends/cloud/cloudmanager.h | 4 ++-- backends/cloud/downloadrequest.cpp | 6 ++--- backends/cloud/downloadrequest.h | 4 ++-- .../dropbox/dropboxcreatedirectoryrequest.cpp | 6 ++--- .../cloud/dropbox/dropboxcreatedirectoryrequest.h | 2 +- backends/cloud/dropbox/dropboxinforequest.cpp | 4 ++-- backends/cloud/dropbox/dropboxinforequest.h | 2 +- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 12 +++++----- .../cloud/dropbox/dropboxlistdirectoryrequest.h | 2 +- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- backends/cloud/dropbox/dropboxstorage.h | 6 ++--- backends/cloud/dropbox/dropboxuploadrequest.cpp | 24 +++++++++---------- backends/cloud/dropbox/dropboxuploadrequest.h | 2 +- backends/cloud/folderdownloadrequest.cpp | 6 ++--- .../googledrivelistdirectorybyidrequest.cpp | 10 ++++---- .../googledrivelistdirectorybyidrequest.h | 4 ++-- backends/cloud/googledrive/googledrivestorage.cpp | 18 +++++++------- backends/cloud/googledrive/googledrivestorage.h | 2 +- .../googledrive/googledrivetokenrefresher.cpp | 12 +++++----- .../cloud/googledrive/googledrivetokenrefresher.h | 6 ++--- .../cloud/googledrive/googledriveuploadrequest.cpp | 28 +++++++++++----------- .../cloud/googledrive/googledriveuploadrequest.h | 2 +- backends/cloud/id/idcreatedirectoryrequest.cpp | 6 ++--- backends/cloud/id/iddownloadrequest.cpp | 2 +- backends/cloud/id/idlistdirectoryrequest.cpp | 2 +- backends/cloud/id/idresolveidrequest.cpp | 6 ++--- backends/cloud/id/idresolveidrequest.h | 2 +- backends/cloud/id/idstorage.h | 2 +- backends/cloud/id/idstreamfilerequest.cpp | 2 +- backends/cloud/iso8601.cpp | 6 ++--- .../onedrive/onedrivecreatedirectoryrequest.cpp | 12 +++++----- .../onedrive/onedrivecreatedirectoryrequest.h | 2 +- .../onedrive/onedrivelistdirectoryrequest.cpp | 12 +++++----- backends/cloud/onedrive/onedrivestorage.cpp | 2 +- backends/cloud/onedrive/onedrivestorage.h | 4 ++-- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 12 +++++----- backends/cloud/onedrive/onedrivetokenrefresher.h | 6 ++--- backends/cloud/onedrive/onedriveuploadrequest.cpp | 26 ++++++++++---------- backends/cloud/onedrive/onedriveuploadrequest.h | 2 +- backends/cloud/savessyncrequest.cpp | 20 ++++++++-------- backends/cloud/savessyncrequest.h | 2 +- backends/cloud/storage.cpp | 2 +- backends/cloud/storage.h | 4 ++-- backends/cloud/storageinfo.h | 2 +- 53 files changed, 174 insertions(+), 174 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp index d4606b1851..537666bc52 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.cpp +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -87,7 +87,7 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp Common::JSONObject responseObject = json->asObject(); //debug("%s", json->stringify(true).c_str()); - + //TODO: check that error is returned the right way /* if (responseObject.contains("error") || responseObject.contains("error_summary")) { @@ -100,7 +100,7 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp } */ - //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 (responseObject.contains("entries") && responseObject.getVal("entries")->isArray()) { Common::JSONArray items = responseObject.getVal("entries")->asArray(); @@ -160,7 +160,7 @@ void BoxListDirectoryByIdRequest::restart() { start(); } Common::String BoxListDirectoryByIdRequest::date() const { return _date; } -void BoxListDirectoryByIdRequest::finishListing(Common::Array &files) { +void BoxListDirectoryByIdRequest::finishListing(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.h b/backends/cloud/box/boxlistdirectorybyidrequest.h index ccf8d2e342..13f1ba056c 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.h +++ b/backends/cloud/box/boxlistdirectorybyidrequest.h @@ -34,7 +34,7 @@ namespace Box { class BoxStorage; class BoxListDirectoryByIdRequest: public Networking::Request { - Common::String _requestedId; + Common::String _requestedId; BoxStorage *_storage; Storage::ListDirectoryCallback _listDirectoryCallback; @@ -42,7 +42,7 @@ class BoxListDirectoryByIdRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _date; - + void start(); void makeRequest(uint32 offset); void responseCallback(Networking::JsonResponse response); diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index c31c72b49f..6d4b5efd8e 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -152,7 +152,7 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking delete outerCallback; return; } - + Common::JSONObject info = json->asObject(); Common::String uid, name, email; @@ -224,7 +224,7 @@ Networking::Request *BoxStorage::createDirectoryWithParentId(Common::String pare Common::JSONObject parentObject; parentObject.setVal("id", new Common::JSONValue(parentId)); - Common::JSONObject jsonRequestParameters; + Common::JSONObject jsonRequestParameters; jsonRequestParameters.setVal("name", new Common::JSONValue(name)); jsonRequestParameters.setVal("parent", new Common::JSONValue(parentObject)); @@ -248,7 +248,7 @@ Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableRea } bool BoxStorage::uploadStreamSupported() { - return false; + return false; } Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 1373c2fbeb..89bc470a26 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -48,7 +48,7 @@ class BoxStorage: public Id::IdStorage { void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); void createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response); -public: +public: /** This constructor uses OAuth code flow to get tokens. */ BoxStorage(Common::String code); virtual ~BoxStorage(); @@ -97,7 +97,7 @@ public: virtual Common::String savesDirectoryPath(); /** - * Load token and user id from configs and return BoxStorage for those. + * Load token and user id from configs and return BoxStorage for those. * @return pointer to the newly created BoxStorage or 0 if some problem occured. */ static BoxStorage *loadFromConfig(Common::String keyPrefix); diff --git a/backends/cloud/box/boxtokenrefresher.cpp b/backends/cloud/box/boxtokenrefresher.cpp index f100e186be..65964f3010 100644 --- a/backends/cloud/box/boxtokenrefresher.cpp +++ b/backends/cloud/box/boxtokenrefresher.cpp @@ -52,7 +52,7 @@ void BoxTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { } setHeaders(_headers); - //successfully received refreshed token, can restart the original request now + //successfully received refreshed token, can restart the original request now retry(0); } @@ -77,7 +77,7 @@ void BoxTokenRefresher::finishJson(Common::JSONValue *json) { Common::String code, message; if (result.contains("code")) { code = result.getVal("code")->asString(); - debug(9, "code = %s", code.c_str()); + debug(9, "code = %s", code.c_str()); } if (result.contains("message")) { @@ -88,13 +88,13 @@ void BoxTokenRefresher::finishJson(Common::JSONValue *json) { //TODO: decide when token refreshment will help //if (code == "unauthenticated") irrecoverable = false; - if (irrecoverable) { + if (irrecoverable) { finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpCode)); delete json; return; } - pause(); + pause(); delete json; _parentStorage->getAccessToken(new Common::Callback(this, &BoxTokenRefresher::tokenRefreshed)); return; @@ -117,7 +117,7 @@ void BoxTokenRefresher::finishError(Networking::ErrorResponse error) { Request::finishError(error); } -void BoxTokenRefresher::setHeaders(Common::Array &headers) { +void BoxTokenRefresher::setHeaders(Common::Array &headers) { _headers = headers; curl_slist_free_all(_headersList); _headersList = 0; diff --git a/backends/cloud/box/boxtokenrefresher.h b/backends/cloud/box/boxtokenrefresher.h index 7dedefdbe5..c08e8468c3 100644 --- a/backends/cloud/box/boxtokenrefresher.h +++ b/backends/cloud/box/boxtokenrefresher.h @@ -33,13 +33,13 @@ class BoxStorage; class BoxTokenRefresher: public Networking::CurlJsonRequest { BoxStorage *_parentStorage; - Common::Array _headers; - + Common::Array _headers; + void tokenRefreshed(Storage::BoolResponse response); virtual void finishJson(Common::JSONValue *json); virtual void finishError(Networking::ErrorResponse error); -public: +public: BoxTokenRefresher(BoxStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); virtual ~BoxTokenRefresher(); diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index c81a3ab439..d1f68f1d24 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -123,12 +123,12 @@ void BoxUploadRequest::upload() { _workingRequest = ConnMan.addRequest(request); } -void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { +void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - + Networking::ErrorResponse error(this, false, true, "", -1); - Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq) { const Networking::NetworkReadStream *stream = rq->getNetworkReadStream(); if (stream) { @@ -193,7 +193,7 @@ void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { delete json; } -void BoxUploadRequest::notUploadedCallback(Networking::ErrorResponse error) { +void BoxUploadRequest::notUploadedCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; finishError(error); diff --git a/backends/cloud/box/boxuploadrequest.h b/backends/cloud/box/boxuploadrequest.h index 3d15aa70b3..1bc8690210 100644 --- a/backends/cloud/box/boxuploadrequest.h +++ b/backends/cloud/box/boxuploadrequest.h @@ -39,7 +39,7 @@ class BoxUploadRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _resolvedId, _parentId; - + void start(); void resolveId(); void idResolvedCallback(Storage::UploadResponse response); diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 55dbb2b42d..a4763dba2d 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -42,7 +42,7 @@ const char *const CloudManager::kStoragePrefix = "storage_"; CloudManager::CloudManager() : _currentStorageIndex(0), _activeStorage(nullptr) {} CloudManager::~CloudManager() { - //TODO: do we have to save storages on manager destruction? + //TODO: do we have to save storages on manager destruction? delete _activeStorage; freeStorages(); } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 2941ea6331..0146a4118e 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -89,7 +89,7 @@ public: * @note this method automatically saves the changes with ConfMan. * * @param storage Cloud::Storage to replace active storage with. - * @param index one of Cloud::StorageID enum values to indicate what storage type is replaced. + * @param index one of Cloud::StorageID enum values to indicate what storage type is replaced. */ void replaceStorage(Storage *storage, uint32 index); @@ -160,7 +160,7 @@ public: */ void setStorageUsername(uint32 index, Common::String name); - /** + /** * Set Storage's used space field. * Automatically saves changes to the config. * diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index e8c410ae3e..33ac81138d 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -66,7 +66,7 @@ void DownloadRequest::streamErrorCallback(Networking::ErrorResponse error) { finishError(error); } -void DownloadRequest::handle() { +void DownloadRequest::handle() { if (!_localFile) { warning("DownloadRequest: no file to write"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); @@ -96,12 +96,12 @@ void DownloadRequest::handle() { if (_remoteFileStream->eos()) { if (_remoteFileStream->httpResponseCode() != 200) { warning("HTTP response code is not 200 OK (it's %ld)", _remoteFileStream->httpResponseCode()); - //TODO: do something about it actually + //TODO: do something about it actually } finishDownload(_remoteFileStream->httpResponseCode() == 200); - _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() + _localFile->close(); //yes, I know it's closed automatically in ~DumpFile() } } diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h index 138616a04b..7e58098849 100644 --- a/backends/cloud/downloadrequest.h +++ b/backends/cloud/downloadrequest.h @@ -32,8 +32,8 @@ namespace Cloud { #define DOWNLOAD_REQUEST_BUFFER_SIZE 1 * 1024 * 1024 -class DownloadRequest: public Networking::Request { - Storage::BoolCallback _boolCallback; +class DownloadRequest: public Networking::Request { + Storage::BoolCallback _boolCallback; Common::DumpFile *_localFile; Common::String _remoteFileId; Storage *_storage; diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index 81ace75dda..6d228224d7 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -44,7 +44,7 @@ DropboxCreateDirectoryRequest::~DropboxCreateDirectoryRequest() { void DropboxCreateDirectoryRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) _workingRequest->finish(); _ignoreCallback = false; Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxCreateDirectoryRequest::responseCallback); @@ -74,13 +74,13 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - + if (!json) { warning("NULL passed instead of JSON"); finishError(error); return; } - + Common::JSONObject info = json->asObject(); if (info.contains("id")) finishCreation(true); else { diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h index 4bdc6dbee6..0ef6a22a04 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h @@ -37,7 +37,7 @@ class DropboxCreateDirectoryRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _date; - + void start(); void responseCallback(Networking::JsonResponse response); void errorCallback(Networking::ErrorResponse error); diff --git a/backends/cloud/dropbox/dropboxinforequest.cpp b/backends/cloud/dropbox/dropboxinforequest.cpp index f5a14abe1c..e147ac58e2 100644 --- a/backends/cloud/dropbox/dropboxinforequest.cpp +++ b/backends/cloud/dropbox/dropboxinforequest.cpp @@ -45,7 +45,7 @@ DropboxInfoRequest::~DropboxInfoRequest() { void DropboxInfoRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) _workingRequest->finish(); _ignoreCallback = false; Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxInfoRequest::userResponseCallback); @@ -70,7 +70,7 @@ void DropboxInfoRequest::userResponseCallback(Networking::JsonResponse response) Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - + if (!json) { warning("NULL passed instead of JSON"); finishError(error); diff --git a/backends/cloud/dropbox/dropboxinforequest.h b/backends/cloud/dropbox/dropboxinforequest.h index a91d016e60..68a3e135de 100644 --- a/backends/cloud/dropbox/dropboxinforequest.h +++ b/backends/cloud/dropbox/dropboxinforequest.h @@ -36,7 +36,7 @@ class DropboxInfoRequest: public Networking::Request { Storage::StorageInfoCallback _infoCallback; Request *_workingRequest; bool _ignoreCallback; - + void start(); void userResponseCallback(Networking::JsonResponse response); void quotaResponseCallback(Networking::JsonResponse response); 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)); } diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h index 62dde71f76..5c0d8dfa21 100644 --- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h +++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h @@ -41,7 +41,7 @@ class DropboxListDirectoryRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _date; - + void start(); void responseCallback(Networking::JsonResponse response); void errorCallback(Networking::ErrorResponse error); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 7e3521f40e..7ef07a5a65 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -87,7 +87,7 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { CloudMan.removeStorage(this); } else { _token = result.getVal("access_token")->asString(); - _uid = result.getVal("uid")->asString(); + _uid = result.getVal("uid")->asString(); ConfMan.removeKey("dropbox_code", ConfMan.kCloudDomain); CloudMan.replaceStorage(this, kStorageDropboxId); ConfMan.flushToDisk(); diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 9dd28ba810..0d308f4131 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -72,9 +72,9 @@ public: /** Returns ListDirectoryStatus struct with list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); - + /** 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); /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); @@ -92,7 +92,7 @@ public: virtual Common::String savesDirectoryPath(); /** - * Load token and user id from configs and return DropboxStorage for those. + * Load token and user id from configs and return DropboxStorage for those. * @return pointer to the newly created DropboxStorage or 0 if some problem occured. */ static DropboxStorage *loadFromConfig(Common::String keyPrefix); diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index 29b7f60c8a..eaa945ada3 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -63,9 +63,9 @@ void DropboxUploadRequest::start() { uploadNextPart(); } -void DropboxUploadRequest::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; @@ -82,8 +82,8 @@ void DropboxUploadRequest::uploadNextPart() { } } else { if ((uint32)(_contentsStream->size() - _contentsStream->pos()) <= UPLOAD_PER_ONE_REQUEST) { - url += "finish"; - Common::JSONObject jsonCursor, jsonCommit; + url += "finish"; + Common::JSONObject jsonCursor, jsonCommit; jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId)); jsonCursor.setVal("offset", new Common::JSONValue((long long int)_contentsStream->pos())); jsonCommit.setVal("path", new Common::JSONValue(_savePath)); @@ -98,22 +98,22 @@ void DropboxUploadRequest::uploadNextPart() { jsonCursor.setVal("session_id", new Common::JSONValue(_sessionId)); jsonCursor.setVal("offset", new Common::JSONValue((long long int)_contentsStream->pos())); jsonRequestParameters.setVal("cursor", new Common::JSONValue(jsonCursor)); - jsonRequestParameters.setVal("close", new Common::JSONValue(false)); + jsonRequestParameters.setVal("close", new Common::JSONValue(false)); } } - + Common::JSONValue value(jsonRequestParameters); Networking::JsonCallback callback = new Common::Callback(this, &DropboxUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &DropboxUploadRequest::partUploadedErrorCallback); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, url); request->addHeader("Authorization: Bearer " + _token); - request->addHeader("Content-Type: application/octet-stream"); - request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); + 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); } @@ -137,7 +137,7 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons //debug("%s", json->stringify(true).c_str()); if (object.contains("error") || object.contains("error_summary")) { - warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); + warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); error.response = json->stringify(true); finishError(error); delete json; @@ -162,14 +162,14 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons } } - if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { + if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { warning("no file info to return"); finishUpload(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } } else { - warning("null, not json"); + warning("null, not json"); finishError(error); } diff --git a/backends/cloud/dropbox/dropboxuploadrequest.h b/backends/cloud/dropbox/dropboxuploadrequest.h index 8d9a3e2650..5adf5a6df2 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.h +++ b/backends/cloud/dropbox/dropboxuploadrequest.h @@ -39,7 +39,7 @@ class DropboxUploadRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _sessionId; - + void start(); void uploadNextPart(); void partUploadedCallback(Networking::JsonResponse response); diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 9e05202bf7..de60480423 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -46,7 +46,7 @@ FolderDownloadRequest::~FolderDownloadRequest() { void FolderDownloadRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) _workingRequest->finish(); _currentFile = StorageFile(); _pendingFiles.clear(); _failedFiles.clear(); @@ -108,7 +108,7 @@ void FolderDownloadRequest::downloadNextFile() { finishDownload(_failedFiles); return; } - + _currentFile = _pendingFiles.back(); _pendingFiles.pop_back(); } while (_currentFile.isDirectory()); //TODO: may be create these directories (in case those are empty) @@ -124,7 +124,7 @@ void FolderDownloadRequest::downloadNextFile() { } else { warning("Can't process the following paths:"); warning("remote directory: %s", _remoteDirectoryPath.c_str()); - warning("remote file under that directory: %s", remotePath.c_str()); + warning("remote file under that directory: %s", remotePath.c_str()); } if (_localDirectoryPath != "") { if (_localDirectoryPath.lastChar() == '/' || _localDirectoryPath.lastChar() == '\\') diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 36bc390da0..7b05d48784 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -82,7 +82,7 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo Common::JSONObject responseObject = json->asObject(); ///debug("%s", json->stringify(true).c_str()); - + if (responseObject.contains("error") || responseObject.contains("error_summary")) { warning("GoogleDrive returned error: %s", responseObject.getVal("error_summary")->asString().c_str()); error.failed = true; @@ -92,7 +92,7 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo 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 (responseObject.contains("files") && responseObject.getVal("files")->isArray()) { Common::JSONArray items = responseObject.getVal("files")->asArray(); @@ -117,9 +117,9 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo if (hasMore) { Common::String token = responseObject.getVal("nextPageToken")->asString(); makeRequest(token); - } else { + } else { finishListing(_files); - } + } } else { warning("null, not json"); error.failed = true; @@ -142,7 +142,7 @@ void GoogleDriveListDirectoryByIdRequest::restart() { start(); } Common::String GoogleDriveListDirectoryByIdRequest::date() const { return _date; } -void GoogleDriveListDirectoryByIdRequest::finishListing(Common::Array &files) { +void GoogleDriveListDirectoryByIdRequest::finishListing(Common::Array &files) { Request::finishSuccess(); if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h index ecde880323..e94c6b1f4e 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.h @@ -34,7 +34,7 @@ namespace GoogleDrive { class GoogleDriveStorage; class GoogleDriveListDirectoryByIdRequest: public Networking::Request { - Common::String _requestedId; + Common::String _requestedId; GoogleDriveStorage *_storage; Storage::ListDirectoryCallback _listDirectoryCallback; @@ -42,7 +42,7 @@ class GoogleDriveListDirectoryByIdRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _date; - + void start(); void makeRequest(Common::String pageToken); void responseCallback(Networking::JsonResponse response); diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 77ac8989f1..2d9f33cfce 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -138,7 +138,7 @@ void GoogleDriveStorage::codeFlowFailed(Networking::ErrorResponse error) { CloudMan.removeStorage(this); } -void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { +void GoogleDriveStorage::saveConfig(Common::String keyPrefix) { ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain); ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain); } @@ -173,11 +173,11 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne //"usageInDrive":"6332462","limit":"18253611008","usage":"6332462","usageInDriveTrash":"0" Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); Common::String usage = storageQuota.getVal("usage")->asString(); - Common::String limit = storageQuota.getVal("limit")->asString(); + Common::String limit = storageQuota.getVal("limit")->asString(); quotaUsed = usage.asUint64(); quotaAllocated = limit.asUint64(); } - + CloudMan.setStorageUsername(kStorageGoogleDriveId, email); if (outerCallback) { @@ -197,7 +197,7 @@ void GoogleDriveStorage::createDirectoryInnerCallback(BoolCallback outerCallback } if (outerCallback) { - Common::JSONObject info = json->asObject(); + Common::JSONObject info = json->asObject(); (*outerCallback)(BoolResponse(nullptr, info.contains("id"))); delete outerCallback; } @@ -212,7 +212,7 @@ Networking::Request *GoogleDriveStorage::listDirectoryById(Common::String id, Li } Networking::Request *GoogleDriveStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { - return addRequest(new GoogleDriveUploadRequest(this, path, contents, callback, errorCallback)); + return addRequest(new GoogleDriveUploadRequest(this, path, contents, callback, errorCallback)); } Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { @@ -221,7 +221,7 @@ Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Netwo Common::String header = "Authorization: Bearer " + _token; curl_slist *headersList = curl_slist_append(nullptr, header.c_str()); Networking::NetworkReadStream *stream = new Networking::NetworkReadStream(url.c_str(), headersList, ""); - (*callback)(Networking::NetworkReadStreamResponse(nullptr, stream)); + (*callback)(Networking::NetworkReadStreamResponse(nullptr, stream)); } delete callback; delete errorCallback; @@ -237,8 +237,8 @@ void GoogleDriveStorage::printInfo(StorageInfoResponse response) { Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { if (!errorCallback) errorCallback = getErrorPrintingCallback(); - - Common::String url = "https://www.googleapis.com/drive/v3/files"; + + Common::String url = "https://www.googleapis.com/drive/v3/files"; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::createDirectoryInnerCallback, callback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + accessToken()); @@ -263,7 +263,7 @@ Networking::Request *GoogleDriveStorage::info(StorageInfoCallback callback, Netw Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::infoInnerCallback, callback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, "https://www.googleapis.com/drive/v3/about?fields=storageQuota,user"); request->addHeader("Authorization: Bearer " + _token); - return addRequest(request); + return addRequest(request); } Common::String GoogleDriveStorage::savesDirectoryPath() { return "scummvm/saves/"; } diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 4c164dd91d..e60719c770 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -95,7 +95,7 @@ public: virtual Common::String savesDirectoryPath(); /** - * Load token and user id from configs and return GoogleDriveStorage for those. + * Load token and user id from configs and return GoogleDriveStorage for those. * @return pointer to the newly created GoogleDriveStorage or 0 if some problem occured. */ static GoogleDriveStorage *loadFromConfig(Common::String keyPrefix); diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp index 9e26e62149..b876bc2995 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.cpp +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -52,7 +52,7 @@ void GoogleDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { } setHeaders(_headers); - //successfully received refreshed token, can restart the original request now + //successfully received refreshed token, can restart the original request now retry(0); } @@ -65,13 +65,13 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::JSONObject result = json->asObject(); if (result.contains("error")) { - //new token needed => request token & then retry original request + //new token needed => request token & then retry original request if (_stream) { debug(9, "code %ld", _stream->httpResponseCode()); } Common::JSONObject error = result.getVal("error")->asObject(); - bool irrecoverable = true; + bool irrecoverable = true; uint32 code = -1; Common::String message; @@ -88,13 +88,13 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (code == 401 || message == "Invalid Credentials") irrecoverable = false; - if (irrecoverable) { + if (irrecoverable) { finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode delete json; return; } - pause(); + pause(); delete json; _parentStorage->getAccessToken(new Common::Callback(this, &GoogleDriveTokenRefresher::tokenRefreshed)); return; @@ -104,7 +104,7 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { CurlJsonRequest::finishJson(json); } -void GoogleDriveTokenRefresher::setHeaders(Common::Array &headers) { +void GoogleDriveTokenRefresher::setHeaders(Common::Array &headers) { _headers = headers; curl_slist_free_all(_headersList); _headersList = 0; diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.h b/backends/cloud/googledrive/googledrivetokenrefresher.h index 3bc5fbd784..6cb3e41849 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.h +++ b/backends/cloud/googledrive/googledrivetokenrefresher.h @@ -33,12 +33,12 @@ class GoogleDriveStorage; class GoogleDriveTokenRefresher: public Networking::CurlJsonRequest { GoogleDriveStorage *_parentStorage; - Common::Array _headers; - + Common::Array _headers; + void tokenRefreshed(Storage::BoolResponse response); virtual void finishJson(Common::JSONValue *json); -public: +public: GoogleDriveTokenRefresher(GoogleDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); virtual ~GoogleDriveTokenRefresher(); diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index b63e989df8..4a7c30e9a5 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -164,7 +164,7 @@ void GoogleDriveUploadRequest::startUploadCallback(Networking::JsonResponse resp } } - Common::JSONValue *json = response.value; + Common::JSONValue *json = response.value; delete json; finishError(error); @@ -179,11 +179,11 @@ void GoogleDriveUploadRequest::startUploadErrorCallback(Networking::ErrorRespons void GoogleDriveUploadRequest::uploadNextPart() { const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; Common::String url = _uploadUrl; - + Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveUploadRequest::partUploadedErrorCallback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); - request->addHeader("Authorization: Bearer " + _storage->accessToken()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); request->usePut(); uint32 oldPos = _contentsStream->pos(); @@ -206,17 +206,17 @@ void GoogleDriveUploadRequest::uploadNextPart() { else request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos() - 1, _contentsStream->size())); } - + _workingRequest = ConnMan.addRequest(request); } bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream *stream) { //308 Resume Incomplete, with Range: X-Y header if (!stream) return false; - if (stream->httpResponseCode() != 308) return false; //seriously - + if (stream->httpResponseCode() != 308) return false; //seriously + Common::String headers = stream->responseHeaders(); - const char *cstr = headers.c_str(); + const char *cstr = headers.c_str(); for (int rangeTry = 0; rangeTry < 2; ++rangeTry) { const char *needle = (rangeTry==0 ? "Range: 0-" : "Range: bytes=0-"); uint32 needleLength = (rangeTry == 0 ? 9 : 15); @@ -239,12 +239,12 @@ bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream return false; } -void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse response) { +void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - + Networking::ErrorResponse error(this, false, true, "", -1); - Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq) { const Networking::NetworkReadStream *stream = rq->getNetworkReadStream(); if (stream) { @@ -301,16 +301,16 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res delete json; } -void GoogleDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { +void GoogleDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; - + Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)error.request; if (rq) { const Networking::NetworkReadStream *stream = rq->getNetworkReadStream(); if (stream) { - long code = stream->httpResponseCode(); - if (code == 308 && handleHttp308(stream)) { + long code = stream->httpResponseCode(); + if (code == 308 && handleHttp308(stream)) { return; } } diff --git a/backends/cloud/googledrive/googledriveuploadrequest.h b/backends/cloud/googledrive/googledriveuploadrequest.h index 8cc40795e9..73acab5bbd 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.h +++ b/backends/cloud/googledrive/googledriveuploadrequest.h @@ -42,7 +42,7 @@ class GoogleDriveUploadRequest: public Networking::Request { Common::String _resolvedId, _parentId; Common::String _uploadUrl; uint64 _serverReceivedBytes; - + void start(); void resolveId(); void idResolvedCallback(Storage::UploadResponse response); diff --git a/backends/cloud/id/idcreatedirectoryrequest.cpp b/backends/cloud/id/idcreatedirectoryrequest.cpp index 7968a4b126..f64133c888 100644 --- a/backends/cloud/id/idcreatedirectoryrequest.cpp +++ b/backends/cloud/id/idcreatedirectoryrequest.cpp @@ -56,7 +56,7 @@ void IdCreateDirectoryRequest::start() { _workingRequest = _storage->createDirectory("ScummVM", callback, failureCallback); return; } - + resolveId(); } @@ -97,9 +97,9 @@ void IdCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse _workingRequest = nullptr; if (_ignoreCallback) return; if (error.request) _date = error.request->date(); - + //not resolved => folder not exists - if (error.response.contains("no such file found in its parent directory")) { + if (error.response.contains("no such file found in its parent directory")) { //parent's id after the '\n' Common::String parentId = error.response; for (uint32 i = 0; i < parentId.size(); ++i) diff --git a/backends/cloud/id/iddownloadrequest.cpp b/backends/cloud/id/iddownloadrequest.cpp index 7166a1e026..edd2d26ece 100644 --- a/backends/cloud/id/iddownloadrequest.cpp +++ b/backends/cloud/id/iddownloadrequest.cpp @@ -48,7 +48,7 @@ void IdDownloadRequest::start() { //find file's id Storage::UploadCallback innerCallback = new Common::Callback(this, &IdDownloadRequest::idResolvedCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdDownloadRequest::idResolveFailedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdDownloadRequest::idResolveFailedCallback); _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); } diff --git a/backends/cloud/id/idlistdirectoryrequest.cpp b/backends/cloud/id/idlistdirectoryrequest.cpp index 012065dc77..6c70ed56a2 100644 --- a/backends/cloud/id/idlistdirectoryrequest.cpp +++ b/backends/cloud/id/idlistdirectoryrequest.cpp @@ -83,7 +83,7 @@ void IdListDirectoryRequest::listNextDirectory() { _directoriesQueue.pop_back(); Storage::FileArrayCallback callback = new Common::Callback(this, &IdListDirectoryRequest::listedDirectoryCallback); - Networking::ErrorCallback failureCallback = new Common::Callback(this, &IdListDirectoryRequest::listedDirectoryErrorCallback); + Networking::ErrorCallback failureCallback = new Common::Callback(this, &IdListDirectoryRequest::listedDirectoryErrorCallback); _workingRequest = _storage->listDirectoryById(_currentDirectory.id(), callback, failureCallback); } diff --git a/backends/cloud/id/idresolveidrequest.cpp b/backends/cloud/id/idresolveidrequest.cpp index fc61137088..abd64df1db 100644 --- a/backends/cloud/id/idresolveidrequest.cpp +++ b/backends/cloud/id/idresolveidrequest.cpp @@ -47,7 +47,7 @@ void IdResolveIdRequest::start() { _currentDirectory = ""; _currentDirectoryId = _storage->getRootDirectoryId(); _ignoreCallback = false; - + listNextDirectory(StorageFile(_currentDirectoryId, 0, 0, true)); } @@ -62,10 +62,10 @@ void IdResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { _workingRequest = _storage->listDirectoryById(_currentDirectoryId, callback, failureCallback); } -void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { +void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - + Common::String currentLevelName = _requestedPath; ///debug("'%s'", currentLevelName.c_str()); if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); diff --git a/backends/cloud/id/idresolveidrequest.h b/backends/cloud/id/idresolveidrequest.h index 94d4af5030..e735e96385 100644 --- a/backends/cloud/id/idresolveidrequest.h +++ b/backends/cloud/id/idresolveidrequest.h @@ -33,7 +33,7 @@ namespace Id { class IdStorage; class IdResolveIdRequest: public Networking::Request { - Common::String _requestedPath; + Common::String _requestedPath; IdStorage *_storage; Storage::UploadCallback _uploadCallback; Common::String _currentDirectory; diff --git a/backends/cloud/id/idstorage.h b/backends/cloud/id/idstorage.h index ccadc0e455..7e64fd4a37 100644 --- a/backends/cloud/id/idstorage.h +++ b/backends/cloud/id/idstorage.h @@ -50,7 +50,7 @@ protected: void printFile(UploadResponse response); ListDirectoryCallback getPrintFilesCallback(); - + public: virtual ~IdStorage(); diff --git a/backends/cloud/id/idstreamfilerequest.cpp b/backends/cloud/id/idstreamfilerequest.cpp index 08060b9e40..cc1ce2c54f 100644 --- a/backends/cloud/id/idstreamfilerequest.cpp +++ b/backends/cloud/id/idstreamfilerequest.cpp @@ -47,7 +47,7 @@ void IdStreamFileRequest::start() { //find file's id Storage::UploadCallback innerCallback = new Common::Callback(this, &IdStreamFileRequest::idResolvedCallback); - Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdStreamFileRequest::idResolveFailedCallback); + Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdStreamFileRequest::idResolveFailedCallback); _workingRequest = _storage->resolveFileId(_requestedFile, innerCallback, innerErrorCallback); } diff --git a/backends/cloud/iso8601.cpp b/backends/cloud/iso8601.cpp index 1675c7ce54..b2483fd7f9 100644 --- a/backends/cloud/iso8601.cpp +++ b/backends/cloud/iso8601.cpp @@ -44,9 +44,9 @@ int find(const char *cstr, uint32 startPosition, char needle) { namespace Cloud { namespace ISO8601 { -uint32 convertToTimestamp(const Common::String &iso8601Date) { +uint32 convertToTimestamp(const Common::String &iso8601Date) { //2015-05-12T15:50:38Z - const char *cstr = iso8601Date.c_str(); + const char *cstr = iso8601Date.c_str(); int firstHyphen = find(cstr, 0, '-'); int secondHyphen = find(cstr, firstHyphen + 1, '-'); int tSeparator = find(cstr, secondHyphen + 1, 'T'); @@ -54,7 +54,7 @@ uint32 convertToTimestamp(const Common::String &iso8601Date) { int secondColon = find(cstr, firstColon + 1, ':'); int zSeparator = find(cstr, secondColon + 1, 'Z'); if (zSeparator == -1) zSeparator = find(cstr, secondColon + 1, '-'); // Box's RFC 3339 - //now note '+1' which means if there ever was '-1' result of find(), we still did a valid find() from 0th char + //now note '+1' which means if there ever was '-1' result of find(), we still did a valid find() from 0th char Common::String year = getSubstring(iso8601Date, 0, firstHyphen); Common::String month = getSubstring(iso8601Date, firstHyphen + 1, secondHyphen); diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index 617346529b..c934f2e684 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -45,7 +45,7 @@ OneDriveCreateDirectoryRequest::~OneDriveCreateDirectoryRequest() { void OneDriveCreateDirectoryRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) _workingRequest->finish(); _ignoreCallback = false; Common::String name = _path, parent = _path; @@ -54,7 +54,7 @@ void OneDriveCreateDirectoryRequest::start() { while (true) { parent.deleteLastChar(); if (name[i] == '/' || name[i] == '\\') { - name.erase(0, i + 1); + name.erase(0, i + 1); break; } if (i == 0) break; @@ -62,9 +62,9 @@ void OneDriveCreateDirectoryRequest::start() { } } - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot"; + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot"; if (parent != "") url += ":/" + ConnMan.urlEncode(parent) + ":"; - url += "/children"; + url += "/children"; Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::responseCallback); Networking::ErrorCallback errorCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::errorCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, innerCallback, errorCallback, url.c_str()); @@ -93,13 +93,13 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - + if (!json) { warning("NULL passed instead of JSON"); finishError(error); return; } - + Common::JSONObject info = json->asObject(); if (info.contains("id")) finishCreation(true); else { diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h index 83c72c4e0a..acaca2bf00 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.h @@ -39,7 +39,7 @@ class OneDriveCreateDirectoryRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _date; - + void start(); void responseCallback(Networking::JsonResponse response); void errorCallback(Networking::ErrorResponse error); diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index baccdf418e..d0b2714989 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -77,7 +77,7 @@ void OneDriveListDirectoryRequest::listNextDirectory() { makeRequest(url); } -void OneDriveListDirectoryRequest::makeRequest(Common::String url) { +void OneDriveListDirectoryRequest::makeRequest(Common::String url) { Networking::JsonCallback callback = new Common::Callback(this, &OneDriveListDirectoryRequest::listedDirectoryCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &OneDriveListDirectoryRequest::listedDirectoryErrorCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); @@ -107,18 +107,18 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo return; } - Common::JSONObject object = json->asObject(); - + Common::JSONObject object = json->asObject(); + //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults Common::JSONArray items = object.getVal("value")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { - Common::JSONObject item = items[i]->asObject(); + Common::JSONObject item = items[i]->asObject(); Common::String path = _currentDirectory + item.getVal("name")->asString(); - bool isDirectory = item.contains("folder"); + bool isDirectory = item.contains("folder"); uint32 size = item.getVal("size")->asIntegerNumber(); - uint32 timestamp = ISO8601::convertToTimestamp(item.getVal("lastModifiedDateTime")->asString()); + uint32 timestamp = ISO8601::convertToTimestamp(item.getVal("lastModifiedDateTime")->asString()); StorageFile file(path, size, timestamp, isDirectory); _files.push_back(file); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 39213e82ed..5fc10b748c 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -154,7 +154,7 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo delete outerCallback; return; } - + Common::JSONObject info = json->asObject(); Common::String uid, name, email; diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 60817e6084..4985f3fd67 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -47,7 +47,7 @@ class OneDriveStorage: public Cloud::Storage { void infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse json); void fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response); -public: +public: /** This constructor uses OAuth code flow to get tokens. */ OneDriveStorage(Common::String code); virtual ~OneDriveStorage(); @@ -92,7 +92,7 @@ public: virtual Common::String savesDirectoryPath(); /** - * Load token and user id from configs and return OneDriveStorage for those. + * Load token and user id from configs and return OneDriveStorage for those. * @return pointer to the newly created OneDriveStorage or 0 if some problem occured. */ static OneDriveStorage *loadFromConfig(Common::String keyPrefix); diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 9afea3d5bd..88b5154d8a 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -52,7 +52,7 @@ void OneDriveTokenRefresher::tokenRefreshed(Storage::BoolResponse response) { } setHeaders(_headers); - //successfully received refreshed token, can restart the original request now + //successfully received refreshed token, can restart the original request now retry(0); } @@ -65,7 +65,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::JSONObject result = json->asObject(); if (result.contains("error")) { - //new token needed => request token & then retry original request + //new token needed => request token & then retry original request if (_stream) { debug(9, "code %ld", _stream->httpResponseCode()); } @@ -76,7 +76,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::String code, message; if (error.contains("code")) { code = error.getVal("code")->asString(); - debug(9, "code = %s", code.c_str()); + debug(9, "code = %s", code.c_str()); } if (error.contains("message")) { @@ -92,13 +92,13 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (code == "unauthenticated") irrecoverable = false; - if (irrecoverable) { + if (irrecoverable) { finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode delete json; return; } - pause(); + pause(); delete json; _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); return; @@ -108,7 +108,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { CurlJsonRequest::finishJson(json); } -void OneDriveTokenRefresher::setHeaders(Common::Array &headers) { +void OneDriveTokenRefresher::setHeaders(Common::Array &headers) { _headers = headers; curl_slist_free_all(_headersList); _headersList = 0; diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h index 4be1fa726b..77e34d4e03 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.h +++ b/backends/cloud/onedrive/onedrivetokenrefresher.h @@ -33,12 +33,12 @@ class OneDriveStorage; class OneDriveTokenRefresher: public Networking::CurlJsonRequest { OneDriveStorage *_parentStorage; - Common::Array _headers; - + Common::Array _headers; + void tokenRefreshed(Storage::BoolResponse response); virtual void finishJson(Common::JSONValue *json); -public: +public: OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url); virtual ~OneDriveTokenRefresher(); diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 569809d16b..2af4d06741 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -64,7 +64,7 @@ void OneDriveUploadRequest::start() { uploadNextPart(); } -void OneDriveUploadRequest::uploadNextPart() { +void OneDriveUploadRequest::uploadNextPart() { const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; if (_uploadUrl == "" && (uint32)_contentsStream->size() > UPLOAD_PER_ONE_REQUEST) { @@ -79,16 +79,16 @@ void OneDriveUploadRequest::uploadNextPart() { } Common::String url; - if (_uploadUrl == "") { + if (_uploadUrl == "") { url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+ConnMan.urlEncode(_savePath)+":/content"; - } else { + } else { url = _uploadUrl; } - + Networking::JsonCallback callback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedErrorCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); - request->addHeader("Authorization: Bearer " + _storage->accessToken()); + request->addHeader("Authorization: Bearer " + _storage->accessToken()); request->usePut(); uint32 oldPos = _contentsStream->pos(); @@ -106,18 +106,18 @@ void OneDriveUploadRequest::uploadNextPart() { delete request; return; } - + _workingRequest = ConnMan.addRequest(request); } -void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse response) { +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(); + error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); Common::JSONValue *json = response.value; if (json) { @@ -133,7 +133,7 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon } if (object.contains("id") && object.contains("name")) { - //finished + //finished Common::String path = _savePath; uint32 size = object.getVal("size")->asIntegerNumber(); uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("lastModifiedDateTime")->asString()); @@ -145,7 +145,7 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon if (object.contains("uploadUrl")) _uploadUrl = object.getVal("uploadUrl")->asString(); else - warning("no uploadUrl found in OneDrive's response"); + warning("no uploadUrl found in OneDrive's response"); } } @@ -156,14 +156,14 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon uploadNextPart(); } } else { - warning("null, not json"); + warning("null, not json"); finishError(error); } delete json; } -void OneDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { +void OneDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; if (_ignoreCallback) return; finishError(error); diff --git a/backends/cloud/onedrive/onedriveuploadrequest.h b/backends/cloud/onedrive/onedriveuploadrequest.h index f613c415e1..4e2cb24a7f 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.h +++ b/backends/cloud/onedrive/onedriveuploadrequest.h @@ -40,7 +40,7 @@ class OneDriveUploadRequest: public Networking::Request { Request *_workingRequest; bool _ignoreCallback; Common::String _uploadUrl; - + void start(); void uploadNextPart(); void partUploadedCallback(Networking::JsonResponse response); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 014e6a0ae6..957b7e655d 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -48,7 +48,7 @@ SavesSyncRequest::~SavesSyncRequest() { void SavesSyncRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) _workingRequest->finish(); _currentDownloadingFile = StorageFile(); _currentUploadingFile = ""; _filesToDownload.clear(); @@ -78,7 +78,7 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re if (response.request) _date = response.request->date(); Common::HashMap localFileNotAvailableInCloud; - for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { + for (Common::HashMap::iterator i = _localFilesTimestamps.begin(); i != _localFilesTimestamps.end(); ++i) { localFileNotAvailableInCloud[i->_key] = true; } @@ -96,7 +96,7 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re _filesToDownload.push_back(file); else { localFileNotAvailableInCloud[name] = false; - + if (_localFilesTimestamps[name] == file.timestamp()) continue; @@ -145,7 +145,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er //Dropbox-related error: if (object.contains("error_summary")) { Common::String summary = object.getVal("error_summary")->asString(); - if (summary.contains("not_found")) { + if (summary.contains("not_found")) { irrecoverable = false; } } @@ -223,7 +223,7 @@ void SavesSyncRequest::downloadNextFile() { _filesToDownload.pop_back(); sendCommand(GUI::kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); - + debug(9, "downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); _workingRequest = _storage->downloadById(_currentDownloadingFile.id(), DefaultSaveFileManager::concatWithSavesPath(_currentDownloadingFile.name()), new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), @@ -258,7 +258,7 @@ void SavesSyncRequest::fileDownloadedErrorCallback(Networking::ErrorResponse err if (_ignoreCallback) return; //stop syncing if download failed - finishError(error); + finishError(error); } void SavesSyncRequest::uploadNextFile() { @@ -269,8 +269,8 @@ void SavesSyncRequest::uploadNextFile() { _currentUploadingFile = _filesToUpload.back(); _filesToUpload.pop_back(); - - debug(9, "uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress()*100)); + + debug(9, "uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress()*100)); if (_storage->uploadStreamSupported()) { _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), @@ -288,7 +288,7 @@ void SavesSyncRequest::uploadNextFile() { void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; if (_ignoreCallback) return; - + //update local timestamp for the uploaded file _localFilesTimestamps = DefaultSaveFileManager::loadTimestamps(); _localFilesTimestamps[_currentUploadingFile] = response.value.timestamp(); @@ -345,7 +345,7 @@ void SavesSyncRequest::finishError(Networking::ErrorResponse error) { debug("SavesSync::finishError"); //if we were downloading a file - remember the name //and make the Request close() it, so we can delete it - Common::String name = _currentDownloadingFile.name(); + Common::String name = _currentDownloadingFile.name(); if (_workingRequest) { _ignoreCallback = true; _workingRequest->finish(); diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h index 304c44407c..e891e93969 100644 --- a/backends/cloud/savessyncrequest.h +++ b/backends/cloud/savessyncrequest.h @@ -57,7 +57,7 @@ class SavesSyncRequest: public Networking::Request, public GUI::CommandSender { void uploadNextFile(); virtual void finishError(Networking::ErrorResponse error); void finishSync(bool success); - + public: SavesSyncRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb); virtual ~SavesSyncRequest(); diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index 100d72b5be..dc403dfb30 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -132,7 +132,7 @@ SavesSyncRequest *Storage::syncSaves(BoolCallback callback, Networking::ErrorCal if (!errorCallback) errorCallback = new Common::Callback(this, &Storage::savesSyncDefaultErrorCallback); _savesSyncRequest = new SavesSyncRequest(this, callback, errorCallback); _syncRestartRequestsed = false; - _runningRequestsMutex.unlock(); + _runningRequestsMutex.unlock(); return (SavesSyncRequest *)addRequest(_savesSyncRequest); //who knows what that ConnMan could return in the future } diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index eaa6e9cea0..8582a7575a 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -110,7 +110,7 @@ public: virtual void saveConfig(Common::String keyPrefix) = 0; /** - * Return unique storage name. + * Return unique storage name. * @returns some unique storage name (for example, "Dropbox (user@example.com)") */ virtual Common::String name() const = 0; @@ -125,7 +125,7 @@ public: /** Returns ListDirectoryResponse with list of files. */ virtual Networking::Request *listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false) = 0; - + /** Returns StorageFile 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 remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback); diff --git a/backends/cloud/storageinfo.h b/backends/cloud/storageinfo.h index e0666bc190..469f0402c0 100644 --- a/backends/cloud/storageinfo.h +++ b/backends/cloud/storageinfo.h @@ -32,7 +32,7 @@ namespace Cloud { * It's disk quota usage, owner name, and such. */ -class StorageInfo { +class StorageInfo { Common::String _uid, _name, _email; uint64 _usedBytes, _allocatedBytes; -- cgit v1.2.3 From 772d8ee42b820a5c19a8d9a9efb215f17606fb8f Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 21 Jul 2016 12:06:00 +0600 Subject: CLOUD: Fix `redirect_uri` selection code Now it's not hardcoded based on USE_SDL_NET, but one or another value is used depending on currently selected LocalWebserver's port. --- backends/cloud/box/boxstorage.cpp | 10 +++++----- backends/cloud/cloudmanager.cpp | 11 +++++++++++ backends/cloud/cloudmanager.h | 3 +++ backends/cloud/dropbox/dropboxstorage.cpp | 10 +++++----- backends/cloud/googledrive/googledrivestorage.cpp | 10 +++++----- backends/cloud/onedrive/onedrivestorage.cpp | 10 +++++----- 6 files changed, 34 insertions(+), 20 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 6d4b5efd8e..873e4fabc1 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -88,11 +88,11 @@ void BoxStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); /* -#ifdef USE_SDL_NET - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); -#else - request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); -#endif + if (Cloud::CloudManager::couldUseLocalServer()) { + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); + } else { + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); + } */ addRequest(request); } diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a4763dba2d..f5b7c97afc 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -28,6 +28,9 @@ #include "common/translation.h" #include "common/config-manager.h" #include "common/str.h" +#ifdef USE_SDL_NET +#include "backends/networking/sdl_net/localwebserver.h" +#endif namespace Common { @@ -296,6 +299,14 @@ bool CloudManager::isWorking() const { return false; } +bool CloudManager::couldUseLocalServer() { +#ifdef USE_SDL_NET + return Networking::LocalWebserver::getPort() == Networking::LocalWebserver::DEFAULT_SERVER_PORT; +#else + return false; +#endif +} + ///// SavesSyncRequest-related ///// bool CloudManager::isSyncing() const { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 0146a4118e..42aa7189b9 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -207,6 +207,9 @@ public: /** Returns whether there are any requests running. */ bool isWorking() const; + /** Returns whether LocalWebserver is available to use for auth. */ + static bool couldUseLocalServer(); + ///// SavesSyncRequest-related ///// /** Returns whether there is a SavesSyncRequest running. */ diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 7ef07a5a65..d35e29fb05 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -69,11 +69,11 @@ void DropboxStorage::getAccessToken(Common::String code) { request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); -#ifdef USE_SDL_NET - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); -#else - request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); -#endif + if (Cloud::CloudManager::couldUseLocalServer()) { + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); + } else { + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); + } addRequest(request); } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 2d9f33cfce..fbb5e69881 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -87,11 +87,11 @@ void GoogleDriveStorage::getAccessToken(BoolCallback callback, Networking::Error } request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); -#ifdef USE_SDL_NET - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); -#else - request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); -#endif + if (Cloud::CloudManager::couldUseLocalServer()) { + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); + } else { + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); + } addRequest(request); } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 5fc10b748c..7c1849e0da 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -88,11 +88,11 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Networking::ErrorCal } request->addPostField("client_id=" + Common::String(KEY)); request->addPostField("client_secret=" + Common::String(SECRET)); -#ifdef USE_SDL_NET - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); -#else - request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); -#endif + if (Cloud::CloudManager::couldUseLocalServer()) { + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"); + } else { + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); + } addRequest(request); } -- cgit v1.2.3 From 9254df2d9614b2cc8e35a3abbdc593e54616a322 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Thu, 21 Jul 2016 09:29:54 +0200 Subject: CLOUD: Fix code formatting --- backends/cloud/box/boxlistdirectorybyidrequest.cpp | 14 +++---- backends/cloud/box/boxstorage.cpp | 10 ++--- backends/cloud/box/boxstorage.h | 2 +- backends/cloud/box/boxuploadrequest.cpp | 10 ++--- backends/cloud/cloudmanager.h | 46 +++++++++++----------- backends/cloud/dropbox/dropboxstorage.h | 2 +- backends/cloud/folderdownloadrequest.cpp | 2 +- .../googledrivelistdirectorybyidrequest.cpp | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 6 +-- backends/cloud/googledrive/googledrivestorage.h | 2 +- .../cloud/googledrive/googledriveuploadrequest.cpp | 2 +- backends/cloud/id/idcreatedirectoryrequest.cpp | 2 +- backends/cloud/id/idresolveidrequest.cpp | 2 +- backends/cloud/iso8601.h | 4 +- backends/cloud/onedrive/onedrivestorage.cpp | 6 +-- backends/cloud/onedrive/onedrivestorage.h | 2 +- backends/cloud/onedrive/onedriveuploadrequest.cpp | 19 +++++---- backends/cloud/savessyncrequest.cpp | 17 +++++--- backends/cloud/storage.h | 4 +- backends/cloud/storagefile.cpp | 2 +- 20 files changed, 81 insertions(+), 75 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp index 537666bc52..5a4e06265f 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.cpp +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -37,7 +37,7 @@ namespace Box { BoxListDirectoryByIdRequest::BoxListDirectoryByIdRequest(BoxStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _requestedId(id), _storage(storage), _listDirectoryCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { + _workingRequest(nullptr), _ignoreCallback(false) { start(); } @@ -91,12 +91,12 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp //TODO: check that error is returned the right way /* if (responseObject.contains("error") || responseObject.contains("error_summary")) { - warning("Box returned error: %s", responseObject.getVal("error_summary")->asString().c_str()); - error.failed = true; - error.response = json->stringify(); - finishError(error); - delete json; - return; + warning("Box returned error: %s", responseObject.getVal("error_summary")->asString().c_str()); + error.failed = true; + error.response = json->stringify(); + finishError(error); + delete json; + return; } */ diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 873e4fabc1..cd61e042da 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -57,9 +57,9 @@ BoxStorage::BoxStorage(Common::String accessToken, Common::String refreshToken): BoxStorage::BoxStorage(Common::String code) { getAccessToken( - new Common::Callback(this, &BoxStorage::codeFlowComplete), - new Common::Callback(this, &BoxStorage::codeFlowFailed), - code + new Common::Callback(this, &BoxStorage::codeFlowComplete), + new Common::Callback(this, &BoxStorage::codeFlowFailed), + code ); } @@ -89,9 +89,9 @@ void BoxStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback request->addPostField("client_secret=" + Common::String(SECRET)); /* if (Cloud::CloudManager::couldUseLocalServer()) { - request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); + request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345"); } else { - request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); + request->addPostField("&redirect_uri=https%3A%2F%2Fwww.scummvm.org/c/code"); } */ addRequest(request); diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 89bc470a26..80a572cb31 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -68,7 +68,7 @@ public: /** * Return unique storage name. - * @returns some unique storage name (for example, "Dropbox (user@example.com)") + * @returns some unique storage name (for example, "Dropbox (user@example.com)") */ virtual Common::String name() const; diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index d1f68f1d24..1449aa97e3 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -174,11 +174,11 @@ void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { //TODO: check errors /* if (object.contains("error")) { - warning("Box returned error: %s", json->stringify(true).c_str()); - delete json; - error.response = json->stringify(true); - finishError(error); - return; + warning("Box returned error: %s", json->stringify(true).c_str()); + delete json; + error.response = json->stringify(true); + finishError(error); + return; } */ } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index 42aa7189b9..aad01338a9 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -88,8 +88,8 @@ public: * Replace active Storage. * @note this method automatically saves the changes with ConfMan. * - * @param storage Cloud::Storage to replace active storage with. - * @param index one of Cloud::StorageID enum values to indicate what storage type is replaced. + * @param storage Cloud::Storage to replace active storage with. + * @param index one of Cloud::StorageID enum values to indicate what storage type is replaced. */ void replaceStorage(Storage *storage, uint32 index); @@ -100,54 +100,54 @@ public: * Returns active Storage, which could be used to interact * with cloud storage. * - * @return active Cloud::Storage or null, if there is no active Storage. + * @return active Cloud::Storage or null, if there is no active Storage. */ Cloud::Storage *getCurrentStorage() const; /** * Return active Storage's index. * - * @return active Storage's index. + * @return active Storage's index. */ uint32 getStorageIndex() const; /** * Return Storages names as list. * - * @return a list of Storages names. + * @return a list of Storages names. */ Common::StringArray listStorages() const; /** * Changes the storage to the one with given index. * - * @param new Storage's index. + * @param new Storage's index. */ bool switchStorage(uint32 index); /** * Return username used by Storage. * - * @param Storage's index. - * @returns username or "" if index is invalid (no such Storage). + * @param Storage's index. + * @returns username or "" if index is invalid (no such Storage). */ Common::String getStorageUsername(uint32 index); /** * Return space used by Storage. * - * @param Storage's index. - * @returns used space in bytes or 0 if index is invalid (no such Storage). + * @param Storage's index. + * @returns used space in bytes or 0 if index is invalid (no such Storage). */ uint64 getStorageUsedSpace(uint32 index); /** * Return Storage's last sync date. * - * @param Storage's index. - * @returns last sync date or "" if index is invalid (no such Storage). - It also returns "" if there never was any sync - or if storage is syncing right now. + * @param Storage's index. + * @returns last sync date or "" if index is invalid (no such Storage). + It also returns "" if there never was any sync + or if storage is syncing right now. */ Common::String getStorageLastSync(uint32 index); @@ -155,8 +155,8 @@ public: * Set Storage's username. * Automatically saves changes to the config. * - * @param index Storage's index. - * @param name username to set + * @param index Storage's index. + * @param name username to set */ void setStorageUsername(uint32 index, Common::String name); @@ -164,8 +164,8 @@ public: * Set Storage's used space field. * Automatically saves changes to the config. * - * @param index Storage's index. - * @param used value to set + * @param index Storage's index. + * @param used value to set */ void setStorageUsedSpace(uint32 index, uint64 used); @@ -173,8 +173,8 @@ public: * Set Storage's last sync date. * Automatically saves changes to the config. * - * @param index Storage's index. - * @param date date to set + * @param index Storage's index. + * @param date date to set */ void setStorageLastSync(uint32 index, Common::String date); @@ -182,8 +182,8 @@ public: * Replace Storage which has given index with a * storage created with given code. * - * @param index Storage's index - * @param code OAuth2 code received from user + * @param index Storage's index + * @param code OAuth2 code received from user */ void connectStorage(uint32 index, Common::String code); @@ -264,7 +264,7 @@ public: }; /** Shortcut for accessing the connection manager. */ -#define CloudMan Cloud::CloudManager::instance() +#define CloudMan Cloud::CloudManager::instance() } // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 0d308f4131..1f46c51558 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -64,7 +64,7 @@ public: /** * Return unique storage name. - * @returns some unique storage name (for example, "Dropbox (user@example.com)") + * @returns some unique storage name (for example, "Dropbox (user@example.com)") */ virtual Common::String name() const; diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index de60480423..ebcd167506 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -69,7 +69,7 @@ void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryRespon _pendingFiles = response.value; // remove all directories - for (Common::Array::iterator i = _pendingFiles.begin(); i != _pendingFiles.end(); ) + for (Common::Array::iterator i = _pendingFiles.begin(); i != _pendingFiles.end();) if (i->isDirectory()) _pendingFiles.erase(i); else { diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 7b05d48784..3228dde100 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -35,7 +35,7 @@ namespace GoogleDrive { GoogleDriveListDirectoryByIdRequest::GoogleDriveListDirectoryByIdRequest(GoogleDriveStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _requestedId(id), _storage(storage), _listDirectoryCallback(cb), - _workingRequest(nullptr), _ignoreCallback(false) { + _workingRequest(nullptr), _ignoreCallback(false) { start(); } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index fbb5e69881..3d87be36d5 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -57,9 +57,9 @@ GoogleDriveStorage::GoogleDriveStorage(Common::String accessToken, Common::Strin GoogleDriveStorage::GoogleDriveStorage(Common::String code) { getAccessToken( - new Common::Callback(this, &GoogleDriveStorage::codeFlowComplete), - new Common::Callback(this, &GoogleDriveStorage::codeFlowFailed), - code + new Common::Callback(this, &GoogleDriveStorage::codeFlowComplete), + new Common::Callback(this, &GoogleDriveStorage::codeFlowFailed), + code ); } diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index e60719c770..6a834c44ca 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -70,7 +70,7 @@ public: /** * Return unique storage name. - * @returns some unique storage name (for example, "Dropbox (user@example.com)") + * @returns some unique storage name (for example, "Dropbox (user@example.com)") */ virtual Common::String name() const; diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index 4a7c30e9a5..90dc8af9d2 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -218,7 +218,7 @@ bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream Common::String headers = stream->responseHeaders(); const char *cstr = headers.c_str(); for (int rangeTry = 0; rangeTry < 2; ++rangeTry) { - const char *needle = (rangeTry==0 ? "Range: 0-" : "Range: bytes=0-"); + const char *needle = (rangeTry == 0 ? "Range: 0-" : "Range: bytes=0-"); uint32 needleLength = (rangeTry == 0 ? 9 : 15); const char *position = strstr(cstr, needle); //if it lost the first part, I refuse to talk with it diff --git a/backends/cloud/id/idcreatedirectoryrequest.cpp b/backends/cloud/id/idcreatedirectoryrequest.cpp index f64133c888..11f65033ae 100644 --- a/backends/cloud/id/idcreatedirectoryrequest.cpp +++ b/backends/cloud/id/idcreatedirectoryrequest.cpp @@ -104,7 +104,7 @@ void IdCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse Common::String parentId = error.response; for (uint32 i = 0; i < parentId.size(); ++i) if (parentId[i] == '\n') { - parentId.erase(0, i+1); + parentId.erase(0, i + 1); break; } diff --git a/backends/cloud/id/idresolveidrequest.cpp b/backends/cloud/id/idresolveidrequest.cpp index abd64df1db..38478fa149 100644 --- a/backends/cloud/id/idresolveidrequest.cpp +++ b/backends/cloud/id/idresolveidrequest.cpp @@ -101,7 +101,7 @@ void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse resp } if (!found) { - if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n")+_currentDirectoryId, 404)); + if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n") + _currentDirectoryId, 404)); else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); } } diff --git a/backends/cloud/iso8601.h b/backends/cloud/iso8601.h index 6e11322cdb..cdd817bc07 100644 --- a/backends/cloud/iso8601.h +++ b/backends/cloud/iso8601.h @@ -28,8 +28,8 @@ namespace Cloud { namespace ISO8601 { - /** Returns timestamp corresponding to given ISO 8601 date */ - uint32 convertToTimestamp(const Common::String &iso8601Date); +/** Returns timestamp corresponding to given ISO 8601 date */ +uint32 convertToTimestamp(const Common::String &iso8601Date); } // End of namespace ISO8601 } // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 7c1849e0da..a26dec37a4 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -58,9 +58,9 @@ OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String user OneDriveStorage::OneDriveStorage(Common::String code) { getAccessToken( - new Common::Callback(this, &OneDriveStorage::codeFlowComplete), - new Common::Callback(this, &OneDriveStorage::codeFlowFailed), - code + new Common::Callback(this, &OneDriveStorage::codeFlowComplete), + new Common::Callback(this, &OneDriveStorage::codeFlowFailed), + code ); } diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 4985f3fd67..59c61074e3 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -67,7 +67,7 @@ public: /** * Return unique storage name. - * @returns some unique storage name (for example, "Dropbox (user@example.com)") + * @returns some unique storage name (for example, "Dropbox (user@example.com)") */ virtual Common::String name() const; diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 2af4d06741..a22dbf06a3 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -68,7 +68,7 @@ void OneDriveUploadRequest::uploadNextPart() { const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; if (_uploadUrl == "" && (uint32)_contentsStream->size() > UPLOAD_PER_ONE_REQUEST) { - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+ConnMan.urlEncode(_savePath)+":/upload.createSession"; //folder must exist + Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(_savePath) + ":/upload.createSession"; //folder must exist Networking::JsonCallback callback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedErrorCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); @@ -80,7 +80,7 @@ void OneDriveUploadRequest::uploadNextPart() { Common::String url; if (_uploadUrl == "") { - url = "https://api.onedrive.com/v1.0/drive/special/approot:/"+ConnMan.urlEncode(_savePath)+":/content"; + url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(_savePath) + ":/content"; } else { url = _uploadUrl; } @@ -98,14 +98,13 @@ void OneDriveUploadRequest::uploadNextPart() { request->setBuffer(buffer, size); if (_uploadUrl != "") - request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos()-1, _contentsStream->size())); - else - if (_contentsStream->size() == 0) { - warning("\"Sorry, OneDrive can't upload empty files\""); - finishUpload(StorageFile(_savePath, 0, 0, false)); - delete request; - return; - } + request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos() - 1, _contentsStream->size())); + else if (_contentsStream->size() == 0) { + warning("\"Sorry, OneDrive can't upload empty files\""); + finishUpload(StorageFile(_savePath, 0, 0, false)); + delete request; + return; + } _workingRequest = ConnMan.addRequest(request); } diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 957b7e655d..e3b3aa2400 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -181,7 +181,8 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er Common::String dir = _storage->savesDirectoryPath(); if (dir.lastChar() == '/') dir.deleteLastChar(); debug(9, "creating %s", dir.c_str()); - _workingRequest = _storage->createDirectory(dir, + _workingRequest = _storage->createDirectory( + dir, new Common::Callback(this, &SavesSyncRequest::directoryCreatedCallback), new Common::Callback(this, &SavesSyncRequest::directoryCreatedErrorCallback) ); @@ -225,7 +226,9 @@ void SavesSyncRequest::downloadNextFile() { sendCommand(GUI::kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); debug(9, "downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); - _workingRequest = _storage->downloadById(_currentDownloadingFile.id(), DefaultSaveFileManager::concatWithSavesPath(_currentDownloadingFile.name()), + _workingRequest = _storage->downloadById( + _currentDownloadingFile.id(), + DefaultSaveFileManager::concatWithSavesPath(_currentDownloadingFile.name()), new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), new Common::Callback(this, &SavesSyncRequest::fileDownloadedErrorCallback) ); @@ -270,14 +273,18 @@ void SavesSyncRequest::uploadNextFile() { _currentUploadingFile = _filesToUpload.back(); _filesToUpload.pop_back(); - debug(9, "uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress()*100)); + debug(9, "uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress() * 100)); if (_storage->uploadStreamSupported()) { - _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, g_system->getSavefileManager()->openRawFile(_currentUploadingFile), + _workingRequest = _storage->upload( + _storage->savesDirectoryPath() + _currentUploadingFile, + g_system->getSavefileManager()->openRawFile(_currentUploadingFile), new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) ); } else { - _workingRequest = _storage->upload(_storage->savesDirectoryPath() + _currentUploadingFile, DefaultSaveFileManager::concatWithSavesPath(_currentUploadingFile), + _workingRequest = _storage->upload( + _storage->savesDirectoryPath() + _currentUploadingFile, + DefaultSaveFileManager::concatWithSavesPath(_currentUploadingFile), new Common::Callback(this, &SavesSyncRequest::fileUploadedCallback), new Common::Callback(this, &SavesSyncRequest::fileUploadedErrorCallback) ); diff --git a/backends/cloud/storage.h b/backends/cloud/storage.h index 8582a7575a..6a5765f13a 100644 --- a/backends/cloud/storage.h +++ b/backends/cloud/storage.h @@ -111,7 +111,7 @@ public: /** * Return unique storage name. - * @returns some unique storage name (for example, "Dropbox (user@example.com)") + * @returns some unique storage name (for example, "Dropbox (user@example.com)") */ virtual Common::String name() const = 0; @@ -155,7 +155,7 @@ public: * Calls the if failed to get information. * * @note on success Storage should also call - * CloudMan.setStorageUsername(). + * CloudMan.setStorageUsername(). */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) = 0; diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp index 4bee92edce..c1107ea23d 100644 --- a/backends/cloud/storagefile.cpp +++ b/backends/cloud/storagefile.cpp @@ -42,7 +42,7 @@ StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { uint32 i = _name.size() - 1; while (true) { if (_name[i] == '/' || _name[i] == '\\') { - _name.erase(0, i+1); + _name.erase(0, i + 1); break; } if (i == 0) break; -- cgit v1.2.3 From efebb5b90dd84f962572f3e8df161f6284465cbc Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 21 Jul 2016 13:58:58 +0600 Subject: CLOUD: Remove DropboxStorage::remove() --- backends/cloud/dropbox/dropboxstorage.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index 1f46c51558..0a0043abee 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -79,9 +79,6 @@ public: /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Calls the callback when finished. */ virtual Networking::Request *createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback); -- cgit v1.2.3 From 8c62993769dd12d3ee96eba84f3b35d8c63f9269 Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Thu, 21 Jul 2016 10:12:41 +0200 Subject: CLOUD: Remove remove() from BoxStorage --- backends/cloud/box/boxstorage.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 80a572cb31..018562379f 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -87,9 +87,6 @@ public: /** Returns pointer to Networking::NetworkReadStream. */ virtual Networking::Request *streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback); - /** Calls the callback when finished. */ - virtual Networking::Request *remove(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { return nullptr; } //TODO - /** Returns the StorageInfo struct. */ virtual Networking::Request *info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback); -- cgit v1.2.3 From bd8f2ed8250f902b9061f2c3688857390ceebe97 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 21 Jul 2016 14:50:24 +0600 Subject: CLOUD: Fix some TODOs in CloudManager "No Storage connected!" error message is passed to the error callback now when there is no Storage connected to the CloudManager. --- backends/cloud/cloudmanager.cpp | 16 ++++++++++++---- backends/cloud/cloudmanager.h | 3 +++ 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index f5b7c97afc..056eb086c5 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -45,7 +45,6 @@ const char *const CloudManager::kStoragePrefix = "storage_"; CloudManager::CloudManager() : _currentStorageIndex(0), _activeStorage(nullptr) {} CloudManager::~CloudManager() { - //TODO: do we have to save storages on manager destruction? delete _activeStorage; freeStorages(); } @@ -161,6 +160,11 @@ void CloudManager::freeStorages() { _storagesToRemove.clear(); } +void CloudManager::passNoStorageConnected(Networking::ErrorCallback errorCallback) const { + if (errorCallback == nullptr) return; + (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "No Storage connected!", -1)); +} + Storage *CloudManager::getCurrentStorage() const { return _activeStorage; } @@ -249,9 +253,9 @@ Networking::Request *CloudManager::listDirectory(Common::String path, Storage::L Storage *storage = getCurrentStorage(); if (storage) return storage->listDirectory(path, callback, errorCallback, recursive); else { + passNoStorageConnected(errorCallback); delete callback; delete errorCallback; - //TODO: should we call errorCallback? } return nullptr; } @@ -260,9 +264,9 @@ Networking::Request *CloudManager::downloadFolder(Common::String remotePath, Com Storage *storage = getCurrentStorage(); if (storage) return storage->downloadFolder(remotePath, localPath, callback, errorCallback, recursive); else { + passNoStorageConnected(errorCallback); delete callback; delete errorCallback; - //TODO: should we call errorCallback? } return nullptr; } @@ -271,9 +275,9 @@ Networking::Request *CloudManager::info(Storage::StorageInfoCallback callback, N Storage *storage = getCurrentStorage(); if (storage) return storage->info(callback, errorCallback); else { + passNoStorageConnected(errorCallback); delete callback; delete errorCallback; - //TODO: should we call errorCallback? } return nullptr; } @@ -289,6 +293,10 @@ SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networ if (storage) { setStorageLastSync(_currentStorageIndex, "???"); //TODO get the date return storage->syncSaves(callback, errorCallback); + } else { + passNoStorageConnected(errorCallback); + delete callback; + delete errorCallback; } return nullptr; } diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index aad01338a9..c504ff39cb 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -68,6 +68,9 @@ class CloudManager : public Common::Singleton { /** Frees memory used by storages which failed to connect. */ void freeStorages(); + /** Calls the error callback with a special "no storage connected" message. */ + void passNoStorageConnected(Networking::ErrorCallback errorCallback) const; + public: CloudManager(); virtual ~CloudManager(); -- cgit v1.2.3 From 5f9beb76cdb7b34acc258cd30c4c7390036f25c1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 21 Jul 2016 15:39:21 +0600 Subject: CLOUD: Fix HTTP response code TODOs --- backends/cloud/googledrive/googledrivetokenrefresher.cpp | 6 ++++-- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp index b876bc2995..1b858504c5 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.cpp +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -64,10 +64,12 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { } Common::JSONObject result = json->asObject(); + long httpResponseCode = -1; if (result.contains("error")) { //new token needed => request token & then retry original request if (_stream) { - debug(9, "code %ld", _stream->httpResponseCode()); + httpResponseCode = _stream->httpResponseCode(); + debug(9, "code %ld", httpResponseCode); } Common::JSONObject error = result.getVal("error")->asObject(); @@ -89,7 +91,7 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { irrecoverable = false; if (irrecoverable) { - finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpResponseCode)); delete json; return; } diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 88b5154d8a..3e429f1ef8 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -64,10 +64,12 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { } Common::JSONObject result = json->asObject(); + long httpResponseCode = -1; if (result.contains("error")) { //new token needed => request token & then retry original request if (_stream) { - debug(9, "code %ld", _stream->httpResponseCode()); + httpResponseCode = _stream->httpResponseCode(); + debug(9, "code %ld", httpResponseCode); } Common::JSONObject error = result.getVal("error")->asObject(); @@ -93,7 +95,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (code == "unauthenticated") irrecoverable = false; if (irrecoverable) { - finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), -1)); //TODO: httpCode + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpResponseCode)); delete json; return; } -- cgit v1.2.3 From a30d0d19945890acae27a9fc3a2520f9b36fc04c Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 21 Jul 2016 15:49:01 +0600 Subject: CLOUD: Update DownloadRequest's TODO We need a way to reopen DumpFile if we want DownloadRequest to support restarting. --- backends/cloud/downloadrequest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 33ac81138d..49a8a1e179 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -44,7 +44,7 @@ void DownloadRequest::start() { _ignoreCallback = true; if (_workingRequest) _workingRequest->finish(); _remoteFileStream = nullptr; - //TODO: reopen DumpFile + //TODO: add some way to reopen DumpFile, so DownloadRequest could be restarted _ignoreCallback = false; _workingRequest = _storage->streamFileById( -- cgit v1.2.3 From 758f46ddf0ad312858fa0260c7e92a2d242dc40a Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 21 Jul 2016 15:53:00 +0600 Subject: CLOUD: Fix FolderDownloadRequest TODO --- backends/cloud/folderdownloadrequest.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index ebcd167506..1b3c1c57f5 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -69,6 +69,7 @@ void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryRespon _pendingFiles = response.value; // remove all directories + // non-empty directories would be created by DumpFile, and empty ones are just ignored for (Common::Array::iterator i = _pendingFiles.begin(); i != _pendingFiles.end();) if (i->isDirectory()) _pendingFiles.erase(i); @@ -111,7 +112,7 @@ void FolderDownloadRequest::downloadNextFile() { _currentFile = _pendingFiles.back(); _pendingFiles.pop_back(); - } while (_currentFile.isDirectory()); //TODO: may be create these directories (in case those are empty) + } while (_currentFile.isDirectory()); // directories are actually removed earlier, in the directoryListedCallback() sendCommand(GUI::kDownloadProgressCmd, (int)(getProgress() * 100)); -- cgit v1.2.3 From 876b8616afc290028a714108ec476486d4ef9b8f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 22 Jul 2016 14:15:19 +0300 Subject: CLOUD: Fix format warning --- backends/cloud/googledrive/googledrivestorage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 3d87be36d5..33b2bf5efd 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -232,7 +232,7 @@ void GoogleDriveStorage::printInfo(StorageInfoResponse response) { debug(9, "\nuser info:"); debug(9, "\tname: %s", response.value.name().c_str()); debug(9, "\temail: %s", response.value.email().c_str()); - debug(9, "\tdisk usage: %llu/%llu", response.value.used(), response.value.available()); + debug(9, "\tdisk usage: %lu/%lu", response.value.used(), response.value.available()); } Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { -- cgit v1.2.3 From 43c940c98579e669826de838eff9dcb372d453f7 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 22 Jul 2016 18:04:56 +0600 Subject: CLOUD: Updated BoxListDirectoryByIdRequest It now checks for all keys in JSON to avoid segfaults and prints warnings if passed keys are missing or have wrong types. --- backends/cloud/box/boxlistdirectorybyidrequest.cpp | 174 ++++++++++++++------- 1 file changed, 121 insertions(+), 53 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp index 5a4e06265f..3e518066f2 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.cpp +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -83,67 +83,135 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); Common::JSONValue *json = response.value; - if (json) { - Common::JSONObject responseObject = json->asObject(); - - //debug("%s", json->stringify(true).c_str()); - - //TODO: check that error is returned the right way - /* - if (responseObject.contains("error") || responseObject.contains("error_summary")) { - warning("Box returned error: %s", responseObject.getVal("error_summary")->asString().c_str()); - error.failed = true; - error.response = json->stringify(); - finishError(error); - delete json; - return; + 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(); + //debug(9, "%s", json->stringify(true).c_str()); + + //TODO: check that error is returned the right way + /* + if (responseObject.contains("error") || responseObject.contains("error_summary")) { + warning("Box returned error: %s", responseObject.getVal("error_summary")->asString().c_str()); + error.failed = true; + error.response = json->stringify(); + finishError(error); + delete json; + return; + } + */ + + //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 (responseObject.contains("entries") && responseObject.getVal("entries")->isArray()) { - Common::JSONArray items = responseObject.getVal("entries")->asArray(); - for (uint32 i = 0; i < items.size(); ++i) { - Common::JSONObject item = items[i]->asObject(); - Common::String id = item.getVal("id")->asString(); - Common::String name = item.getVal("name")->asString(); - bool isDirectory = (item.getVal("type")->asString() == "folder"); - uint32 size = 0, timestamp = 0; + + Common::JSONArray items = responseObject.getVal("entries")->asArray(); + for (uint32 i = 0; i < items.size(); ++i) { + if (!items[i]->isObject()) { + warning("BoxListDirectoryByIdRequest: \"entries\" item is not an object!"); + debug(9, "%s", items[i]->stringify(true).c_str()); + continue; + } + + Common::JSONObject item = items[i]->asObject(); + + if (!item.contains("id") || !item.getVal("id")->isString()) { + warning("BoxListDirectoryByIdRequest: \"entries\" item's \"id\"!"); + if (item.contains("id")) { + debug(9, "%s", item.getVal("id")->stringify(true).c_str()); + } else { + debug(9, "(not available)"); + } + continue; + } + + if (!item.contains("name") || !item.getVal("name")->isString()) { + warning("BoxListDirectoryByIdRequest: \"entries\" item's \"name\"!"); + if (item.contains("name")) { + debug(9, "%s", item.getVal("name")->stringify(true).c_str()); + } else { + debug(9, "(not available)"); + } + continue; + } + + if (!item.contains("type") || !item.getVal("type")->isString()) { + warning("BoxListDirectoryByIdRequest: \"entries\" item's \"type\"!"); + if (item.contains("type")) { + debug(9, "%s", item.getVal("type")->stringify(true).c_str()); + } else { + debug(9, "(not available)"); + } + continue; + } + + if (!item.contains("size") || (!item.getVal("size")->isString() && !item.getVal("size")->isIntegerNumber())) { + warning("BoxListDirectoryByIdRequest: \"entries\" item's \"size\"!"); if (item.contains("size")) { - if (item.getVal("size")->isString()) - size = item.getVal("size")->asString().asUint64(); - else if (item.getVal("size")->isIntegerNumber()) - size = item.getVal("size")->asIntegerNumber(); - else - warning("strange type for field 'size'"); + debug(9, "%s", item.getVal("size")->stringify(true).c_str()); + } else { + debug(9, "(not available)"); + } + continue; + } + + if (!item.contains("modified_at") || !item.getVal("modified_at")->isString()) { + warning("BoxListDirectoryByIdRequest: \"entries\" item's \"modified_at\"!"); + if (item.contains("modified_at")) { + debug(9, "%s", item.getVal("modified_at")->stringify(true).c_str()); + } else { + debug(9, "(not available)"); } - if (item.contains("modified_at") && item.getVal("modified_at")->isString()) - timestamp = ISO8601::convertToTimestamp(item.getVal("modified_at")->asString()); + continue; + } - //as we list directory by id, we can't determine full path for the file, so we leave it empty - _files.push_back(StorageFile(id, "", name, size, timestamp, isDirectory)); + Common::String id = item.getVal("id")->asString(); + Common::String name = item.getVal("name")->asString(); + bool isDirectory = (item.getVal("type")->asString() == "folder"); + uint32 size; + if (item.getVal("size")->isString()) { + size = item.getVal("size")->asString().asUint64(); + } else { + size = item.getVal("size")->asIntegerNumber(); } - } + uint32 timestamp = ISO8601::convertToTimestamp(item.getVal("modified_at")->asString()); - uint32 received = 0; - uint32 totalCount = 0; - if (responseObject.contains("total_count") && responseObject.getVal("total_count")->isIntegerNumber()) - totalCount = responseObject.getVal("total_count")->asIntegerNumber(); - if (responseObject.contains("offset") && responseObject.getVal("offset")->isIntegerNumber()) - received = responseObject.getVal("offset")->asIntegerNumber(); - if (responseObject.contains("limit") && responseObject.getVal("limit")->isIntegerNumber()) - received += responseObject.getVal("limit")->asIntegerNumber(); - bool hasMore = (received < totalCount); - - if (hasMore) makeRequest(received); - else finishListing(_files); - } else { - warning("null, not json"); - error.failed = true; - finishError(error); + //as we list directory by id, we can't determine full path for the file, so we leave it empty + _files.push_back(StorageFile(id, "", name, size, timestamp, isDirectory)); + } } + uint32 received = 0; + uint32 totalCount = 0; + if (responseObject.contains("total_count") && responseObject.getVal("total_count")->isIntegerNumber()) + totalCount = responseObject.getVal("total_count")->asIntegerNumber(); + if (responseObject.contains("offset") && responseObject.getVal("offset")->isIntegerNumber()) + received = responseObject.getVal("offset")->asIntegerNumber(); + if (responseObject.contains("limit") && responseObject.getVal("limit")->isIntegerNumber()) + received += responseObject.getVal("limit")->asIntegerNumber(); + bool hasMore = (received < totalCount); + + if (hasMore) makeRequest(received); + else finishListing(_files); + delete json; } -- cgit v1.2.3 From cccfe7c247fed9b00c100e64433439386d6ef077 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Fri, 22 Jul 2016 18:27:49 +0600 Subject: CLOUD: Update BoxListDirectoryByIdRequest It now uses special CurlJsonRequest static methods to check whether JSON is an object, has a string or integer parameter. --- backends/cloud/box/boxlistdirectorybyidrequest.cpp | 61 +++------------------- 1 file changed, 7 insertions(+), 54 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp index 3e518066f2..776ee71d64 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.cpp +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -125,63 +125,16 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp Common::JSONArray items = responseObject.getVal("entries")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { - if (!items[i]->isObject()) { - warning("BoxListDirectoryByIdRequest: \"entries\" item is not an object!"); - debug(9, "%s", items[i]->stringify(true).c_str()); - continue; - } + if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "BoxListDirectoryByIdRequest")) continue; Common::JSONObject item = items[i]->asObject(); - if (!item.contains("id") || !item.getVal("id")->isString()) { - warning("BoxListDirectoryByIdRequest: \"entries\" item's \"id\"!"); - if (item.contains("id")) { - debug(9, "%s", item.getVal("id")->stringify(true).c_str()); - } else { - debug(9, "(not available)"); - } - continue; - } - - if (!item.contains("name") || !item.getVal("name")->isString()) { - warning("BoxListDirectoryByIdRequest: \"entries\" item's \"name\"!"); - if (item.contains("name")) { - debug(9, "%s", item.getVal("name")->stringify(true).c_str()); - } else { - debug(9, "(not available)"); - } - continue; - } - - if (!item.contains("type") || !item.getVal("type")->isString()) { - warning("BoxListDirectoryByIdRequest: \"entries\" item's \"type\"!"); - if (item.contains("type")) { - debug(9, "%s", item.getVal("type")->stringify(true).c_str()); - } else { - debug(9, "(not available)"); - } - continue; - } - - if (!item.contains("size") || (!item.getVal("size")->isString() && !item.getVal("size")->isIntegerNumber())) { - warning("BoxListDirectoryByIdRequest: \"entries\" item's \"size\"!"); - if (item.contains("size")) { - debug(9, "%s", item.getVal("size")->stringify(true).c_str()); - } else { - debug(9, "(not available)"); - } - continue; - } - - if (!item.contains("modified_at") || !item.getVal("modified_at")->isString()) { - warning("BoxListDirectoryByIdRequest: \"entries\" item's \"modified_at\"!"); - if (item.contains("modified_at")) { - debug(9, "%s", item.getVal("modified_at")->stringify(true).c_str()); - } else { - debug(9, "(not available)"); - } - continue; - } + if (!Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "modified_at", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "size", "BoxListDirectoryByIdRequest") && + !Networking::CurlJsonRequest::jsonContainsIntegerNumber(item, "size", "BoxListDirectoryByIdRequest")) continue; Common::String id = item.getVal("id")->asString(); Common::String name = item.getVal("name")->asString(); -- 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 --- backends/cloud/box/boxstorage.cpp | 34 ++++-- backends/cloud/box/boxuploadrequest.cpp | 22 ++-- backends/cloud/cloudmanager.cpp | 124 ++++++++++++++------- backends/cloud/downloadrequest.cpp | 18 ++- .../dropbox/dropboxcreatedirectoryrequest.cpp | 20 ++-- backends/cloud/dropbox/dropboxinforequest.cpp | 9 +- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 21 ++-- backends/cloud/dropbox/dropboxstorage.cpp | 12 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 15 ++- backends/cloud/folderdownloadrequest.cpp | 35 ++++-- .../googledrivelistdirectorybyidrequest.cpp | 24 ++-- backends/cloud/googledrive/googledrivestorage.cpp | 33 ++++-- .../cloud/googledrive/googledriveuploadrequest.cpp | 53 ++++++--- backends/cloud/id/idcreatedirectoryrequest.cpp | 51 ++++++--- backends/cloud/id/iddownloadrequest.cpp | 24 ++-- backends/cloud/id/idlistdirectoryrequest.cpp | 36 ++++-- backends/cloud/id/idresolveidrequest.cpp | 33 ++++-- backends/cloud/id/idstorage.cpp | 18 ++- backends/cloud/id/idstreamfilerequest.cpp | 21 ++-- backends/cloud/iso8601.cpp | 6 +- .../onedrive/onedrivecreatedirectoryrequest.cpp | 29 +++-- .../onedrive/onedrivelistdirectoryrequest.cpp | 18 ++- backends/cloud/onedrive/onedrivestorage.cpp | 36 +++--- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 3 +- backends/cloud/onedrive/onedriveuploadrequest.cpp | 19 ++-- backends/cloud/savessyncrequest.cpp | 73 +++++++----- backends/cloud/storage.cpp | 25 +++-- backends/cloud/storagefile.cpp | 3 +- 28 files changed, 536 insertions(+), 279 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index cd61e042da..2b2be70e55 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -57,16 +57,17 @@ BoxStorage::BoxStorage(Common::String accessToken, Common::String refreshToken): BoxStorage::BoxStorage(Common::String code) { getAccessToken( - new Common::Callback(this, &BoxStorage::codeFlowComplete), - new Common::Callback(this, &BoxStorage::codeFlowFailed), - code + new Common::Callback(this, &BoxStorage::codeFlowComplete), + new Common::Callback(this, &BoxStorage::codeFlowFailed), + code ); } BoxStorage::~BoxStorage() {} void BoxStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback, Common::String code) { - if (!KEY || !SECRET) loadKeyAndSecret(); + if (!KEY || !SECRET) + loadKeyAndSecret(); bool codeFlow = (code != ""); if (!codeFlow && _refreshToken == "") { @@ -76,7 +77,9 @@ void BoxStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback } Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::tokenRefreshed, callback); - if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); + if (errorCallback == nullptr) + errorCallback = getErrorPrintingCallback(); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.box.com/oauth2/token"); if (codeFlow) { request->addPostField("grant_type=authorization_code"); @@ -109,12 +112,14 @@ void BoxStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse if (!result.contains("access_token") || !result.contains("refresh_token")) { warning("Bad response, no token passed"); debug("%s", json->stringify().c_str()); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); } else { _token = result.getVal("access_token")->asString(); _refreshToken = result.getVal("refresh_token")->asString(); CloudMan.save(); //ask CloudManager to save our new refreshToken - if (callback) (*callback)(BoolResponse(nullptr, true)); + if (callback) + (*callback)(BoolResponse(nullptr, true)); } delete json; } @@ -190,8 +195,10 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking } Networking::Request *BoxStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = getPrintFilesCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); + if (!callback) + callback = getPrintFilesCallback(); return addRequest(new BoxListDirectoryByIdRequest(this, id, callback, errorCallback)); } @@ -213,7 +220,8 @@ void BoxStorage::createDirectoryInnerCallback(BoolCallback outerCallback, Networ } Networking::Request *BoxStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); Common::String url = "https://api.box.com/2.0/folders"; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::createDirectoryInnerCallback, callback); @@ -235,13 +243,15 @@ Networking::Request *BoxStorage::createDirectoryWithParentId(Common::String pare } Networking::Request *BoxStorage::upload(Common::String remotePath, Common::String localPath, UploadCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); return addRequest(new BoxUploadRequest(this, remotePath, localPath, callback, errorCallback)); } Networking::Request *BoxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) { warning("BoxStorage::upload(ReadStream) not implemented"); - if (errorCallback) (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "BoxStorage::upload(ReadStream) not implemented", -1)); + if (errorCallback) + (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "BoxStorage::upload(ReadStream) not implemented", -1)); delete callback; delete errorCallback; return nullptr; diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index 1449aa97e3..c308ddb429 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -41,13 +41,15 @@ BoxUploadRequest::BoxUploadRequest(BoxStorage *storage, Common::String path, Com BoxUploadRequest::~BoxUploadRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _uploadCallback; } void BoxUploadRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _resolvedId = ""; //used to update file contents _parentId = ""; //used to create file within parent directory _ignoreCallback = false; @@ -101,7 +103,8 @@ void BoxUploadRequest::upload() { } Common::String url = "https://upload.box.com/api/2.0/files"; - if (_resolvedId != "") url += "/" + _resolvedId; + if (_resolvedId != "") + url += "/" + _resolvedId; url += "/content"; Networking::JsonCallback callback = new Common::Callback(this, &BoxUploadRequest::uploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &BoxUploadRequest::notUploadedCallback); @@ -174,11 +177,11 @@ void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { //TODO: check errors /* if (object.contains("error")) { - warning("Box returned error: %s", json->stringify(true).c_str()); - delete json; - error.response = json->stringify(true); - finishError(error); - return; + warning("Box returned error: %s", json->stringify(true).c_str()); + delete json; + error.response = json->stringify(true); + finishError(error); + return; } */ } @@ -205,7 +208,8 @@ void BoxUploadRequest::restart() { start(); } void BoxUploadRequest::finishUpload(StorageFile file) { Request::finishSuccess(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); + if (_uploadCallback) + (*_uploadCallback)(Storage::UploadResponse(this, file)); } } // End of namespace Box diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 056eb086c5..a68a8720ae 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -112,7 +112,8 @@ void CloudManager::init() { void CloudManager::save() { for (uint32 i = 0; i < _storages.size(); ++i) { - if (i == kStorageNoneId) continue; + if (i == kStorageNoneId) + continue; Common::String name = getStorageConfigName(i); ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username, ConfMan.kCloudDomain); ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate, ConfMan.kCloudDomain); @@ -127,12 +128,16 @@ void CloudManager::save() { void CloudManager::replaceStorage(Storage *storage, uint32 index) { freeStorages(); - if (!storage) error("CloudManager::replaceStorage: NULL storage passed"); - if (index >= kStorageTotal) error("CloudManager::replaceStorage: invalid index passed"); + if (!storage) + error("CloudManager::replaceStorage: NULL storage passed"); + if (index >= kStorageTotal) + error("CloudManager::replaceStorage: invalid index passed"); if (_activeStorage != nullptr && _activeStorage->isWorking()) { warning("CloudManager::replaceStorage: replacing Storage while the other is working"); - if (_activeStorage->isDownloading()) _activeStorage->cancelDownload(); - if (_activeStorage->isSyncing()) _activeStorage->cancelSync(); + if (_activeStorage->isDownloading()) + _activeStorage->cancelDownload(); + if (_activeStorage->isSyncing()) + _activeStorage->cancelSync(); removeStorage(_activeStorage); } else { delete _activeStorage; @@ -161,7 +166,8 @@ void CloudManager::freeStorages() { } void CloudManager::passNoStorageConnected(Networking::ErrorCallback errorCallback) const { - if (errorCallback == nullptr) return; + if (errorCallback == nullptr) + return; (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "No Storage connected!", -1)); } @@ -200,35 +206,42 @@ bool CloudManager::switchStorage(uint32 index) { } Common::String CloudManager::getStorageUsername(uint32 index) { - if (index >= _storages.size()) return ""; + if (index >= _storages.size()) + return ""; return _storages[index].username; } uint64 CloudManager::getStorageUsedSpace(uint32 index) { - if (index >= _storages.size()) return 0; + if (index >= _storages.size()) + return 0; return _storages[index].usedBytes; } Common::String CloudManager::getStorageLastSync(uint32 index) { - if (index >= _storages.size()) return ""; - if (index == _currentStorageIndex && isSyncing()) return ""; + if (index >= _storages.size()) + return ""; + if (index == _currentStorageIndex && isSyncing()) + return ""; return _storages[index].lastSyncDate; } void CloudManager::setStorageUsername(uint32 index, Common::String name) { - if (index >= _storages.size()) return; + if (index >= _storages.size()) + return; _storages[index].username = name; save(); } void CloudManager::setStorageUsedSpace(uint32 index, uint64 used) { - if (index >= _storages.size()) return; + if (index >= _storages.size()) + return; _storages[index].usedBytes = used; save(); } void CloudManager::setStorageLastSync(uint32 index, Common::String date) { - if (index >= _storages.size()) return; + if (index >= _storages.size()) + return; _storages[index].lastSyncDate = date; save(); } @@ -238,10 +251,18 @@ void CloudManager::connectStorage(uint32 index, Common::String code) { Storage *storage = nullptr; switch (index) { - case kStorageDropboxId: storage = new Dropbox::DropboxStorage(code); break; - case kStorageOneDriveId: storage = new OneDrive::OneDriveStorage(code); break; - case kStorageGoogleDriveId: storage = new GoogleDrive::GoogleDriveStorage(code); break; - case kStorageBoxId: storage = new Box::BoxStorage(code); break; + case kStorageDropboxId: + storage = new Dropbox::DropboxStorage(code); + break; + case kStorageOneDriveId: + storage = new OneDrive::OneDriveStorage(code); + break; + case kStorageGoogleDriveId: + storage = new GoogleDrive::GoogleDriveStorage(code); + break; + case kStorageBoxId: + storage = new Box::BoxStorage(code); + break; } // in these constructors Storages request token using the passed code // when the token is received, they call replaceStorage() @@ -251,8 +272,9 @@ void CloudManager::connectStorage(uint32 index, Common::String code) { Networking::Request *CloudManager::listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { Storage *storage = getCurrentStorage(); - if (storage) return storage->listDirectory(path, callback, errorCallback, recursive); - else { + if (storage) { + return storage->listDirectory(path, callback, errorCallback, recursive); + } else { passNoStorageConnected(errorCallback); delete callback; delete errorCallback; @@ -262,8 +284,9 @@ Networking::Request *CloudManager::listDirectory(Common::String path, Storage::L Networking::Request *CloudManager::downloadFolder(Common::String remotePath, Common::String localPath, Storage::FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { Storage *storage = getCurrentStorage(); - if (storage) return storage->downloadFolder(remotePath, localPath, callback, errorCallback, recursive); - else { + if (storage) { + return storage->downloadFolder(remotePath, localPath, callback, errorCallback, recursive); + } else { passNoStorageConnected(errorCallback); delete callback; delete errorCallback; @@ -273,8 +296,9 @@ Networking::Request *CloudManager::downloadFolder(Common::String remotePath, Com Networking::Request *CloudManager::info(Storage::StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Storage *storage = getCurrentStorage(); - if (storage) return storage->info(callback, errorCallback); - else { + if (storage) { + return storage->info(callback, errorCallback); + } else { passNoStorageConnected(errorCallback); delete callback; delete errorCallback; @@ -284,7 +308,8 @@ Networking::Request *CloudManager::info(Storage::StorageInfoCallback callback, N Common::String CloudManager::savesDirectoryPath() { Storage *storage = getCurrentStorage(); - if (storage) return storage->savesDirectoryPath(); + if (storage) + return storage->savesDirectoryPath(); return ""; } @@ -303,7 +328,8 @@ SavesSyncRequest *CloudManager::syncSaves(Storage::BoolCallback callback, Networ bool CloudManager::isWorking() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->isWorking(); + if (storage) + return storage->isWorking(); return false; } @@ -319,95 +345,111 @@ bool CloudManager::couldUseLocalServer() { bool CloudManager::isSyncing() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->isSyncing(); + if (storage) + return storage->isSyncing(); return false; } double CloudManager::getSyncDownloadingProgress() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getSyncDownloadingProgress(); + if (storage) + return storage->getSyncDownloadingProgress(); return 1; } double CloudManager::getSyncProgress() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getSyncProgress(); + if (storage) + return storage->getSyncProgress(); return 1; } Common::Array CloudManager::getSyncingFiles() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getSyncingFiles(); + if (storage) + return storage->getSyncingFiles(); return Common::Array(); } void CloudManager::cancelSync() const { Storage *storage = getCurrentStorage(); - if (storage) storage->cancelSync(); + if (storage) + storage->cancelSync(); } void CloudManager::setSyncTarget(GUI::CommandReceiver *target) const { Storage *storage = getCurrentStorage(); - if (storage) storage->setSyncTarget(target); + if (storage) + storage->setSyncTarget(target); } ///// DownloadFolderRequest-related ///// bool CloudManager::startDownload(Common::String remotePath, Common::String localPath) const { Storage *storage = getCurrentStorage(); - if (storage) return storage->startDownload(remotePath, localPath); + if (storage) + return storage->startDownload(remotePath, localPath); return false; } void CloudManager::cancelDownload() const { Storage *storage = getCurrentStorage(); - if (storage) storage->cancelDownload(); + if (storage) + storage->cancelDownload(); } void CloudManager::setDownloadTarget(GUI::CommandReceiver *target) const { Storage *storage = getCurrentStorage(); - if (storage) storage->setDownloadTarget(target); + if (storage) + storage->setDownloadTarget(target); } bool CloudManager::isDownloading() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->isDownloading(); + if (storage) + return storage->isDownloading(); return false; } double CloudManager::getDownloadingProgress() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getDownloadingProgress(); + if (storage) + return storage->getDownloadingProgress(); return 1; } uint64 CloudManager::getDownloadBytesNumber() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getDownloadBytesNumber(); + if (storage) + return storage->getDownloadBytesNumber(); return 0; } uint64 CloudManager::getDownloadTotalBytesNumber() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getDownloadTotalBytesNumber(); + if (storage) + return storage->getDownloadTotalBytesNumber(); return 0; } uint64 CloudManager::getDownloadSpeed() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getDownloadSpeed(); + if (storage) + return storage->getDownloadSpeed(); return 0; } Common::String CloudManager::getDownloadRemoteDirectory() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getDownloadRemoteDirectory(); + if (storage) + return storage->getDownloadRemoteDirectory(); return ""; } Common::String CloudManager::getDownloadLocalDirectory() const { Storage *storage = getCurrentStorage(); - if (storage) return storage->getDownloadLocalDirectory(); + if (storage) + return storage->getDownloadLocalDirectory(); return ""; } diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index 49a8a1e179..f706ed64f4 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -34,7 +34,8 @@ DownloadRequest::DownloadRequest(Storage *storage, Storage::BoolCallback callbac DownloadRequest::~DownloadRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _boolCallback; delete _localFile; delete[] _buffer; @@ -42,7 +43,8 @@ DownloadRequest::~DownloadRequest() { void DownloadRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _remoteFileStream = nullptr; //TODO: add some way to reopen DumpFile, so DownloadRequest could be restarted _ignoreCallback = false; @@ -56,13 +58,15 @@ void DownloadRequest::start() { void DownloadRequest::streamCallback(Networking::NetworkReadStreamResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; _remoteFileStream = (Networking::NetworkReadStream *)response.value; } void DownloadRequest::streamErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } @@ -113,11 +117,13 @@ void DownloadRequest::restart() { void DownloadRequest::finishDownload(bool success) { Request::finishSuccess(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); + if (_boolCallback) + (*_boolCallback)(Storage::BoolResponse(this, success)); } void DownloadRequest::finishError(Networking::ErrorResponse error) { - if (_localFile) _localFile->close(); + if (_localFile) + _localFile->close(); Request::finishError(error); } diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index 6d228224d7..968fb4550a 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -38,13 +38,15 @@ DropboxCreateDirectoryRequest::DropboxCreateDirectoryRequest(Common::String toke DropboxCreateDirectoryRequest::~DropboxCreateDirectoryRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _boolCallback; } void DropboxCreateDirectoryRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _ignoreCallback = false; Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxCreateDirectoryRequest::responseCallback); @@ -82,8 +84,9 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re } Common::JSONObject info = json->asObject(); - if (info.contains("id")) finishCreation(true); - else { + if (info.contains("id")) { + finishCreation(true); + } else { if (info.contains("error_summary") && info.getVal("error_summary")->isString()) { Common::String summary = info.getVal("error_summary")->asString(); if (summary.contains("path") && summary.contains("conflict") && summary.contains("folder")) { @@ -101,8 +104,10 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re void DropboxCreateDirectoryRequest::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); } @@ -114,7 +119,8 @@ Common::String DropboxCreateDirectoryRequest::date() const { return _date; } void DropboxCreateDirectoryRequest::finishCreation(bool success) { Request::finishSuccess(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); + if (_boolCallback) + (*_boolCallback)(Storage::BoolResponse(this, success)); } } // End of namespace Dropbox diff --git a/backends/cloud/dropbox/dropboxinforequest.cpp b/backends/cloud/dropbox/dropboxinforequest.cpp index e147ac58e2..37700eaf55 100644 --- a/backends/cloud/dropbox/dropboxinforequest.cpp +++ b/backends/cloud/dropbox/dropboxinforequest.cpp @@ -39,13 +39,15 @@ DropboxInfoRequest::DropboxInfoRequest(Common::String token, Storage::StorageInf DropboxInfoRequest::~DropboxInfoRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _infoCallback; } void DropboxInfoRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _ignoreCallback = false; Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxInfoRequest::userResponseCallback); @@ -136,7 +138,8 @@ void DropboxInfoRequest::restart() { start(); } void DropboxInfoRequest::finishInfo(StorageInfo info) { Request::finishSuccess(); - if (_infoCallback) (*_infoCallback)(Storage::StorageInfoResponse(this, info)); + if (_infoCallback) + (*_infoCallback)(Storage::StorageInfoResponse(this, info)); } } // End of namespace Dropbox 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 diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index d35e29fb05..cd1dff8afb 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -61,7 +61,8 @@ DropboxStorage::DropboxStorage(Common::String code) { DropboxStorage::~DropboxStorage() {} void DropboxStorage::getAccessToken(Common::String code) { - if (!KEY || !SECRET) loadKeyAndSecret(); + if (!KEY || !SECRET) + loadKeyAndSecret(); Networking::JsonCallback callback = new Common::Callback(this, &DropboxStorage::codeFlowComplete); Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxStorage::codeFlowFailed); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, errorCallback, "https://api.dropboxapi.com/oauth2/token"); @@ -134,17 +135,20 @@ Networking::Request *DropboxStorage::streamFileById(Common::String path, Network request->addHeader("Content-Type: "); //required to be empty (as we do POST, it's usually app/form-url-encoded) Networking::NetworkReadStreamResponse response = request->execute(); - if (callback) (*callback)(response); + if (callback) + (*callback)(response); return response.request; // no leak here, response.request == request } Networking::Request *DropboxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); return addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback)); } Networking::Request *DropboxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); return addRequest(new DropboxInfoRequest(_token, callback, errorCallback)); } diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index eaa945ada3..03c3fbc244 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -40,14 +40,16 @@ DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String DropboxUploadRequest::~DropboxUploadRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _contentsStream; delete _uploadCallback; } void DropboxUploadRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); if (!_contentsStream) { warning("DropboxUploadRequest: cannot start because stream is invalid"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); @@ -120,7 +122,8 @@ void DropboxUploadRequest::uploadNextPart() { void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse response) { debug(9, "partUploadedCallback"); _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Networking::ErrorResponse error(this, false, true, "", -1); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -179,7 +182,8 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons void DropboxUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { debug("partUploadedErrorCallback"); _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } @@ -189,7 +193,8 @@ void DropboxUploadRequest::restart() { start(); } void DropboxUploadRequest::finishUpload(StorageFile file) { Request::finishSuccess(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); + if (_uploadCallback) + (*_uploadCallback)(Storage::UploadResponse(this, file)); } } // End of namespace Dropbox diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index 1b3c1c57f5..fe9704cf81 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -39,14 +39,16 @@ FolderDownloadRequest::FolderDownloadRequest(Storage *storage, Storage::FileArra FolderDownloadRequest::~FolderDownloadRequest() { sendCommand(GUI::kDownloadEndedCmd, 0); _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _fileArrayCallback; } void FolderDownloadRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _currentFile = StorageFile(); _pendingFiles.clear(); _failedFiles.clear(); @@ -65,7 +67,8 @@ void FolderDownloadRequest::start() { void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; _pendingFiles = response.value; // remove all directories @@ -84,13 +87,15 @@ void FolderDownloadRequest::directoryListedCallback(Storage::ListDirectoryRespon void FolderDownloadRequest::directoryListedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; if (!response.value) _failedFiles.push_back(_currentFile); _downloadedBytes += _currentFile.size(); downloadNextFile(); @@ -98,7 +103,8 @@ void FolderDownloadRequest::fileDownloadedCallback(Storage::BoolResponse respons void FolderDownloadRequest::fileDownloadedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; fileDownloadedCallback(Storage::BoolResponse(error.request, false)); } @@ -153,23 +159,28 @@ void FolderDownloadRequest::restart() { start(); } void FolderDownloadRequest::finishDownload(Common::Array &files) { Request::finishSuccess(); - if (_fileArrayCallback) (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); + if (_fileArrayCallback) + (*_fileArrayCallback)(Storage::FileArrayResponse(this, files)); } double FolderDownloadRequest::getProgress() const { - if (_totalFiles == 0 || _totalBytes == 0) return 0; + if (_totalFiles == 0 || _totalBytes == 0) + return 0; return (double)getDownloadedBytes() / (double)getTotalBytesToDownload(); } uint64 FolderDownloadRequest::getDownloadedBytes() const { - if (_totalFiles == 0) return 0; + if (_totalFiles == 0) + return 0; double currentFileProgress = 0; DownloadRequest *downloadRequest = dynamic_cast(_workingRequest); - if (downloadRequest != nullptr) currentFileProgress = downloadRequest->getProgress(); - else { + if (downloadRequest != nullptr) { + currentFileProgress = downloadRequest->getProgress(); + } else { Id::IdDownloadRequest *idDownloadRequest = dynamic_cast(_workingRequest); - if (idDownloadRequest != nullptr) currentFileProgress = idDownloadRequest->getProgress(); + if (idDownloadRequest != nullptr) + currentFileProgress = idDownloadRequest->getProgress(); } return _downloadedBytes + (uint64)(currentFileProgress * _currentFile.size()); diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 3228dde100..d2e94a7196 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -41,13 +41,15 @@ GoogleDriveListDirectoryByIdRequest::GoogleDriveListDirectoryByIdRequest(GoogleD GoogleDriveListDirectoryByIdRequest::~GoogleDriveListDirectoryByIdRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _listDirectoryCallback; } void GoogleDriveListDirectoryByIdRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _files.clear(); _ignoreCallback = false; @@ -57,7 +59,8 @@ void GoogleDriveListDirectoryByIdRequest::start() { void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) { Common::String url = "https://www.googleapis.com/drive/v3/files?spaces=drive&fields=files%28id,mimeType,modifiedTime,name,size%29,nextPageToken&orderBy=folder,name"; //files(id,mimeType,modifiedTime,name,size),nextPageToken - if (pageToken != "") url += "&pageToken=" + pageToken; + if (pageToken != "") + url += "&pageToken=" + pageToken; url += "&q=%27" + _requestedId + "%27+in+parents"; Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveListDirectoryByIdRequest::responseCallback); @@ -69,8 +72,10 @@ void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); + if (_ignoreCallback) + return; + if (response.request) + _date = response.request->date(); Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -131,8 +136,10 @@ void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonRespo void GoogleDriveListDirectoryByIdRequest::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); } @@ -144,7 +151,8 @@ Common::String GoogleDriveListDirectoryByIdRequest::date() const { return _date; void GoogleDriveListDirectoryByIdRequest::finishListing(Common::Array &files) { Request::finishSuccess(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); + if (_listDirectoryCallback) + (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace GoogleDrive diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 33b2bf5efd..22013210d3 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -57,9 +57,9 @@ GoogleDriveStorage::GoogleDriveStorage(Common::String accessToken, Common::Strin GoogleDriveStorage::GoogleDriveStorage(Common::String code) { getAccessToken( - new Common::Callback(this, &GoogleDriveStorage::codeFlowComplete), - new Common::Callback(this, &GoogleDriveStorage::codeFlowFailed), - code + new Common::Callback(this, &GoogleDriveStorage::codeFlowComplete), + new Common::Callback(this, &GoogleDriveStorage::codeFlowFailed), + code ); } @@ -71,12 +71,14 @@ void GoogleDriveStorage::getAccessToken(BoolCallback callback, Networking::Error if (!codeFlow && _refreshToken == "") { warning("GoogleDriveStorage: no refresh token available to get new access token."); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); return; } Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::tokenRefreshed, callback); - if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); + if (errorCallback == nullptr) + errorCallback = getErrorPrintingCallback(); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://accounts.google.com/o/oauth2/token"); //TODO if (codeFlow) { request->addPostField("code=" + code); @@ -99,7 +101,8 @@ void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonR Common::JSONValue *json = response.value; if (!json) { warning("GoogleDriveStorage: got NULL instead of JSON"); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); return; } @@ -107,7 +110,8 @@ void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonR if (!result.contains("access_token")) { warning("Bad response, no token passed"); debug("%s", json->stringify().c_str()); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); } else { _token = result.getVal("access_token")->asString(); if (!result.contains("refresh_token")) @@ -115,7 +119,8 @@ void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonR else _refreshToken = result.getVal("refresh_token")->asString(); CloudMan.save(); //ask CloudManager to save our new refreshToken - if (callback) (*callback)(BoolResponse(nullptr, true)); + if (callback) + (*callback)(BoolResponse(nullptr, true)); } delete json; } @@ -206,8 +211,10 @@ void GoogleDriveStorage::createDirectoryInnerCallback(BoolCallback outerCallback } Networking::Request *GoogleDriveStorage::listDirectoryById(Common::String id, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printFiles); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); + if (!callback) + callback = new Common::Callback(this, &GoogleDriveStorage::printFiles); return addRequest(new GoogleDriveListDirectoryByIdRequest(this, id, callback, errorCallback)); } @@ -236,7 +243,8 @@ void GoogleDriveStorage::printInfo(StorageInfoResponse response) { } Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::String parentId, Common::String name, BoolCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); Common::String url = "https://www.googleapis.com/drive/v3/files"; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::createDirectoryInnerCallback, callback); @@ -259,7 +267,8 @@ Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::Str } Networking::Request *GoogleDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { - if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printInfo); + if (!callback) + callback = new Common::Callback(this, &GoogleDriveStorage::printInfo); Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::infoInnerCallback, callback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, "https://www.googleapis.com/drive/v3/about?fields=storageQuota,user"); request->addHeader("Authorization: Bearer " + _token); diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index 90dc8af9d2..3cdee26dbe 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -41,14 +41,16 @@ GoogleDriveUploadRequest::GoogleDriveUploadRequest(GoogleDriveStorage *storage, GoogleDriveUploadRequest::~GoogleDriveUploadRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _contentsStream; delete _uploadCallback; } void GoogleDriveUploadRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); if (_contentsStream == nullptr || !_contentsStream->seek(0)) { warning("GoogleDriveUploadRequest: cannot restart because stream couldn't seek(0)"); finishError(Networking::ErrorResponse(this, false, true, "", -1)); @@ -71,14 +73,16 @@ void GoogleDriveUploadRequest::resolveId() { void GoogleDriveUploadRequest::idResolvedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; _resolvedId = response.value.id(); startUpload(); } void GoogleDriveUploadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; //not resolved => error or no such file if (error.response.contains("no such file found in its parent directory")) { @@ -108,18 +112,21 @@ void GoogleDriveUploadRequest::startUpload() { } Common::String url = "https://www.googleapis.com/upload/drive/v3/files"; - if (_resolvedId != "") url += "/" + ConnMan.urlEncode(_resolvedId); + if (_resolvedId != "") + url += "/" + ConnMan.urlEncode(_resolvedId); url += "?uploadType=resumable&fields=id,mimeType,modifiedTime,name,size"; Networking::JsonCallback callback = new Common::Callback(this, &GoogleDriveUploadRequest::startUploadCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &GoogleDriveUploadRequest::startUploadErrorCallback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _storage->accessToken()); request->addHeader("Content-Type: application/json"); - if (_resolvedId != "") request->usePatch(); + if (_resolvedId != "") + request->usePatch(); Common::JSONObject jsonRequestParameters; - if (_resolvedId != "") jsonRequestParameters.setVal("id", new Common::JSONValue(_resolvedId)); - else { + if (_resolvedId != "") { + jsonRequestParameters.setVal("id", new Common::JSONValue(_resolvedId)); + } else { Common::JSONArray parentsArray; parentsArray.push_back(new Common::JSONValue(_parentId)); jsonRequestParameters.setVal("parents", new Common::JSONValue(parentsArray)); @@ -134,7 +141,8 @@ void GoogleDriveUploadRequest::startUpload() { void GoogleDriveUploadRequest::startUploadCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Networking::ErrorResponse error(this, false, true, "", -1); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -151,7 +159,8 @@ void GoogleDriveUploadRequest::startUploadCallback(Networking::JsonResponse resp Common::String result = ""; char c; for (const char *i = position + 10; c = *i, c != 0; ++i) { - if (c == '\n' || c == '\r') break; + if (c == '\n' || c == '\r') + break; result += c; } _uploadUrl = result; @@ -172,7 +181,8 @@ void GoogleDriveUploadRequest::startUploadCallback(Networking::JsonResponse resp void GoogleDriveUploadRequest::startUploadErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } @@ -198,7 +208,8 @@ void GoogleDriveUploadRequest::uploadNextPart() { byte *buffer = new byte[UPLOAD_PER_ONE_REQUEST]; uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST); - if (size != 0) request->setBuffer(buffer, size); + if (size != 0) + request->setBuffer(buffer, size); if (_uploadUrl != "") { if (_contentsStream->pos() == 0) @@ -212,8 +223,10 @@ void GoogleDriveUploadRequest::uploadNextPart() { bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream *stream) { //308 Resume Incomplete, with Range: X-Y header - if (!stream) return false; - if (stream->httpResponseCode() != 308) return false; //seriously + if (!stream) + return false; + if (stream->httpResponseCode() != 308) + return false; //seriously Common::String headers = stream->responseHeaders(); const char *cstr = headers.c_str(); @@ -227,7 +240,8 @@ bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream Common::String result = ""; char c; for (const char *i = position + needleLength; c = *i, c != 0; ++i) { - if (c == '\n' || c == '\r') break; + if (c == '\n' || c == '\r') + break; result += c; } _serverReceivedBytes = result.asUint64() + 1; @@ -241,7 +255,8 @@ bool GoogleDriveUploadRequest::handleHttp308(const Networking::NetworkReadStream void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Networking::ErrorResponse error(this, false, true, "", -1); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -303,7 +318,8 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res void GoogleDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)error.request; if (rq) { @@ -325,7 +341,8 @@ void GoogleDriveUploadRequest::restart() { start(); } void GoogleDriveUploadRequest::finishUpload(StorageFile file) { Request::finishSuccess(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); + if (_uploadCallback) + (*_uploadCallback)(Storage::UploadResponse(this, file)); } } // End of namespace GoogleDrive diff --git a/backends/cloud/id/idcreatedirectoryrequest.cpp b/backends/cloud/id/idcreatedirectoryrequest.cpp index 11f65033ae..37f417f806 100644 --- a/backends/cloud/id/idcreatedirectoryrequest.cpp +++ b/backends/cloud/id/idcreatedirectoryrequest.cpp @@ -36,20 +36,23 @@ IdCreateDirectoryRequest::IdCreateDirectoryRequest(IdStorage *storage, Common::S IdCreateDirectoryRequest::~IdCreateDirectoryRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _boolCallback; } void IdCreateDirectoryRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _workingRequest = nullptr; _ignoreCallback = false; //the only exception when we create parent folder - is when it's ScummVM/ base folder Common::String prefix = _requestedParentPath; - if (prefix.size() > 7) prefix.erase(7); + if (prefix.size() > 7) + prefix.erase(7); if (prefix.equalsIgnoreCase("ScummVM")) { Storage::BoolCallback callback = new Common::Callback(this, &IdCreateDirectoryRequest::createdBaseDirectoryCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &IdCreateDirectoryRequest::createdBaseDirectoryErrorCallback); @@ -62,15 +65,19 @@ void IdCreateDirectoryRequest::start() { void IdCreateDirectoryRequest::createdBaseDirectoryCallback(Storage::BoolResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); + if (_ignoreCallback) + return; + if (response.request) + _date = response.request->date(); resolveId(); } void IdCreateDirectoryRequest::createdBaseDirectoryErrorCallback(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); } @@ -79,15 +86,18 @@ void IdCreateDirectoryRequest::resolveId() { Storage::UploadCallback innerCallback = new Common::Callback(this, &IdCreateDirectoryRequest::idResolvedCallback); Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdCreateDirectoryRequest::idResolveFailedCallback); Common::String path = _requestedParentPath; - if (_requestedParentPath != "") path += "/"; + if (_requestedParentPath != "") + path += "/"; path += _requestedDirectoryName; _workingRequest = _storage->resolveFileId(path, innerCallback, innerErrorCallback); } void IdCreateDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); + if (_ignoreCallback) + return; + if (response.request) + _date = response.request->date(); //resolved => folder already exists finishCreation(false); @@ -95,8 +105,10 @@ void IdCreateDirectoryRequest::idResolvedCallback(Storage::UploadResponse respon void IdCreateDirectoryRequest::idResolveFailedCallback(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(); //not resolved => folder not exists if (error.response.contains("no such file found in its parent directory")) { @@ -119,15 +131,19 @@ void IdCreateDirectoryRequest::idResolveFailedCallback(Networking::ErrorResponse void IdCreateDirectoryRequest::createdDirectoryCallback(Storage::BoolResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); + if (_ignoreCallback) + return; + if (response.request) + _date = response.request->date(); finishCreation(response.value); } void IdCreateDirectoryRequest::createdDirectoryErrorCallback(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); } @@ -139,7 +155,8 @@ Common::String IdCreateDirectoryRequest::date() const { return _date; } void IdCreateDirectoryRequest::finishCreation(bool success) { Request::finishSuccess(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); + if (_boolCallback) + (*_boolCallback)(Storage::BoolResponse(this, success)); } } // End of namespace Id diff --git a/backends/cloud/id/iddownloadrequest.cpp b/backends/cloud/id/iddownloadrequest.cpp index edd2d26ece..2532d611b8 100644 --- a/backends/cloud/id/iddownloadrequest.cpp +++ b/backends/cloud/id/iddownloadrequest.cpp @@ -35,14 +35,16 @@ IdDownloadRequest::IdDownloadRequest(IdStorage *storage, Common::String remotePa IdDownloadRequest::~IdDownloadRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _boolCallback; } void IdDownloadRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _workingRequest = nullptr; _ignoreCallback = false; @@ -54,7 +56,8 @@ void IdDownloadRequest::start() { void IdDownloadRequest::idResolvedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Storage::BoolCallback innerCallback = new Common::Callback(this, &IdDownloadRequest::downloadCallback); Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdDownloadRequest::downloadErrorCallback); @@ -63,19 +66,22 @@ void IdDownloadRequest::idResolvedCallback(Storage::UploadResponse response) { void IdDownloadRequest::idResolveFailedCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } void IdDownloadRequest::downloadCallback(Storage::BoolResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishDownload(response.value); } void IdDownloadRequest::downloadErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } @@ -85,12 +91,14 @@ void IdDownloadRequest::restart() { start(); } void IdDownloadRequest::finishDownload(bool success) { Request::finishSuccess(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); + if (_boolCallback) + (*_boolCallback)(Storage::BoolResponse(this, success)); } double IdDownloadRequest::getProgress() const { DownloadRequest *downloadRequest = dynamic_cast(_workingRequest); - if (downloadRequest == nullptr) return 0; // resolving id still + if (downloadRequest == nullptr) + return 0; // resolving id still // id resolve is 10 % and download is the other 90 % return 0.1 + 0.9 * downloadRequest->getProgress(); // downloading diff --git a/backends/cloud/id/idlistdirectoryrequest.cpp b/backends/cloud/id/idlistdirectoryrequest.cpp index 6c70ed56a2..4e63709984 100644 --- a/backends/cloud/id/idlistdirectoryrequest.cpp +++ b/backends/cloud/id/idlistdirectoryrequest.cpp @@ -35,14 +35,16 @@ IdListDirectoryRequest::IdListDirectoryRequest(IdStorage *storage, Common::Strin IdListDirectoryRequest::~IdListDirectoryRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _listDirectoryCallback; } void IdListDirectoryRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _workingRequest = nullptr; _files.clear(); _directoriesQueue.clear(); @@ -57,8 +59,10 @@ void IdListDirectoryRequest::start() { void IdListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); + if (_ignoreCallback) + return; + if (response.request) + _date = response.request->date(); StorageFile directory = response.value; directory.setPath(_requestedPath); @@ -68,8 +72,10 @@ void IdListDirectoryRequest::idResolvedCallback(Storage::UploadResponse response void IdListDirectoryRequest::idResolveErrorCallback(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); } @@ -89,13 +95,16 @@ void IdListDirectoryRequest::listNextDirectory() { void IdListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); + if (_ignoreCallback) + return; + if (response.request) + _date = response.request->date(); for (uint32 i = 0; i < response.value.size(); ++i) { StorageFile &file = response.value[i]; Common::String path = _currentDirectory.path(); - if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') path += '/'; + if (path.size() && path.lastChar() != '/' && path.lastChar() != '\\') + path += '/'; path += file.name(); file.setPath(path); _files.push_back(file); @@ -109,8 +118,10 @@ void IdListDirectoryRequest::listedDirectoryCallback(Storage::FileArrayResponse void IdListDirectoryRequest::listedDirectoryErrorCallback(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); } @@ -122,7 +133,8 @@ Common::String IdListDirectoryRequest::date() const { return _date; } void IdListDirectoryRequest::finishListing(Common::Array &files) { Request::finishSuccess(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); + if (_listDirectoryCallback) + (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace Id diff --git a/backends/cloud/id/idresolveidrequest.cpp b/backends/cloud/id/idresolveidrequest.cpp index 38478fa149..6742a5890f 100644 --- a/backends/cloud/id/idresolveidrequest.cpp +++ b/backends/cloud/id/idresolveidrequest.cpp @@ -35,14 +35,16 @@ IdResolveIdRequest::IdResolveIdRequest(IdStorage *storage, Common::String path, IdResolveIdRequest::~IdResolveIdRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _uploadCallback; } void IdResolveIdRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _workingRequest = nullptr; _currentDirectory = ""; _currentDirectoryId = _storage->getRootDirectoryId(); @@ -64,12 +66,15 @@ void IdResolveIdRequest::listNextDirectory(StorageFile fileToReturn) { void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Common::String currentLevelName = _requestedPath; ///debug("'%s'", currentLevelName.c_str()); - if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); - if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) currentLevelName.erase(0, 1); + if (_currentDirectory.size()) + currentLevelName.erase(0, _currentDirectory.size()); + if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) + currentLevelName.erase(0, 1); ///debug("'%s'", currentLevelName.c_str()); for (uint32 i = 0; i < currentLevelName.size(); ++i) { if (currentLevelName[i] == '/' || currentLevelName[i] == '\\') { @@ -80,7 +85,8 @@ void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse resp } Common::String path = _currentDirectory; - if (path != "") path += "/"; + if (path != "") + path += "/"; path += currentLevelName; bool lastLevel = (path.equalsIgnoreCase(_requestedPath)); @@ -90,7 +96,8 @@ void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse resp bool found = false; for (uint32 i = 0; i < files.size(); ++i) { if ((files[i].isDirectory() || lastLevel) && files[i].name().equalsIgnoreCase(currentLevelName)) { - if (_currentDirectory != "") _currentDirectory += "/"; + if (_currentDirectory != "") + _currentDirectory += "/"; _currentDirectory += files[i].name(); _currentDirectoryId = files[i].id(); ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); @@ -101,14 +108,17 @@ void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse resp } if (!found) { - if (lastLevel) finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n") + _currentDirectoryId, 404)); - else finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); + if (lastLevel) + finishError(Networking::ErrorResponse(this, false, true, Common::String("no such file found in its parent directory\n") + _currentDirectoryId, 404)); + else + finishError(Networking::ErrorResponse(this, false, true, "subdirectory not found", 400)); } } void IdResolveIdRequest::listedDirectoryErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } @@ -118,7 +128,8 @@ void IdResolveIdRequest::restart() { start(); } void IdResolveIdRequest::finishFile(StorageFile file) { Request::finishSuccess(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); + if (_uploadCallback) + (*_uploadCallback)(Storage::UploadResponse(this, file)); } } // End of namespace Id diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index 5b0f9db347..857e3fb379 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -63,20 +63,26 @@ Storage::ListDirectoryCallback IdStorage::getPrintFilesCallback() { } Networking::Request *IdStorage::resolveFileId(Common::String path, UploadCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &IdStorage::printFile); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); + if (!callback) + callback = new Common::Callback(this, &IdStorage::printFile); return addRequest(new IdResolveIdRequest(this, path, callback, errorCallback)); } Networking::Request *IdStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &IdStorage::printFiles); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); + if (!callback) + callback = new Common::Callback(this, &IdStorage::printFiles); return addRequest(new IdListDirectoryRequest(this, path, callback, errorCallback, recursive)); } Networking::Request *IdStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); - if (!callback) callback = new Common::Callback(this, &IdStorage::printBool); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); + if (!callback) + callback = new Common::Callback(this, &IdStorage::printBool); //find out the parent path and directory name Common::String parentPath = "", directoryName = path; diff --git a/backends/cloud/id/idstreamfilerequest.cpp b/backends/cloud/id/idstreamfilerequest.cpp index cc1ce2c54f..2e68b15412 100644 --- a/backends/cloud/id/idstreamfilerequest.cpp +++ b/backends/cloud/id/idstreamfilerequest.cpp @@ -34,14 +34,16 @@ IdStreamFileRequest::IdStreamFileRequest(IdStorage *storage, Common::String path IdStreamFileRequest::~IdStreamFileRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _streamCallback; } void IdStreamFileRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _workingRequest = nullptr; _ignoreCallback = false; @@ -53,7 +55,8 @@ void IdStreamFileRequest::start() { void IdStreamFileRequest::idResolvedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Networking::NetworkReadStreamCallback innerCallback = new Common::Callback(this, &IdStreamFileRequest::streamFileCallback); Networking::ErrorCallback innerErrorCallback = new Common::Callback(this, &IdStreamFileRequest::streamFileErrorCallback); @@ -62,19 +65,22 @@ void IdStreamFileRequest::idResolvedCallback(Storage::UploadResponse response) { void IdStreamFileRequest::idResolveFailedCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } void IdStreamFileRequest::streamFileCallback(Networking::NetworkReadStreamResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishStream(response.value); } void IdStreamFileRequest::streamFileErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } @@ -84,7 +90,8 @@ void IdStreamFileRequest::restart() { start(); } void IdStreamFileRequest::finishStream(Networking::NetworkReadStream *stream) { Request::finishSuccess(); - if (_streamCallback) (*_streamCallback)(Networking::NetworkReadStreamResponse(this, stream)); + if (_streamCallback) + (*_streamCallback)(Networking::NetworkReadStreamResponse(this, stream)); } } // End of namespace Id diff --git a/backends/cloud/iso8601.cpp b/backends/cloud/iso8601.cpp index b2483fd7f9..177ef67f11 100644 --- a/backends/cloud/iso8601.cpp +++ b/backends/cloud/iso8601.cpp @@ -35,7 +35,8 @@ Common::String getSubstring(const Common::String &s, uint32 beginning, uint32 en int find(const char *cstr, uint32 startPosition, char needle) { const char *res = strchr(cstr + startPosition, needle); - if (res == nullptr) return -1; + if (res == nullptr) + return -1; return res - cstr; } @@ -53,7 +54,8 @@ uint32 convertToTimestamp(const Common::String &iso8601Date) { int firstColon = find(cstr, tSeparator + 1, ':'); int secondColon = find(cstr, firstColon + 1, ':'); int zSeparator = find(cstr, secondColon + 1, 'Z'); - if (zSeparator == -1) zSeparator = find(cstr, secondColon + 1, '-'); // Box's RFC 3339 + if (zSeparator == -1) + zSeparator = find(cstr, secondColon + 1, '-'); // Box's RFC 3339 //now note '+1' which means if there ever was '-1' result of find(), we still did a valid find() from 0th char Common::String year = getSubstring(iso8601Date, 0, firstHyphen); diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index c934f2e684..bd612d64a8 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -39,13 +39,15 @@ OneDriveCreateDirectoryRequest::OneDriveCreateDirectoryRequest(OneDriveStorage * OneDriveCreateDirectoryRequest::~OneDriveCreateDirectoryRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _boolCallback; } void OneDriveCreateDirectoryRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _ignoreCallback = false; Common::String name = _path, parent = _path; @@ -57,13 +59,15 @@ void OneDriveCreateDirectoryRequest::start() { name.erase(0, i + 1); break; } - if (i == 0) break; + if (i == 0) + break; --i; } } Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot"; - if (parent != "") url += ":/" + ConnMan.urlEncode(parent) + ":"; + if (parent != "") + url += ":/" + ConnMan.urlEncode(parent) + ":"; url += "/children"; Networking::JsonCallback innerCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::responseCallback); Networking::ErrorCallback errorCallback = new Common::Callback(this, &OneDriveCreateDirectoryRequest::errorCallback); @@ -87,7 +91,8 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r delete json; 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; @@ -101,8 +106,9 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r } Common::JSONObject info = json->asObject(); - if (info.contains("id")) finishCreation(true); - else { + if (info.contains("id")) { + finishCreation(true); + } else { error.response = json->stringify(true); finishError(error); } @@ -112,8 +118,10 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r void OneDriveCreateDirectoryRequest::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); } @@ -125,7 +133,8 @@ Common::String OneDriveCreateDirectoryRequest::date() const { return _date; } void OneDriveCreateDirectoryRequest::finishCreation(bool success) { Request::finishSuccess(); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); + if (_boolCallback) + (*_boolCallback)(Storage::BoolResponse(this, success)); } } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index d0b2714989..30a89a79d0 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -40,14 +40,16 @@ OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *stor OneDriveListDirectoryRequest::~OneDriveListDirectoryRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _listDirectoryCallback; } void OneDriveListDirectoryRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _workingRequest = nullptr; _files.clear(); _directoriesQueue.clear(); @@ -94,7 +96,8 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo 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; @@ -139,8 +142,10 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo void OneDriveListDirectoryRequest::listedDirectoryErrorCallback(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); } @@ -152,7 +157,8 @@ Common::String OneDriveListDirectoryRequest::date() const { return _date; } void OneDriveListDirectoryRequest::finishListing(Common::Array &files) { Request::finishSuccess(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); + if (_listDirectoryCallback) + (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace OneDrive diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index a26dec37a4..5612cbfd16 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -58,26 +58,29 @@ OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String user OneDriveStorage::OneDriveStorage(Common::String code) { getAccessToken( - new Common::Callback(this, &OneDriveStorage::codeFlowComplete), - new Common::Callback(this, &OneDriveStorage::codeFlowFailed), - code + new Common::Callback(this, &OneDriveStorage::codeFlowComplete), + new Common::Callback(this, &OneDriveStorage::codeFlowFailed), + code ); } OneDriveStorage::~OneDriveStorage() {} void OneDriveStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback, Common::String code) { - if (!KEY || !SECRET) loadKeyAndSecret(); + if (!KEY || !SECRET) + loadKeyAndSecret(); bool codeFlow = (code != ""); if (!codeFlow && _refreshToken == "") { warning("OneDriveStorage: no refresh token available to get new access token."); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); return; } Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); - if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); + if (errorCallback == nullptr) + errorCallback = getErrorPrintingCallback(); Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://login.live.com/oauth20_token.srf"); //TODO if (codeFlow) { request->addPostField("code=" + code); @@ -108,13 +111,15 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResp if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) { warning("Bad response, no token or user_id passed"); debug("%s", json->stringify().c_str()); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); } else { _token = result.getVal("access_token")->asString(); _uid = result.getVal("user_id")->asString(); _refreshToken = result.getVal("refresh_token")->asString(); CloudMan.save(); //ask CloudManager to save our new refreshToken - if (callback) (*callback)(BoolResponse(nullptr, true)); + if (callback) + (*callback)(BoolResponse(nullptr, true)); } delete json; } @@ -174,8 +179,10 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo } Common::String username = email; - if (username == "") username = name; - if (username == "") username = uid; + if (username == "") + username = name; + if (username == "") + username = uid; CloudMan.setStorageUsername(kStorageOneDriveId, username); if (outerCallback) { @@ -189,7 +196,8 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { if (!response.value) { warning("fileInfoCallback: NULL"); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); + if (outerCallback) + (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); return; } @@ -204,7 +212,8 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out } else { warning("downloadUrl not found in passed JSON"); debug("%s", response.value->stringify().c_str()); - if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); + if (outerCallback) + (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); } delete response.value; } @@ -226,7 +235,8 @@ Networking::Request *OneDriveStorage::streamFileById(Common::String path, Networ } Networking::Request *OneDriveStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); return addRequest(new OneDriveCreateDirectoryRequest(this, path, callback, errorCallback)); } diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 3e429f1ef8..f7597599c7 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -92,7 +92,8 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { irrecoverable = false; } - if (code == "unauthenticated") irrecoverable = false; + if (code == "unauthenticated") + irrecoverable = false; if (irrecoverable) { finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpResponseCode)); diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index a22dbf06a3..331800a381 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -41,14 +41,16 @@ OneDriveUploadRequest::OneDriveUploadRequest(OneDriveStorage *storage, Common::S OneDriveUploadRequest::~OneDriveUploadRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _contentsStream; delete _uploadCallback; } void OneDriveUploadRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); if (_contentsStream == nullptr) { warning("OneDriveUploadRequest: cannot restart because no stream given"); finishError(Networking::ErrorResponse(this, false, true, "No stream given", -1)); @@ -97,9 +99,9 @@ void OneDriveUploadRequest::uploadNextPart() { uint32 size = _contentsStream->read(buffer, UPLOAD_PER_ONE_REQUEST); request->setBuffer(buffer, size); - if (_uploadUrl != "") + if (_uploadUrl != "") { request->addHeader(Common::String::format("Content-Range: bytes %u-%u/%u", oldPos, _contentsStream->pos() - 1, _contentsStream->size())); - else if (_contentsStream->size() == 0) { + } else if (_contentsStream->size() == 0) { warning("\"Sorry, OneDrive can't upload empty files\""); finishUpload(StorageFile(_savePath, 0, 0, false)); delete request; @@ -111,7 +113,8 @@ void OneDriveUploadRequest::uploadNextPart() { void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; Networking::ErrorResponse error(this, false, true, "", -1); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -164,7 +167,8 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon void OneDriveUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; finishError(error); } @@ -174,7 +178,8 @@ void OneDriveUploadRequest::restart() { start(); } void OneDriveUploadRequest::finishUpload(StorageFile file) { Request::finishSuccess(); - if (_uploadCallback) (*_uploadCallback)(Storage::UploadResponse(this, file)); + if (_uploadCallback) + (*_uploadCallback)(Storage::UploadResponse(this, file)); } } // End of namespace OneDrive diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index e3b3aa2400..7776804579 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -41,14 +41,16 @@ SavesSyncRequest::SavesSyncRequest(Storage *storage, Storage::BoolCallback callb SavesSyncRequest::~SavesSyncRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _boolCallback; } void SavesSyncRequest::start() { //cleanup _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _currentDownloadingFile = StorageFile(); _currentUploadingFile = ""; _filesToDownload.clear(); @@ -62,7 +64,8 @@ void SavesSyncRequest::start() { //list saves directory Common::String dir = _storage->savesDirectoryPath(); - if (dir.lastChar() == '/') dir.deleteLastChar(); + if (dir.lastChar() == '/') + dir.deleteLastChar(); _workingRequest = _storage->listDirectory( dir, new Common::Callback(this, &SavesSyncRequest::directoryListedCallback), @@ -73,7 +76,8 @@ void SavesSyncRequest::start() { void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; if (response.request) _date = response.request->date(); @@ -87,14 +91,16 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re uint64 totalSize = 0; for (uint32 i = 0; i < remoteFiles.size(); ++i) { StorageFile &file = remoteFiles[i]; - if (file.isDirectory()) continue; + if (file.isDirectory()) + continue; totalSize += file.size(); - if (file.name() == DefaultSaveFileManager::TIMESTAMPS_FILENAME) continue; + if (file.name() == DefaultSaveFileManager::TIMESTAMPS_FILENAME) + continue; Common::String name = file.name(); - if (!_localFilesTimestamps.contains(name)) + if (!_localFilesTimestamps.contains(name)) { _filesToDownload.push_back(file); - else { + } else { localFileNotAvailableInCloud[name] = false; if (_localFilesTimestamps[name] == file.timestamp()) @@ -113,8 +119,10 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re //upload files which are unavailable in cloud for (Common::HashMap::iterator i = localFileNotAvailableInCloud.begin(); i != localFileNotAvailableInCloud.end(); ++i) { - if (i->_key == DefaultSaveFileManager::TIMESTAMPS_FILENAME) continue; - if (i->_value) _filesToUpload.push_back(i->_key); + if (i->_key == DefaultSaveFileManager::TIMESTAMPS_FILENAME) + continue; + if (i->_value) + _filesToUpload.push_back(i->_key); } debug(9, "\ndownload files:"); @@ -133,7 +141,8 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; bool irrecoverable = error.interrupted || error.failed; if (error.failed) { @@ -179,19 +188,22 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er //we're lucky - user just lacks his "/cloud/" folder - let's create one Common::String dir = _storage->savesDirectoryPath(); - if (dir.lastChar() == '/') dir.deleteLastChar(); + if (dir.lastChar() == '/') + dir.deleteLastChar(); debug(9, "creating %s", dir.c_str()); _workingRequest = _storage->createDirectory( dir, new Common::Callback(this, &SavesSyncRequest::directoryCreatedCallback), new Common::Callback(this, &SavesSyncRequest::directoryCreatedErrorCallback) ); - if (!_workingRequest) finishError(Networking::ErrorResponse(this)); + if (!_workingRequest) + finishError(Networking::ErrorResponse(this)); } void SavesSyncRequest::directoryCreatedCallback(Storage::BoolResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; //stop syncing if failed to create saves directory if (!response.value) { @@ -206,7 +218,8 @@ void SavesSyncRequest::directoryCreatedCallback(Storage::BoolResponse response) void SavesSyncRequest::directoryCreatedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; //stop syncing if failed to create saves directory finishError(error); @@ -232,12 +245,14 @@ void SavesSyncRequest::downloadNextFile() { new Common::Callback(this, &SavesSyncRequest::fileDownloadedCallback), new Common::Callback(this, &SavesSyncRequest::fileDownloadedErrorCallback) ); - if (!_workingRequest) finishError(Networking::ErrorResponse(this)); + if (!_workingRequest) + finishError(Networking::ErrorResponse(this)); } void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; //stop syncing if download failed if (!response.value) { @@ -258,7 +273,8 @@ void SavesSyncRequest::fileDownloadedCallback(Storage::BoolResponse response) { void SavesSyncRequest::fileDownloadedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; //stop syncing if download failed finishError(error); @@ -294,7 +310,8 @@ void SavesSyncRequest::uploadNextFile() { void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; //update local timestamp for the uploaded file _localFilesTimestamps = DefaultSaveFileManager::loadTimestamps(); @@ -307,7 +324,8 @@ void SavesSyncRequest::fileUploadedCallback(Storage::UploadResponse response) { void SavesSyncRequest::fileUploadedErrorCallback(Networking::ErrorResponse error) { _workingRequest = nullptr; - if (_ignoreCallback) return; + if (_ignoreCallback) + return; //stop syncing if upload failed finishError(error); @@ -319,11 +337,13 @@ void SavesSyncRequest::restart() { start(); } double SavesSyncRequest::getDownloadingProgress() const { if (_totalFilesToHandle == 0) { - if (_state == Networking::FINISHED) return 1; //nothing to upload and download => Request ends soon + if (_state == Networking::FINISHED) + return 1; //nothing to upload and download => Request ends soon return 0; //directory not listed yet } - if (_totalFilesToHandle == _filesToUpload.size()) return 1; //nothing to download => download complete + if (_totalFilesToHandle == _filesToUpload.size()) + return 1; //nothing to download => download complete uint32 totalFilesToDownload = _totalFilesToHandle - _filesToUpload.size(); uint32 filesLeftToDownload = _filesToDownload.size() + (_currentDownloadingFile.name() != "" ? 1 : 0); @@ -332,7 +352,8 @@ double SavesSyncRequest::getDownloadingProgress() const { double SavesSyncRequest::getProgress() const { if (_totalFilesToHandle == 0) { - if (_state == Networking::FINISHED) return 1; //nothing to upload and download => Request ends soon + if (_state == Networking::FINISHED) + return 1; //nothing to upload and download => Request ends soon return 0; //directory not listed yet } @@ -363,7 +384,8 @@ void SavesSyncRequest::finishError(Networking::ErrorResponse error) { _currentDownloadingFile = StorageFile(); _filesToDownload.clear(); //delete the incomplete file - if (name != "") g_system->getSavefileManager()->removeSavefile(name); + if (name != "") + g_system->getSavefileManager()->removeSavefile(name); Request::finishError(error); } @@ -373,7 +395,8 @@ void SavesSyncRequest::finishSync(bool success) { //update last successful sync date CloudMan.setStorageLastSync(CloudMan.getStorageIndex(), _date); - if (_boolCallback) (*_boolCallback)(Storage::BoolResponse(this, success)); + if (_boolCallback) + (*_boolCallback)(Storage::BoolResponse(this, success)); } } // End of namespace Cloud diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index dc403dfb30..b085401f47 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -49,7 +49,8 @@ void Storage::printErrorResponse(Networking::ErrorResponse error) { Networking::Request *Storage::addRequest(Networking::Request *request) { _runningRequestsMutex.lock(); ++_runningRequestsCount; - if (_runningRequestsCount == 1) debug(9, "Storage is working now"); + if (_runningRequestsCount == 1) + debug(9, "Storage is working now"); _runningRequestsMutex.unlock(); return ConnMan.addRequest(request, new Common::Callback(this, &Storage::requestFinishedCallback)); } @@ -61,8 +62,10 @@ void Storage::requestFinishedCallback(Networking::Request *invalidRequestPointer if (invalidRequestPointer == _savesSyncRequest) _savesSyncRequest = nullptr; --_runningRequestsCount; - if (_syncRestartRequestsed) restartSync = true; - if (_runningRequestsCount == 0 && !restartSync) debug(9, "Storage is not working now"); + if (_syncRestartRequestsed) + restartSync = true; + if (_runningRequestsCount == 0 && !restartSync) + debug(9, "Storage is not working now"); _runningRequestsMutex.unlock(); if (restartSync) @@ -75,7 +78,8 @@ Networking::Request *Storage::upload(Common::String remotePath, Common::String l 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)); + if (errorCallback) + (*errorCallback)(Networking::ErrorResponse(nullptr, false, true, "", -1)); delete errorCallback; delete callback; delete f; @@ -116,7 +120,8 @@ Networking::Request *Storage::downloadById(Common::String remoteId, Common::Stri } Networking::Request *Storage::downloadFolder(Common::String remotePath, Common::String localPath, FileArrayCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { - if (!errorCallback) errorCallback = getErrorPrintingCallback(); + if (!errorCallback) + errorCallback = getErrorPrintingCallback(); return addRequest(new FolderDownloadRequest(this, callback, errorCallback, remotePath, localPath, recursive)); } @@ -128,8 +133,10 @@ SavesSyncRequest *Storage::syncSaves(BoolCallback callback, Networking::ErrorCal _runningRequestsMutex.unlock(); return _savesSyncRequest; } - if (!callback) callback = new Common::Callback(this, &Storage::savesSyncDefaultCallback); - if (!errorCallback) errorCallback = new Common::Callback(this, &Storage::savesSyncDefaultErrorCallback); + if (!callback) + callback = new Common::Callback(this, &Storage::savesSyncDefaultCallback); + if (!errorCallback) + errorCallback = new Common::Callback(this, &Storage::savesSyncDefaultErrorCallback); _savesSyncRequest = new SavesSyncRequest(this, callback, errorCallback); _syncRestartRequestsed = false; _runningRequestsMutex.unlock(); @@ -198,7 +205,8 @@ void Storage::savesSyncDefaultCallback(BoolResponse response) { _savesSyncRequest = nullptr; _runningRequestsMutex.unlock(); - if (!response.value) warning("SavesSyncRequest called success callback with `false` argument"); + if (!response.value) + warning("SavesSyncRequest called success callback with `false` argument"); g_system->displayMessageOnOSD(_("Saves sync complete.")); } @@ -332,4 +340,3 @@ void Storage::directoryDownloadedErrorCallback(Networking::ErrorResponse error) } } // End of namespace Cloud - diff --git a/backends/cloud/storagefile.cpp b/backends/cloud/storagefile.cpp index c1107ea23d..62d492292d 100644 --- a/backends/cloud/storagefile.cpp +++ b/backends/cloud/storagefile.cpp @@ -45,7 +45,8 @@ StorageFile::StorageFile(Common::String pth, uint32 sz, uint32 ts, bool dir) { _name.erase(0, i + 1); break; } - if (i == 0) break; + if (i == 0) + break; --i; } } -- cgit v1.2.3 From eb268cd14ff936b5afa2c39ca51acfaea51a8a90 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 22 Jul 2016 15:39:51 +0300 Subject: CLOUD: Fix warning --- backends/cloud/cloudmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/cloud') diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index a68a8720ae..826fc6103d 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -117,7 +117,7 @@ void CloudManager::save() { Common::String name = getStorageConfigName(i); ConfMan.set(kStoragePrefix + name + "_username", _storages[i].username, ConfMan.kCloudDomain); ConfMan.set(kStoragePrefix + name + "_lastSync", _storages[i].lastSyncDate, ConfMan.kCloudDomain); - ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%llu", _storages[i].usedBytes), ConfMan.kCloudDomain); + ConfMan.set(kStoragePrefix + name + "_usedBytes", Common::String::format("%lu", _storages[i].usedBytes), ConfMan.kCloudDomain); } ConfMan.set("current_storage", Common::String::format("%u", _currentStorageIndex), ConfMan.kCloudDomain); -- cgit v1.2.3 From f95073f0084b3fae3e2cbf14fd98135c37eabbdf Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 22 Jul 2016 15:55:40 +0300 Subject: CLOUD: JANITORIAL: More whitespace fixes --- backends/cloud/box/boxlistdirectorybyidrequest.cpp | 45 ++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp index 776ee71d64..697ca48db7 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.cpp +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -43,13 +43,15 @@ BoxListDirectoryByIdRequest::BoxListDirectoryByIdRequest(BoxStorage *storage, Co BoxListDirectoryByIdRequest::~BoxListDirectoryByIdRequest() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); delete _listDirectoryCallback; } void BoxListDirectoryByIdRequest::start() { _ignoreCallback = true; - if (_workingRequest) _workingRequest->finish(); + if (_workingRequest) + _workingRequest->finish(); _files.clear(); _ignoreCallback = false; @@ -74,8 +76,10 @@ void BoxListDirectoryByIdRequest::makeRequest(uint32 offset) { void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) return; - if (response.request) _date = response.request->date(); + if (_ignoreCallback) + return; + if (response.request) + _date = response.request->date(); Networking::ErrorResponse error(this); Networking::CurlJsonRequest *rq = (Networking::CurlJsonRequest *)response.request; @@ -125,16 +129,22 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp Common::JSONArray items = responseObject.getVal("entries")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { - if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "BoxListDirectoryByIdRequest")) + continue; Common::JSONObject item = items[i]->asObject(); - if (!Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxListDirectoryByIdRequest")) continue; - if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxListDirectoryByIdRequest")) continue; - if (!Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxListDirectoryByIdRequest")) continue; - if (!Networking::CurlJsonRequest::jsonContainsString(item, "modified_at", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxListDirectoryByIdRequest")) + continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxListDirectoryByIdRequest")) + continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxListDirectoryByIdRequest")) + continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "modified_at", "BoxListDirectoryByIdRequest")) + continue; if (!Networking::CurlJsonRequest::jsonContainsString(item, "size", "BoxListDirectoryByIdRequest") && - !Networking::CurlJsonRequest::jsonContainsIntegerNumber(item, "size", "BoxListDirectoryByIdRequest")) continue; + !Networking::CurlJsonRequest::jsonContainsIntegerNumber(item, "size", "BoxListDirectoryByIdRequest")) + continue; Common::String id = item.getVal("id")->asString(); Common::String name = item.getVal("name")->asString(); @@ -162,16 +172,20 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp received += responseObject.getVal("limit")->asIntegerNumber(); bool hasMore = (received < totalCount); - if (hasMore) makeRequest(received); - else finishListing(_files); + if (hasMore) + makeRequest(received); + else + finishListing(_files); delete json; } void BoxListDirectoryByIdRequest::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); } @@ -183,7 +197,8 @@ Common::String BoxListDirectoryByIdRequest::date() const { return _date; } void BoxListDirectoryByIdRequest::finishListing(Common::Array &files) { Request::finishSuccess(); - if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); + if (_listDirectoryCallback) + (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace Box -- 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/box/boxlistdirectorybyidrequest.cpp | 47 +++++++++------------- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 4 +- .../googledrivelistdirectorybyidrequest.cpp | 4 +- .../onedrive/onedrivelistdirectoryrequest.cpp | 33 +++++++++++++-- 4 files changed, 54 insertions(+), 34 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp index 697ca48db7..0171b52a0f 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.cpp +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -43,15 +43,13 @@ BoxListDirectoryByIdRequest::BoxListDirectoryByIdRequest(BoxStorage *storage, Co BoxListDirectoryByIdRequest::~BoxListDirectoryByIdRequest() { _ignoreCallback = true; - if (_workingRequest) - _workingRequest->finish(); + if (_workingRequest) _workingRequest->finish(); delete _listDirectoryCallback; } void BoxListDirectoryByIdRequest::start() { _ignoreCallback = true; - if (_workingRequest) - _workingRequest->finish(); + if (_workingRequest) _workingRequest->finish(); _files.clear(); _ignoreCallback = false; @@ -76,8 +74,11 @@ void BoxListDirectoryByIdRequest::makeRequest(uint32 offset) { void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) + if (_ignoreCallback) { + delete response.value; return; + } + if (response.request) _date = response.request->date(); @@ -103,7 +104,7 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp Common::JSONObject responseObject = json->asObject(); //debug(9, "%s", json->stringify(true).c_str()); - //TODO: check that error is returned the right way + //TODO: handle error messages passed as JSON /* if (responseObject.contains("error") || responseObject.contains("error_summary")) { warning("Box returned error: %s", responseObject.getVal("error_summary")->asString().c_str()); @@ -129,22 +130,15 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp Common::JSONArray items = responseObject.getVal("entries")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { - if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "BoxListDirectoryByIdRequest")) - continue; + if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "BoxListDirectoryByIdRequest")) continue; Common::JSONObject item = items[i]->asObject(); - if (!Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxListDirectoryByIdRequest")) - continue; - if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxListDirectoryByIdRequest")) - continue; - if (!Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxListDirectoryByIdRequest")) - continue; - if (!Networking::CurlJsonRequest::jsonContainsString(item, "modified_at", "BoxListDirectoryByIdRequest")) - continue; - if (!Networking::CurlJsonRequest::jsonContainsString(item, "size", "BoxListDirectoryByIdRequest") && - !Networking::CurlJsonRequest::jsonContainsIntegerNumber(item, "size", "BoxListDirectoryByIdRequest")) - continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "modified_at", "BoxListDirectoryByIdRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsStringOrIntegerNumber(item, "size", "BoxListDirectoryByIdRequest")) continue; Common::String id = item.getVal("id")->asString(); Common::String name = item.getVal("name")->asString(); @@ -172,20 +166,16 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp received += responseObject.getVal("limit")->asIntegerNumber(); bool hasMore = (received < totalCount); - if (hasMore) - makeRequest(received); - else - finishListing(_files); + if (hasMore) makeRequest(received); + else finishListing(_files); delete json; } void BoxListDirectoryByIdRequest::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); } @@ -197,8 +187,7 @@ Common::String BoxListDirectoryByIdRequest::date() const { return _date; } void BoxListDirectoryByIdRequest::finishListing(Common::Array &files) { Request::finishSuccess(); - if (_listDirectoryCallback) - (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); + if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files)); } } // End of namespace Box 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(); diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index d2e94a7196..5597d78704 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -72,8 +72,10 @@ void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) { _workingRequest = nullptr; - if (_ignoreCallback) + if (_ignoreCallback) { + delete response.value; return; + } if (response.request) _date = response.request->date(); diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index 30a89a79d0..069d6fdfb1 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -104,20 +104,40 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - if (!json) { - error.failed = true; + 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 object = json->asObject(); - //TODO: check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults + //check that ALL keys exist AND HAVE RIGHT TYPE to avoid segfaults + if (!Networking::CurlJsonRequest::jsonContainsArray(object, "value", "OneDriveListDirectoryRequest")) { + error.response = "\"value\" not found or that's not an array!"; + finishError(error); + delete json; + return; + } Common::JSONArray items = object.getVal("value")->asArray(); for (uint32 i = 0; i < items.size(); ++i) { + if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "OneDriveListDirectoryRequest")) continue; + Common::JSONObject item = items[i]->asObject(); + if (!Networking::CurlJsonRequest::jsonContainsAttribute(item, "folder", "OneDriveListDirectoryRequest", true)) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "OneDriveListDirectoryRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsIntegerNumber(item, "size", "OneDriveListDirectoryRequest")) continue; + if (!Networking::CurlJsonRequest::jsonContainsString(item, "lastModifiedDateTime", "OneDriveListDirectoryRequest")) continue; + Common::String path = _currentDirectory + item.getVal("name")->asString(); bool isDirectory = item.contains("folder"); uint32 size = item.getVal("size")->asIntegerNumber(); @@ -132,6 +152,13 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo bool hasMore = object.contains("@odata.nextLink"); if (hasMore) { + if (!Networking::CurlJsonRequest::jsonContainsString(object, "@odata.nextLink", "OneDriveListDirectoryRequest")) { + error.response = "\"@odata.nextLink\" is not a string!"; + finishError(error); + delete json; + return; + } + makeRequest(object.getVal("@odata.nextLink")->asString()); } else { listNextDirectory(); -- 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 --- backends/cloud/box/boxlistdirectorybyidrequest.cpp | 3 +- backends/cloud/box/boxstorage.cpp | 13 +- backends/cloud/box/boxuploadrequest.cpp | 4 +- .../dropbox/dropboxcreatedirectoryrequest.cpp | 4 +- backends/cloud/dropbox/dropboxinforequest.cpp | 7 +- .../cloud/dropbox/dropboxlistdirectoryrequest.cpp | 133 +++++++++++++++------ backends/cloud/dropbox/dropboxstorage.cpp | 7 +- backends/cloud/dropbox/dropboxuploadrequest.cpp | 7 +- .../googledrivelistdirectorybyidrequest.cpp | 6 +- backends/cloud/googledrive/googledrivestorage.cpp | 13 +- .../cloud/googledrive/googledriveuploadrequest.cpp | 4 +- .../onedrive/onedrivecreatedirectoryrequest.cpp | 4 +- .../onedrive/onedrivelistdirectoryrequest.cpp | 5 +- backends/cloud/onedrive/onedrivestorage.cpp | 10 +- backends/cloud/onedrive/onedriveuploadrequest.cpp | 7 +- 15 files changed, 160 insertions(+), 67 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxlistdirectorybyidrequest.cpp b/backends/cloud/box/boxlistdirectorybyidrequest.cpp index 0171b52a0f..c013f1eb2a 100644 --- a/backends/cloud/box/boxlistdirectorybyidrequest.cpp +++ b/backends/cloud/box/boxlistdirectorybyidrequest.cpp @@ -34,6 +34,7 @@ namespace Cloud { namespace Box { #define BOX_LIST_DIRECTORY_LIMIT 1000 +#define BOX_FOLDERS_API_LINK "https://api.box.com/2.0/folders/%s/items?offset=%u&limit=%u&fields=%s" BoxListDirectoryByIdRequest::BoxListDirectoryByIdRequest(BoxStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _requestedId(id), _storage(storage), _listDirectoryCallback(cb), @@ -58,7 +59,7 @@ void BoxListDirectoryByIdRequest::start() { void BoxListDirectoryByIdRequest::makeRequest(uint32 offset) { Common::String url = Common::String::format( - "https://api.box.com/2.0/folders/%s/items?offset=%u&limit=%u&fields=%s", + BOX_FOLDERS_API_LINK, _requestedId.c_str(), offset, BOX_LIST_DIRECTORY_LIMIT, diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 2b2be70e55..401ec6a115 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -37,6 +37,11 @@ namespace Cloud { namespace Box { +#define BOX_OAUTH2_TOKEN "https://api.box.com/oauth2/token" +#define BOX_API_FOLDERS "https://api.box.com/2.0/folders" +#define BOX_API_FILES_CONTENT "https://api.box.com/2.0/files/%s/content" +#define BOX_API_USERS_ME "https://api.box.com/2.0/users/me" + char *BoxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth char *BoxStorage::SECRET = nullptr; //TODO: hide these secrets somehow @@ -80,7 +85,7 @@ void BoxStorage::getAccessToken(BoolCallback callback, Networking::ErrorCallback if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.box.com/oauth2/token"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, BOX_OAUTH2_TOKEN); if (codeFlow) { request->addPostField("grant_type=authorization_code"); request->addPostField("code=" + code); @@ -223,7 +228,7 @@ Networking::Request *BoxStorage::createDirectoryWithParentId(Common::String pare if (!errorCallback) errorCallback = getErrorPrintingCallback(); - Common::String url = "https://api.box.com/2.0/folders"; + Common::String url = BOX_API_FOLDERS; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::createDirectoryInnerCallback, callback); Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + accessToken()); @@ -263,7 +268,7 @@ bool BoxStorage::uploadStreamSupported() { Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { if (callback) { - Common::String url = "https://api.box.com/2.0/files/" + id + "/content"; + Common::String url = Common::String::format(BOX_API_FILES_CONTENT, id.c_str()); Common::String header = "Authorization: Bearer " + _token; curl_slist *headersList = curl_slist_append(nullptr, header.c_str()); Networking::NetworkReadStream *stream = new Networking::NetworkReadStream(url.c_str(), headersList, ""); @@ -276,7 +281,7 @@ Networking::Request *BoxStorage::streamFileById(Common::String id, Networking::N Networking::Request *BoxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BoxStorage::infoInnerCallback, callback); - Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.box.com/2.0/users/me"); + Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, BOX_API_USERS_ME); request->addHeader("Authorization: Bearer " + _token); return addRequest(request); } diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index c308ddb429..29034c479f 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -33,6 +33,8 @@ namespace Cloud { namespace Box { +#define BOX_API_FILES "https://upload.box.com/api/2.0/files" + BoxUploadRequest::BoxUploadRequest(BoxStorage *storage, Common::String path, Common::String localPath, Storage::UploadCallback callback, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _storage(storage), _savePath(path), _localPath(localPath), _uploadCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { @@ -102,7 +104,7 @@ void BoxUploadRequest::upload() { } } - Common::String url = "https://upload.box.com/api/2.0/files"; + Common::String url = BOX_API_FILES; if (_resolvedId != "") url += "/" + _resolvedId; url += "/content"; diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index 968fb4550a..ad9b0fcc0d 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -30,6 +30,8 @@ namespace Cloud { namespace Dropbox { +#define DROPBOX_API_CREATE_FOLDER "https://api.dropboxapi.com/2/files/create_folder" + DropboxCreateDirectoryRequest::DropboxCreateDirectoryRequest(Common::String token, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _token(token), _path(path), _boolCallback(cb), _workingRequest(nullptr), _ignoreCallback(false) { @@ -51,7 +53,7 @@ void DropboxCreateDirectoryRequest::start() { Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxCreateDirectoryRequest::responseCallback); Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxCreateDirectoryRequest::errorCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/2/files/create_folder"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, DROPBOX_API_CREATE_FOLDER); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); diff --git a/backends/cloud/dropbox/dropboxinforequest.cpp b/backends/cloud/dropbox/dropboxinforequest.cpp index 37700eaf55..207c20271a 100644 --- a/backends/cloud/dropbox/dropboxinforequest.cpp +++ b/backends/cloud/dropbox/dropboxinforequest.cpp @@ -31,6 +31,9 @@ namespace Cloud { namespace Dropbox { +#define DROPBOX_API_GET_CURRENT_ACCOUNT "https://api.dropboxapi.com/2/users/get_current_account" +#define DROPBOX_API_GET_SPACE_USAGE "https://api.dropboxapi.com/2/users/get_space_usage" + DropboxInfoRequest::DropboxInfoRequest(Common::String token, Storage::StorageInfoCallback cb, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _token(token), _infoCallback(cb), _workingRequest(nullptr), _ignoreCallback(false) { @@ -52,7 +55,7 @@ void DropboxInfoRequest::start() { Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxInfoRequest::userResponseCallback); Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxInfoRequest::errorCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/2/users/get_current_account"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, DROPBOX_API_GET_CURRENT_ACCOUNT); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); request->addPostField("null"); //use POST @@ -90,7 +93,7 @@ void DropboxInfoRequest::userResponseCallback(Networking::JsonResponse response) Networking::JsonCallback innerCallback = new Common::Callback(this, &DropboxInfoRequest::quotaResponseCallback); Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxInfoRequest::errorCallback); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://api.dropboxapi.com/2/users/get_space_usage"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, DROPBOX_API_GET_SPACE_USAGE); request->addHeader("Authorization: Bearer " + _token); request->addHeader("Content-Type: application/json"); request->addPostField("null"); //use POST 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; diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index cd1dff8afb..20f8a68327 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -37,6 +37,9 @@ namespace Cloud { namespace Dropbox { +#define DROPBOX_OAUTH2_TOKEN "https://api.dropboxapi.com/oauth2/token" +#define DROPBOX_API_FILES_DOWNLOAD "https://content.dropboxapi.com/2/files/download" + char *DropboxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth char *DropboxStorage::SECRET = nullptr; //TODO: hide these secrets somehow @@ -65,7 +68,7 @@ void DropboxStorage::getAccessToken(Common::String code) { loadKeyAndSecret(); Networking::JsonCallback callback = new Common::Callback(this, &DropboxStorage::codeFlowComplete); Networking::ErrorCallback errorCallback = new Common::Callback(this, &DropboxStorage::codeFlowFailed); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, errorCallback, "https://api.dropboxapi.com/oauth2/token"); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, errorCallback, DROPBOX_OAUTH2_TOKEN); request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); request->addPostField("client_id=" + Common::String(KEY)); @@ -129,7 +132,7 @@ Networking::Request *DropboxStorage::streamFileById(Common::String path, Network jsonRequestParameters.setVal("path", new Common::JSONValue(path)); Common::JSONValue value(jsonRequestParameters); - Networking::CurlRequest *request = new Networking::CurlRequest(nullptr, nullptr, "https://content.dropboxapi.com/2/files/download"); //TODO: is it right? + Networking::CurlRequest *request = new Networking::CurlRequest(nullptr, nullptr, DROPBOX_API_FILES_DOWNLOAD); //TODO: is it OK to pass no callbacks? request->addHeader("Authorization: Bearer " + _token); request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value)); request->addHeader("Content-Type: "); //required to be empty (as we do POST, it's usually app/form-url-encoded) diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index 03c3fbc244..f129eaa94d 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -32,6 +32,9 @@ namespace Cloud { namespace Dropbox { +#define DROPBOX_API_FILES_UPLOAD "https://content.dropboxapi.com/2/files/upload" +#define DROPBOX_API_FILES_UPLOAD_SESSION "https://content.dropboxapi.com/2/files/upload_session/" + DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _token(token), _savePath(path), _contentsStream(contents), _uploadCallback(callback), _workingRequest(nullptr), _ignoreCallback(false) { @@ -68,12 +71,12 @@ void DropboxUploadRequest::start() { void DropboxUploadRequest::uploadNextPart() { const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; - Common::String url = "https://content.dropboxapi.com/2/files/upload_session/"; + Common::String url = DROPBOX_API_FILES_UPLOAD_SESSION; Common::JSONObject jsonRequestParameters; if (_contentsStream->pos() == 0 || _sessionId == "") { if ((uint32)_contentsStream->size() <= UPLOAD_PER_ONE_REQUEST) { - url = "https://content.dropboxapi.com/2/files/upload"; + url = DROPBOX_API_FILES_UPLOAD; jsonRequestParameters.setVal("path", new Common::JSONValue(_savePath)); jsonRequestParameters.setVal("mode", new Common::JSONValue("overwrite")); jsonRequestParameters.setVal("autorename", new Common::JSONValue(false)); diff --git a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp index 5597d78704..52611126a0 100644 --- a/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp +++ b/backends/cloud/googledrive/googledrivelistdirectorybyidrequest.cpp @@ -33,6 +33,9 @@ namespace Cloud { namespace GoogleDrive { +#define GOOGLEDRIVE_API_FILES "https://www.googleapis.com/drive/v3/files?spaces=drive&fields=files%28id,mimeType,modifiedTime,name,size%29,nextPageToken&orderBy=folder,name" +//files(id,mimeType,modifiedTime,name,size),nextPageToken + GoogleDriveListDirectoryByIdRequest::GoogleDriveListDirectoryByIdRequest(GoogleDriveStorage *storage, Common::String id, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _requestedId(id), _storage(storage), _listDirectoryCallback(cb), _workingRequest(nullptr), _ignoreCallback(false) { @@ -57,8 +60,7 @@ void GoogleDriveListDirectoryByIdRequest::start() { } void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken) { - Common::String url = "https://www.googleapis.com/drive/v3/files?spaces=drive&fields=files%28id,mimeType,modifiedTime,name,size%29,nextPageToken&orderBy=folder,name"; - //files(id,mimeType,modifiedTime,name,size),nextPageToken + Common::String url = GOOGLEDRIVE_API_FILES; if (pageToken != "") url += "&pageToken=" + pageToken; url += "&q=%27" + _requestedId + "%27+in+parents"; diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 22013210d3..af19019a1e 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -37,6 +37,11 @@ namespace Cloud { namespace GoogleDrive { +#define GOOGLEDRIVE_OAUTH2_TOKEN "https://accounts.google.com/o/oauth2/token" +#define GOOGLEDRIVE_API_FILES_ALT_MEDIA "https://www.googleapis.com/drive/v3/files/%s?alt=media" +#define GOOGLEDRIVE_API_FILES "https://www.googleapis.com/drive/v3/files" +#define GOOGLEDRIVE_API_ABOUT "https://www.googleapis.com/drive/v3/about?fields=storageQuota,user" + char *GoogleDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth char *GoogleDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow @@ -79,7 +84,7 @@ void GoogleDriveStorage::getAccessToken(BoolCallback callback, Networking::Error Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::tokenRefreshed, callback); if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://accounts.google.com/o/oauth2/token"); //TODO + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, GOOGLEDRIVE_OAUTH2_TOKEN); //TODO if (codeFlow) { request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); @@ -224,7 +229,7 @@ Networking::Request *GoogleDriveStorage::upload(Common::String path, Common::See Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) { if (callback) { - Common::String url = "https://www.googleapis.com/drive/v3/files/" + ConnMan.urlEncode(id) + "?alt=media"; + Common::String url = Common::String::format(GOOGLEDRIVE_API_FILES_ALT_MEDIA, ConnMan.urlEncode(id).c_str()); Common::String header = "Authorization: Bearer " + _token; curl_slist *headersList = curl_slist_append(nullptr, header.c_str()); Networking::NetworkReadStream *stream = new Networking::NetworkReadStream(url.c_str(), headersList, ""); @@ -246,7 +251,7 @@ Networking::Request *GoogleDriveStorage::createDirectoryWithParentId(Common::Str if (!errorCallback) errorCallback = getErrorPrintingCallback(); - Common::String url = "https://www.googleapis.com/drive/v3/files"; + Common::String url = GOOGLEDRIVE_API_FILES; Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::createDirectoryInnerCallback, callback); Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + accessToken()); @@ -270,7 +275,7 @@ Networking::Request *GoogleDriveStorage::info(StorageInfoCallback callback, Netw if (!callback) callback = new Common::Callback(this, &GoogleDriveStorage::printInfo); Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::infoInnerCallback, callback); - Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, "https://www.googleapis.com/drive/v3/about?fields=storageQuota,user"); + Networking::CurlJsonRequest *request = new GoogleDriveTokenRefresher(this, innerCallback, errorCallback, GOOGLEDRIVE_API_ABOUT); request->addHeader("Authorization: Bearer " + _token); return addRequest(request); } diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index 3cdee26dbe..bd9d8790ed 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -33,6 +33,8 @@ namespace Cloud { namespace GoogleDrive { +#define GOOGLEDRIVE_API_FILES "https://www.googleapis.com/upload/drive/v3/files" + GoogleDriveUploadRequest::GoogleDriveUploadRequest(GoogleDriveStorage *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) { @@ -111,7 +113,7 @@ void GoogleDriveUploadRequest::startUpload() { } } - Common::String url = "https://www.googleapis.com/upload/drive/v3/files"; + Common::String url = GOOGLEDRIVE_API_FILES; if (_resolvedId != "") url += "/" + ConnMan.urlEncode(_resolvedId); url += "?uploadType=resumable&fields=id,mimeType,modifiedTime,name,size"; diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index bd612d64a8..a31fd025ac 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -31,6 +31,8 @@ namespace Cloud { namespace OneDrive { +#define ONEDRIVE_API_SPECIAL_APPROOT "https://api.onedrive.com/v1.0/drive/special/approot" + OneDriveCreateDirectoryRequest::OneDriveCreateDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb): Networking::Request(nullptr, ecb), _storage(storage), _path(path), _boolCallback(cb), _workingRequest(nullptr), _ignoreCallback(false) { @@ -65,7 +67,7 @@ void OneDriveCreateDirectoryRequest::start() { } } - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot"; + Common::String url = ONEDRIVE_API_SPECIAL_APPROOT; if (parent != "") url += ":/" + ConnMan.urlEncode(parent) + ":"; url += "/children"; diff --git a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp index 069d6fdfb1..a247a9f234 100644 --- a/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivelistdirectoryrequest.cpp @@ -31,6 +31,8 @@ namespace Cloud { namespace OneDrive { +#define ONEDRIVE_API_SPECIAL_APPROOT_CHILDREN "https://api.onedrive.com/v1.0/drive/special/approot:/%s:/children" + OneDriveListDirectoryRequest::OneDriveListDirectoryRequest(OneDriveStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive): Networking::Request(nullptr, ecb), _requestedPath(path), _requestedRecursive(recursive), _storage(storage), _listDirectoryCallback(cb), @@ -74,8 +76,7 @@ void OneDriveListDirectoryRequest::listNextDirectory() { Common::String dir = _currentDirectory; dir.deleteLastChar(); - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(dir); - url += ":/children"; + Common::String url = Common::String::format(ONEDRIVE_API_SPECIAL_APPROOT_CHILDREN, ConnMan.urlEncode(dir).c_str()); makeRequest(url); } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 5612cbfd16..af5d9f10ba 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -38,6 +38,10 @@ namespace Cloud { namespace OneDrive { +#define ONEDRIVE_OAUTH2_TOKEN "https://login.live.com/oauth20_token.srf" +#define ONEDRIVE_API_SPECIAL_APPROOT_ID "https://api.onedrive.com/v1.0/drive/special/approot:/" +#define ONEDRIVE_API_SPECIAL_APPROOT "https://api.onedrive.com/v1.0/drive/special/approot" + char *OneDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth char *OneDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow @@ -81,7 +85,7 @@ void OneDriveStorage::getAccessToken(BoolCallback callback, Networking::ErrorCal Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::tokenRefreshed, callback); if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, "https://login.live.com/oauth20_token.srf"); //TODO + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, ONEDRIVE_OAUTH2_TOKEN); if (codeFlow) { request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); @@ -227,7 +231,7 @@ Networking::Request *OneDriveStorage::upload(Common::String path, Common::Seekab } Networking::Request *OneDriveStorage::streamFileById(Common::String path, Networking::NetworkReadStreamCallback outerCallback, Networking::ErrorCallback errorCallback) { - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(path); + Common::String url = ONEDRIVE_API_SPECIAL_APPROOT_ID + ConnMan.urlEncode(path); Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::fileInfoCallback, outerCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, url.c_str()); request->addHeader("Authorization: Bearer " + _token); @@ -242,7 +246,7 @@ Networking::Request *OneDriveStorage::createDirectory(Common::String path, BoolC Networking::Request *OneDriveStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) { Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &OneDriveStorage::infoInnerCallback, callback); - Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, "https://api.onedrive.com/v1.0/drive/special/approot"); + Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, errorCallback, ONEDRIVE_API_SPECIAL_APPROOT); request->addHeader("Authorization: bearer " + _token); return addRequest(request); } diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 331800a381..ef1507d1f2 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -33,6 +33,9 @@ namespace Cloud { namespace OneDrive { +#define ONEDRIVE_API_SPECIAL_APPROOT_UPLOAD "https://api.onedrive.com/v1.0/drive/special/approot:/%s:/upload.createSession" +#define ONEDRIVE_API_SPECIAL_APPROOT_CONTENT "https://api.onedrive.com/v1.0/drive/special/approot:/%s:/content" + 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) { @@ -70,7 +73,7 @@ void OneDriveUploadRequest::uploadNextPart() { const uint32 UPLOAD_PER_ONE_REQUEST = 10 * 1024 * 1024; if (_uploadUrl == "" && (uint32)_contentsStream->size() > UPLOAD_PER_ONE_REQUEST) { - Common::String url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(_savePath) + ":/upload.createSession"; //folder must exist + Common::String url = Common::String::format(ONEDRIVE_API_SPECIAL_APPROOT_UPLOAD, ConnMan.urlEncode(_savePath).c_str()); //folder must exist Networking::JsonCallback callback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(this, &OneDriveUploadRequest::partUploadedErrorCallback); Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(_storage, callback, failureCallback, url.c_str()); @@ -82,7 +85,7 @@ void OneDriveUploadRequest::uploadNextPart() { Common::String url; if (_uploadUrl == "") { - url = "https://api.onedrive.com/v1.0/drive/special/approot:/" + ConnMan.urlEncode(_savePath) + ":/content"; + url = Common::String::format(ONEDRIVE_API_SPECIAL_APPROOT_CONTENT, ConnMan.urlEncode(_savePath).c_str()); } else { url = _uploadUrl; } -- cgit v1.2.3 From 15c6772ff7638e104027f7b7777180e6191841fc Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 23 Jul 2016 12:52:27 +0600 Subject: ALL: Fix debug, warning and error usage Added prefixes, used debug(9). --- backends/cloud/box/boxstorage.cpp | 16 ++++++++-------- backends/cloud/box/boxtokenrefresher.cpp | 6 +++--- backends/cloud/box/boxuploadrequest.cpp | 7 ++++--- backends/cloud/downloadrequest.cpp | 4 +++- .../dropbox/dropboxcreatedirectoryrequest.cpp | 2 +- backends/cloud/dropbox/dropboxinforequest.cpp | 4 ++-- backends/cloud/dropbox/dropboxstorage.cpp | 14 +++++++------- backends/cloud/dropbox/dropboxuploadrequest.cpp | 11 +++++------ backends/cloud/folderdownloadrequest.cpp | 4 ++-- backends/cloud/googledrive/googledrivestorage.cpp | 20 ++++++++++---------- .../googledrive/googledrivetokenrefresher.cpp | 6 +++--- .../cloud/googledrive/googledriveuploadrequest.cpp | 4 ++-- backends/cloud/id/idresolveidrequest.cpp | 10 +++++----- backends/cloud/id/idstorage.cpp | 6 +++--- .../onedrive/onedrivecreatedirectoryrequest.cpp | 2 +- backends/cloud/onedrive/onedrivestorage.cpp | 22 +++++++++++----------- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 6 +++--- backends/cloud/onedrive/onedriveuploadrequest.cpp | 8 ++++---- backends/cloud/savessyncrequest.cpp | 12 ++++++------ backends/cloud/storage.cpp | 4 ++-- 20 files changed, 85 insertions(+), 83 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 401ec6a115..c2c4c6278e 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -115,8 +115,8 @@ void BoxStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse Common::JSONObject result = json->asObject(); if (!result.contains("access_token") || !result.contains("refresh_token")) { - warning("Bad response, no token passed"); - debug("%s", json->stringify().c_str()); + warning("BoxStorage: bad response, no token passed"); + debug(9, "%s", json->stringify().c_str()); if (callback) (*callback)(BoolResponse(nullptr, false)); } else { @@ -141,8 +141,8 @@ void BoxStorage::codeFlowComplete(BoolResponse response) { } void BoxStorage::codeFlowFailed(Networking::ErrorResponse error) { - debug("Box's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); - debug("%s", error.response.c_str()); + debug(9, "BoxStorage: code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug(9, "%s", error.response.c_str()); CloudMan.removeStorage(this); } @@ -158,7 +158,7 @@ Common::String BoxStorage::name() const { void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("NULL passed instead of JSON"); + warning("BoxStorage::infoInnerCallback: NULL passed instead of JSON"); delete outerCallback; return; } @@ -210,7 +210,7 @@ Networking::Request *BoxStorage::listDirectoryById(Common::String id, ListDirect void BoxStorage::createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("NULL passed instead of JSON"); + warning("BoxStorage::createDirectoryInnerCallback: NULL passed instead of JSON"); delete outerCallback; return; } @@ -292,12 +292,12 @@ BoxStorage *BoxStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { - warning("No access_token found"); + warning("BoxStorage: no access_token found"); return nullptr; } if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { - warning("No refresh_token found"); + warning("BoxStorage: no refresh_token found"); return nullptr; } diff --git a/backends/cloud/box/boxtokenrefresher.cpp b/backends/cloud/box/boxtokenrefresher.cpp index 65964f3010..c798b97343 100644 --- a/backends/cloud/box/boxtokenrefresher.cpp +++ b/backends/cloud/box/boxtokenrefresher.cpp @@ -69,7 +69,7 @@ void BoxTokenRefresher::finishJson(Common::JSONValue *json) { long httpCode = -1; if (_stream) { httpCode = _stream->httpResponseCode(); - debug(9, "code %ld", httpCode); + debug(9, "BoxTokenRefresher: code %ld", httpCode); } bool irrecoverable = true; @@ -77,12 +77,12 @@ void BoxTokenRefresher::finishJson(Common::JSONValue *json) { Common::String code, message; if (result.contains("code")) { code = result.getVal("code")->asString(); - debug(9, "code = %s", code.c_str()); + debug(9, "BoxTokenRefresher: code = %s", code.c_str()); } if (result.contains("message")) { message = result.getVal("message")->asString(); - debug(9, "message = %s", message.c_str()); + debug(9, "BoxTokenRefresher: message = %s", message.c_str()); } //TODO: decide when token refreshment will help diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index 29034c479f..f68ba6a580 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -143,8 +143,9 @@ void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { } if (error.httpResponseCode != 200 && error.httpResponseCode != 201) - warning("looks like an error"); + warning("BoxUploadRequest: looks like an error (bad HTTP code)"); + //TODO: add more JSON warnings there Common::JSONValue *json = response.value; if (json) { if (json->isObject()) { @@ -188,10 +189,10 @@ void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { */ } - warning("no file info to return"); + warning("BoxUploadRequest: no file info to return"); finishUpload(StorageFile(_savePath, 0, 0, false)); } else { - warning("null, not json"); + warning("BoxUploadRequest: null, not json"); finishError(error); } diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp index f706ed64f4..e28670fc7b 100644 --- a/backends/cloud/downloadrequest.cpp +++ b/backends/cloud/downloadrequest.cpp @@ -99,8 +99,10 @@ void DownloadRequest::handle() { if (_remoteFileStream->eos()) { if (_remoteFileStream->httpResponseCode() != 200) { - warning("HTTP response code is not 200 OK (it's %ld)", _remoteFileStream->httpResponseCode()); + warning("DownloadRequest: HTTP response code is not 200 OK (it's %ld)", _remoteFileStream->httpResponseCode()); //TODO: do something about it actually + // the problem is file's already downloaded, stream is over + // so we can't return error message anymore } finishDownload(_remoteFileStream->httpResponseCode() == 200); diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index ad9b0fcc0d..6cc6801bc0 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -80,7 +80,7 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); if (!json) { - warning("NULL passed instead of JSON"); + warning("DropboxCreateDirectoryRequest: NULL passed instead of JSON"); finishError(error); return; } diff --git a/backends/cloud/dropbox/dropboxinforequest.cpp b/backends/cloud/dropbox/dropboxinforequest.cpp index 207c20271a..c5cbb9d917 100644 --- a/backends/cloud/dropbox/dropboxinforequest.cpp +++ b/backends/cloud/dropbox/dropboxinforequest.cpp @@ -77,7 +77,7 @@ void DropboxInfoRequest::userResponseCallback(Networking::JsonResponse response) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); if (!json) { - warning("NULL passed instead of JSON"); + warning("DropboxInfoRequest: NULL passed instead of JSON"); finishError(error); return; } @@ -115,7 +115,7 @@ void DropboxInfoRequest::quotaResponseCallback(Networking::JsonResponse response error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); if (!json) { - warning("NULL passed instead of JSON"); + warning("DropboxInfoRequest: NULL passed instead of JSON"); finishError(error); return; } diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 20f8a68327..6fd1f9d2fd 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -86,8 +86,8 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { if (json) { Common::JSONObject result = json->asObject(); if (!result.contains("access_token") || !result.contains("uid")) { - warning("%s", json->stringify(true).c_str()); - warning("Bad response, no token/uid passed"); + warning("DropboxStorage: bad response, no token/uid passed"); + debug(9, "%s", json->stringify(true).c_str()); CloudMan.removeStorage(this); } else { _token = result.getVal("access_token")->asString(); @@ -99,14 +99,14 @@ void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { delete json; } else { - debug("DropboxStorage::codeFlowComplete: got NULL instead of JSON!"); + debug(9, "DropboxStorage::codeFlowComplete: got NULL instead of JSON!"); CloudMan.removeStorage(this); } } void DropboxStorage::codeFlowFailed(Networking::ErrorResponse error) { - debug("Dropbox's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); - debug("%s", error.response.c_str()); + debug(9, "DropboxStorage: code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug(9, "%s", error.response.c_str()); CloudMan.removeStorage(this); } @@ -161,12 +161,12 @@ DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { - warning("No access_token found"); + warning("DropboxStorage: no access_token found"); return nullptr; } if (!ConfMan.hasKey(keyPrefix + "user_id", ConfMan.kCloudDomain)) { - warning("No user_id found"); + warning("DropboxStorage: no user_id found"); return nullptr; } diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index f129eaa94d..dd3a381b7a 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -123,7 +123,6 @@ void DropboxUploadRequest::uploadNextPart() { } void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse response) { - debug(9, "partUploadedCallback"); _workingRequest = nullptr; if (_ignoreCallback) return; @@ -133,6 +132,7 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); + // TODO: add more JSON-related warnings Common::JSONValue *json = response.value; if (json) { bool needsFinishRequest = false; @@ -140,7 +140,7 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons if (json->isObject()) { Common::JSONObject object = json->asObject(); - //debug("%s", json->stringify(true).c_str()); + //debug(9, "%s", json->stringify(true).c_str()); if (object.contains("error") || object.contains("error_summary")) { warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); @@ -163,19 +163,19 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons if (object.contains("session_id")) _sessionId = object.getVal("session_id")->asString(); else - warning("no session_id found in Dropbox's response"); + warning("DropboxUploadRequest: no session_id found"); needsFinishRequest = true; } } if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { - warning("no file info to return"); + warning("DropboxUploadRequest: no file info to return"); finishUpload(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } } else { - warning("null, not json"); + warning("DropboxUploadRequest: null, not json"); finishError(error); } @@ -183,7 +183,6 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons } void DropboxUploadRequest::partUploadedErrorCallback(Networking::ErrorResponse error) { - debug("partUploadedErrorCallback"); _workingRequest = nullptr; if (_ignoreCallback) return; diff --git a/backends/cloud/folderdownloadrequest.cpp b/backends/cloud/folderdownloadrequest.cpp index fe9704cf81..7eeee0c6d6 100644 --- a/backends/cloud/folderdownloadrequest.cpp +++ b/backends/cloud/folderdownloadrequest.cpp @@ -129,7 +129,7 @@ void FolderDownloadRequest::downloadNextFile() { if (_remoteDirectoryPath != "" && (_remoteDirectoryPath.lastChar() != '/' && _remoteDirectoryPath.lastChar() != '\\')) localPath.erase(0, 1); } else { - warning("Can't process the following paths:"); + warning("FolderDownloadRequest: Can't process the following paths:"); warning("remote directory: %s", _remoteDirectoryPath.c_str()); warning("remote file under that directory: %s", remotePath.c_str()); } @@ -139,7 +139,7 @@ void FolderDownloadRequest::downloadNextFile() { else localPath = _localDirectoryPath + "/" + localPath; } - debug(9, "%s -> %s", remotePath.c_str(), localPath.c_str()); + debug(9, "FolderDownloadRequest: %s -> %s", remotePath.c_str(), localPath.c_str()); _workingRequest = _storage->downloadById( _currentFile.id(), localPath, new Common::Callback(this, &FolderDownloadRequest::fileDownloadedCallback), diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index af19019a1e..7ae9dde3bd 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -113,14 +113,14 @@ void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonR Common::JSONObject result = json->asObject(); if (!result.contains("access_token")) { - warning("Bad response, no token passed"); - debug("%s", json->stringify().c_str()); + warning("GoogleDriveStorage: bad response, no token passed"); + debug(9, "%s", json->stringify().c_str()); if (callback) (*callback)(BoolResponse(nullptr, false)); } else { _token = result.getVal("access_token")->asString(); if (!result.contains("refresh_token")) - warning("No refresh_token passed"); + warning("GoogleDriveStorage: no refresh_token passed"); else _refreshToken = result.getVal("refresh_token")->asString(); CloudMan.save(); //ask CloudManager to save our new refreshToken @@ -143,8 +143,8 @@ void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { } void GoogleDriveStorage::codeFlowFailed(Networking::ErrorResponse error) { - debug("Google Drive's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); - debug("%s", error.response.c_str()); + debug(9, "GoogleDriveStorage: code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug(9, "%s", error.response.c_str()); CloudMan.removeStorage(this); } @@ -160,7 +160,7 @@ Common::String GoogleDriveStorage::name() const { void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("NULL passed instead of JSON"); + warning("GoogleDriveStorage: NULL passed instead of JSON"); delete outerCallback; return; } @@ -201,7 +201,7 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne void GoogleDriveStorage::createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("NULL passed instead of JSON"); + warning("GoogleDriveStorage: NULL passed instead of JSON"); delete outerCallback; return; } @@ -241,7 +241,7 @@ Networking::Request *GoogleDriveStorage::streamFileById(Common::String id, Netwo } void GoogleDriveStorage::printInfo(StorageInfoResponse response) { - debug(9, "\nuser info:"); + debug(9, "\nGoogleDriveStorage: user info:"); debug(9, "\tname: %s", response.value.name().c_str()); debug(9, "\temail: %s", response.value.email().c_str()); debug(9, "\tdisk usage: %lu/%lu", response.value.used(), response.value.available()); @@ -286,12 +286,12 @@ GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) loadKeyAndSecret(); if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { - warning("No access_token found"); + warning("GoogleDriveStorage: no access_token found"); return nullptr; } if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { - warning("No refresh_token found"); + warning("GoogleDriveStorage: no refresh_token found"); return nullptr; } diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp index 1b858504c5..99661c262e 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.cpp +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -69,7 +69,7 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { //new token needed => request token & then retry original request if (_stream) { httpResponseCode = _stream->httpResponseCode(); - debug(9, "code %ld", httpResponseCode); + debug(9, "GoogleDriveTokenRefresher: code = %ld", httpResponseCode); } Common::JSONObject error = result.getVal("error")->asObject(); @@ -79,12 +79,12 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::String message; if (error.contains("code") && error.getVal("code")->isIntegerNumber()) { code = error.getVal("code")->asIntegerNumber(); - debug(9, "code = %u", code); + debug(9, "GoogleDriveTokenRefresher: code = %u", code); } if (error.contains("message")) { message = error.getVal("message")->asString(); - debug(9, "message = %s", message.c_str()); + debug(9, "GoogleDriveTokenRefresher: message = %s", message.c_str()); } if (code == 401 || message == "Invalid Credentials") diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index bd9d8790ed..14f43eecde 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -305,13 +305,13 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res } if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { - warning("no file info to return"); + warning("GoogleDriveUploadRequest: no file info to return"); finishUpload(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } } else { - warning("null, not json"); + warning("GoogleDriveUploadRequest: null, not json"); finishError(error); } diff --git a/backends/cloud/id/idresolveidrequest.cpp b/backends/cloud/id/idresolveidrequest.cpp index 6742a5890f..e8589fc204 100644 --- a/backends/cloud/id/idresolveidrequest.cpp +++ b/backends/cloud/id/idresolveidrequest.cpp @@ -70,16 +70,16 @@ void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse resp return; Common::String currentLevelName = _requestedPath; - ///debug("'%s'", currentLevelName.c_str()); + ///debug(9, "'%s'", currentLevelName.c_str()); if (_currentDirectory.size()) currentLevelName.erase(0, _currentDirectory.size()); if (currentLevelName.size() && (currentLevelName[0] == '/' || currentLevelName[0] == '\\')) currentLevelName.erase(0, 1); - ///debug("'%s'", currentLevelName.c_str()); + ///debug(9, "'%s'", currentLevelName.c_str()); for (uint32 i = 0; i < currentLevelName.size(); ++i) { if (currentLevelName[i] == '/' || currentLevelName[i] == '\\') { currentLevelName.erase(i); - ///debug("'%s'", currentLevelName.c_str()); + ///debug(9, "'%s'", currentLevelName.c_str()); break; } } @@ -90,7 +90,7 @@ void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse resp path += currentLevelName; bool lastLevel = (path.equalsIgnoreCase(_requestedPath)); - ///debug("so, searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); + ///debug(9, "IdResolveIdRequest: searching for '%s' in '%s'", currentLevelName.c_str(), _currentDirectory.c_str()); Common::Array &files = response.value; bool found = false; @@ -100,7 +100,7 @@ void IdResolveIdRequest::listedDirectoryCallback(Storage::FileArrayResponse resp _currentDirectory += "/"; _currentDirectory += files[i].name(); _currentDirectoryId = files[i].id(); - ///debug("found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); + ///debug(9, "IdResolveIdRequest: found it! new directory and its id: '%s', '%s'", _currentDirectory.c_str(), _currentDirectoryId.c_str()); listNextDirectory(files[i]); found = true; break; diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index 857e3fb379..36f2df642c 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -36,7 +36,7 @@ namespace Id { IdStorage::~IdStorage() {} void IdStorage::printFiles(FileArrayResponse response) { - debug(9, "files:"); + debug(9, "IdStorage: files:"); Common::Array &files = response.value; for (uint32 i = 0; i < files.size(); ++i) { debug(9, "\t%s%s", files[i].name().c_str(), files[i].isDirectory() ? " (directory)" : ""); @@ -47,11 +47,11 @@ void IdStorage::printFiles(FileArrayResponse response) { } void IdStorage::printBool(BoolResponse response) { - debug(9, "bool: %s", response.value ? "true" : "false"); + debug(9, "IdStorage: bool: %s", response.value ? "true" : "false"); } void IdStorage::printFile(UploadResponse response) { - debug(9, "\nuploaded file info:"); + debug(9, "\nIdStorage: uploaded file info:"); debug(9, "\tid: %s", response.value.path().c_str()); debug(9, "\tname: %s", response.value.name().c_str()); debug(9, "\tsize: %u", response.value.size()); diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index a31fd025ac..4d6d8fceda 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -102,7 +102,7 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); if (!json) { - warning("NULL passed instead of JSON"); + warning("OneDriveCreateDirectoryRequest: NULL passed instead of JSON"); finishError(error); return; } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index af5d9f10ba..1008cab31f 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -113,8 +113,8 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResp Common::JSONObject result = json->asObject(); if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) { - warning("Bad response, no token or user_id passed"); - debug("%s", json->stringify().c_str()); + warning("OneDriveStorage: bad response, no token or user_id passed"); + debug(9, "%s", json->stringify().c_str()); if (callback) (*callback)(BoolResponse(nullptr, false)); } else { @@ -141,8 +141,8 @@ void OneDriveStorage::codeFlowComplete(BoolResponse response) { } void OneDriveStorage::codeFlowFailed(Networking::ErrorResponse error) { - debug("OneDrive's code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); - debug("%s", error.response.c_str()); + debug(9, "OneDriveStorage: code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug(9, "%s", error.response.c_str()); CloudMan.removeStorage(this); } @@ -159,7 +159,7 @@ Common::String OneDriveStorage::name() const { void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("NULL passed instead of JSON"); + warning("OneDriveStorage: NULL passed instead of JSON"); delete outerCallback; return; } @@ -199,7 +199,7 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { if (!response.value) { - warning("fileInfoCallback: NULL"); + warning("OneDriveStorage::fileInfoCallback: NULL, not JSON"); if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); return; @@ -214,8 +214,8 @@ void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback out new Networking::NetworkReadStream(url, nullptr, "") )); } else { - warning("downloadUrl not found in passed JSON"); - debug("%s", response.value->stringify().c_str()); + warning("OneDriveStorage: downloadUrl not found in passed JSON"); + debug(9, "%s", response.value->stringify().c_str()); if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); } @@ -257,17 +257,17 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { loadKeyAndSecret(); if (!ConfMan.hasKey(keyPrefix + "access_token", ConfMan.kCloudDomain)) { - warning("No access_token found"); + warning("OneDriveStorage: no access_token found"); return nullptr; } if (!ConfMan.hasKey(keyPrefix + "user_id", ConfMan.kCloudDomain)) { - warning("No user_id found"); + warning("OneDriveStorage: no user_id found"); return nullptr; } if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) { - warning("No refresh_token found"); + warning("OneDriveStorage: no refresh_token found"); return nullptr; } diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index f7597599c7..5e3bce96af 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -69,7 +69,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { //new token needed => request token & then retry original request if (_stream) { httpResponseCode = _stream->httpResponseCode(); - debug(9, "code %ld", httpResponseCode); + debug(9, "OneDriveTokenRefresher: code = %ld", httpResponseCode); } Common::JSONObject error = result.getVal("error")->asObject(); @@ -78,12 +78,12 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { Common::String code, message; if (error.contains("code")) { code = error.getVal("code")->asString(); - debug(9, "code = %s", code.c_str()); + debug(9, "OneDriveTokenRefresher: code = %s", code.c_str()); } if (error.contains("message")) { message = error.getVal("message")->asString(); - debug(9, "message = %s", message.c_str()); + debug(9, "OneDriveTokenRefresher: message = %s", message.c_str()); } //determine whether token refreshing would help in this situation diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index ef1507d1f2..172266ce2a 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -130,7 +130,7 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon Common::JSONObject object = json->asObject(); if (object.contains("error")) { - warning("OneDrive returned error: %s", json->stringify(true).c_str()); + warning("OneDriveUploadRequest: error: %s", json->stringify(true).c_str()); error.response = json->stringify(true); finishError(error); delete json; @@ -150,18 +150,18 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon if (object.contains("uploadUrl")) _uploadUrl = object.getVal("uploadUrl")->asString(); else - warning("no uploadUrl found in OneDrive's response"); + warning("OneDriveUploadRequest: no uploadUrl found"); } } if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { - warning("no file info to return"); + warning("OneDriveUploadRequest: no file info to return"); finishUpload(StorageFile(_savePath, 0, 0, false)); } else { uploadNextPart(); } } else { - warning("null, not json"); + warning("OneDriveUploadRequest: null, not json"); finishError(error); } diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 7776804579..889c6b936b 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -125,11 +125,11 @@ void SavesSyncRequest::directoryListedCallback(Storage::ListDirectoryResponse re _filesToUpload.push_back(i->_key); } - debug(9, "\ndownload files:"); + debug(9, "\nSavesSyncRequest: download files:"); for (uint32 i = 0; i < _filesToDownload.size(); ++i) { debug(9, "%s", _filesToDownload[i].name().c_str()); } - debug(9, "\nupload files:"); + debug(9, "\nSavesSyncRequest: upload files:"); for (uint32 i = 0; i < _filesToUpload.size(); ++i) { debug(9, "%s", _filesToUpload[i].c_str()); } @@ -190,7 +190,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er Common::String dir = _storage->savesDirectoryPath(); if (dir.lastChar() == '/') dir.deleteLastChar(); - debug(9, "creating %s", dir.c_str()); + debug(9, "SavesSyncRequest: creating %s", dir.c_str()); _workingRequest = _storage->createDirectory( dir, new Common::Callback(this, &SavesSyncRequest::directoryCreatedCallback), @@ -238,7 +238,7 @@ void SavesSyncRequest::downloadNextFile() { sendCommand(GUI::kSavesSyncProgressCmd, (int)(getDownloadingProgress() * 100)); - debug(9, "downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); + debug(9, "SavesSyncRequest: downloading %s (%d %%)", _currentDownloadingFile.name().c_str(), (int)(getProgress() * 100)); _workingRequest = _storage->downloadById( _currentDownloadingFile.id(), DefaultSaveFileManager::concatWithSavesPath(_currentDownloadingFile.name()), @@ -289,7 +289,7 @@ void SavesSyncRequest::uploadNextFile() { _currentUploadingFile = _filesToUpload.back(); _filesToUpload.pop_back(); - debug(9, "uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress() * 100)); + debug(9, "SavesSyncRequest: uploading %s (%d %%)", _currentUploadingFile.c_str(), (int)(getProgress() * 100)); if (_storage->uploadStreamSupported()) { _workingRequest = _storage->upload( _storage->savesDirectoryPath() + _currentUploadingFile, @@ -370,7 +370,7 @@ Common::Array SavesSyncRequest::getFilesToDownload() { } void SavesSyncRequest::finishError(Networking::ErrorResponse error) { - debug("SavesSync::finishError"); + debug(9, "SavesSync::finishError"); //if we were downloading a file - remember the name //and make the Request close() it, so we can delete it Common::String name = _currentDownloadingFile.name(); diff --git a/backends/cloud/storage.cpp b/backends/cloud/storage.cpp index b085401f47..910d80d153 100644 --- a/backends/cloud/storage.cpp +++ b/backends/cloud/storage.cpp @@ -42,8 +42,8 @@ Networking::ErrorCallback Storage::getErrorPrintingCallback() { } void Storage::printErrorResponse(Networking::ErrorResponse error) { - debug("error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); - debug("%s", error.response.c_str()); + debug(9, "Storage: error response (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); + debug(9, "%s", error.response.c_str()); } Networking::Request *Storage::addRequest(Networking::Request *request) { -- cgit v1.2.3 From 6dd10f3a683ab787b751a84958502f7eda1da84c Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 12:29:52 +0600 Subject: CLOUD: Add KEY/SECRET override code The following constants must be defined if ENABLE_RELEASE is: * RELEASE_DROPBOX_KEY, * RELEASE_DROPBOX_SECRET, * RELEASE_ONEDRIVE_KEY, * RELEASE_ONEDRIVE_SECRET, * RELEASE_GOOGLE_DRIVE_KEY, * RELEASE_GOOGLE_DRIVE_SECRET, * RELEASE_BOX_KEY, * RELEASE_BOX_SECRET. --- backends/cloud/box/boxstorage.cpp | 11 ++++++++++- backends/cloud/dropbox/dropboxstorage.cpp | 11 ++++++++++- backends/cloud/googledrive/googledrivestorage.cpp | 9 +++++++++ backends/cloud/onedrive/onedrivestorage.cpp | 11 ++++++++++- 4 files changed, 39 insertions(+), 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index c2c4c6278e..58a2541a74 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -29,10 +29,14 @@ #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" +#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include -#include "common/config-manager.h" + +#ifdef ENABLE_RELEASE +#include "dists/clouds/cloud_keys.h" +#endif namespace Cloud { namespace Box { @@ -46,6 +50,10 @@ char *BoxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it o char *BoxStorage::SECRET = nullptr; //TODO: hide these secrets somehow void BoxStorage::loadKeyAndSecret() { +#ifdef ENABLE_RELEASE + KEY = RELEASE_BOX_KEY; + SECRET = RELEASE_BOX_SECRET; +#else Common::String k = ConfMan.get("BOX_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); @@ -55,6 +63,7 @@ void BoxStorage::loadKeyAndSecret() { SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; +#endif } BoxStorage::BoxStorage(Common::String accessToken, Common::String refreshToken): diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 6fd1f9d2fd..41536fe0ea 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -29,10 +29,14 @@ #include "backends/cloud/cloudmanager.h" #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" +#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include -#include "common/config-manager.h" + +#ifdef ENABLE_RELEASE +#include "dists/clouds/cloud_keys.h" +#endif namespace Cloud { namespace Dropbox { @@ -44,6 +48,10 @@ char *DropboxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading char *DropboxStorage::SECRET = nullptr; //TODO: hide these secrets somehow void DropboxStorage::loadKeyAndSecret() { +#ifdef ENABLE_RELEASE + KEY = RELEASE_DROPBOX_KEY; + SECRET = RELEASE_DROPBOX_SECRET; +#else Common::String k = ConfMan.get("DROPBOX_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); @@ -53,6 +61,7 @@ void DropboxStorage::loadKeyAndSecret() { SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; +#endif } DropboxStorage::DropboxStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) {} diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 7ae9dde3bd..d876883185 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -34,6 +34,10 @@ #include "common/json.h" #include +#ifdef ENABLE_RELEASE +#include "dists/clouds/cloud_keys.h" +#endif + namespace Cloud { namespace GoogleDrive { @@ -46,6 +50,10 @@ char *GoogleDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, load char *GoogleDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void GoogleDriveStorage::loadKeyAndSecret() { +#ifdef ENABLE_RELEASE + KEY = RELEASE_GOOGLE_DRIVE_KEY; + SECRET = RELEASE_GOOGLE_DRIVE_SECRET; +#else Common::String k = ConfMan.get("GOOGLE_DRIVE_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); @@ -55,6 +63,7 @@ void GoogleDriveStorage::loadKeyAndSecret() { SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; +#endif } GoogleDriveStorage::GoogleDriveStorage(Common::String accessToken, Common::String refreshToken): diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 1008cab31f..458aaecf88 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -30,10 +30,14 @@ #include "backends/networking/curl/connectionmanager.h" #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" +#include "common/config-manager.h" #include "common/debug.h" #include "common/json.h" #include -#include "common/config-manager.h" + +#ifdef ENABLE_RELEASE +#include "dists/clouds/cloud_keys.h" +#endif namespace Cloud { namespace OneDrive { @@ -46,6 +50,10 @@ char *OneDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading char *OneDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow void OneDriveStorage::loadKeyAndSecret() { +#ifdef ENABLE_RELEASE + KEY = RELEASE_ONEDRIVE_KEY; + SECRET = RELEASE_ONEDRIVE_SECRET; +#else Common::String k = ConfMan.get("ONEDRIVE_KEY", ConfMan.kCloudDomain); KEY = new char[k.size() + 1]; memcpy(KEY, k.c_str(), k.size()); @@ -55,6 +63,7 @@ void OneDriveStorage::loadKeyAndSecret() { SECRET = new char[k.size() + 1]; memcpy(SECRET, k.c_str(), k.size()); SECRET[k.size()] = 0; +#endif } OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId, Common::String refreshToken): -- cgit v1.2.3 From 0b97aff866686b43ea8b95aeb0f29ac3abe46840 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 12:31:11 +0600 Subject: CLOUD: Minor TODO fix --- backends/cloud/box/boxstorage.cpp | 2 +- backends/cloud/dropbox/dropboxstorage.cpp | 2 +- backends/cloud/googledrive/googledrivestorage.cpp | 2 +- backends/cloud/onedrive/onedrivestorage.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 58a2541a74..7d67ba1676 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -47,7 +47,7 @@ namespace Box { #define BOX_API_USERS_ME "https://api.box.com/2.0/users/me" char *BoxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth -char *BoxStorage::SECRET = nullptr; //TODO: hide these secrets somehow +char *BoxStorage::SECRET = nullptr; void BoxStorage::loadKeyAndSecret() { #ifdef ENABLE_RELEASE diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 41536fe0ea..789f6b497c 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -45,7 +45,7 @@ namespace Dropbox { #define DROPBOX_API_FILES_DOWNLOAD "https://content.dropboxapi.com/2/files/download" char *DropboxStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth -char *DropboxStorage::SECRET = nullptr; //TODO: hide these secrets somehow +char *DropboxStorage::SECRET = nullptr; void DropboxStorage::loadKeyAndSecret() { #ifdef ENABLE_RELEASE diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index d876883185..789dfaf53a 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -47,7 +47,7 @@ namespace GoogleDrive { #define GOOGLEDRIVE_API_ABOUT "https://www.googleapis.com/drive/v3/about?fields=storageQuota,user" char *GoogleDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth -char *GoogleDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow +char *GoogleDriveStorage::SECRET = nullptr; void GoogleDriveStorage::loadKeyAndSecret() { #ifdef ENABLE_RELEASE diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 458aaecf88..9fde2ed2c7 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -47,7 +47,7 @@ namespace OneDrive { #define ONEDRIVE_API_SPECIAL_APPROOT "https://api.onedrive.com/v1.0/drive/special/approot" char *OneDriveStorage::KEY = nullptr; //can't use CloudConfig there yet, loading it on instance creation/auth -char *OneDriveStorage::SECRET = nullptr; //TODO: hide these secrets somehow +char *OneDriveStorage::SECRET = nullptr; void OneDriveStorage::loadKeyAndSecret() { #ifdef ENABLE_RELEASE -- cgit v1.2.3 From 9d96d40b3d78d987d414e0dc77f43c09ef4421ba Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 13:34:12 +0600 Subject: CLOUD: Add JSON-related checks in BoxStorage --- backends/cloud/box/boxstorage.cpp | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 7d67ba1676..6209de0b70 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -119,11 +119,21 @@ void BoxStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse if (!json) { warning("BoxStorage: got NULL instead of JSON"); if (callback) (*callback)(BoolResponse(nullptr, false)); + delete callback; + return; + } + + if (!Networking::CurlJsonRequest::jsonIsObject(json, "BoxStorage")) { + if (callback) + (*callback)(BoolResponse(nullptr, false)); + delete json; + delete callback; return; } Common::JSONObject result = json->asObject(); - if (!result.contains("access_token") || !result.contains("refresh_token")) { + if (!Networking::CurlJsonRequest::jsonContainsString(result, "access_token", "BoxStorage") || + !Networking::CurlJsonRequest::jsonContainsString(result, "refresh_token", "BoxStorage")) { warning("BoxStorage: bad response, no token passed"); debug(9, "%s", json->stringify().c_str()); if (callback) @@ -136,6 +146,7 @@ void BoxStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse (*callback)(BoolResponse(nullptr, true)); } delete json; + delete callback; } void BoxStorage::codeFlowComplete(BoolResponse response) { @@ -172,6 +183,12 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking return; } + if (!Networking::CurlJsonRequest::jsonIsObject(json, "BoxStorage::infoInnerCallback")) { + delete json; + delete outerCallback; + return; + } + Common::JSONObject info = json->asObject(); Common::String uid, name, email; @@ -180,19 +197,19 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking // can check that "type": "user" // there is also "max_upload_size", "phone" and "avatar_url" - if (info.contains("id") && info.getVal("id")->isString()) + if (Networking::CurlJsonRequest::jsonContainsString(info, "id", "BoxStorage::infoInnerCallback")) uid = info.getVal("id")->asString(); - if (info.contains("name") && info.getVal("name")->isString()) + if (Networking::CurlJsonRequest::jsonContainsString(info, "name", "BoxStorage::infoInnerCallback")) name = info.getVal("name")->asString(); - if (info.contains("login") && info.getVal("login")->isString()) + if (Networking::CurlJsonRequest::jsonContainsString(info, "login", "BoxStorage::infoInnerCallback")) email = info.getVal("login")->asString(); - if (info.contains("space_amount") && info.getVal("space_amount")->isIntegerNumber()) + if (Networking::CurlJsonRequest::jsonContainsIntegerNumber(info, "space_amount", "BoxStorage::infoInnerCallback")) quotaAllocated = info.getVal("space_amount")->asIntegerNumber(); - if (info.contains("space_used") && info.getVal("space_used")->isIntegerNumber()) + if (Networking::CurlJsonRequest::jsonContainsIntegerNumber(info, "space_used", "BoxStorage::infoInnerCallback")) quotaUsed = info.getVal("space_used")->asIntegerNumber(); Common::String username = email; @@ -225,8 +242,12 @@ void BoxStorage::createDirectoryInnerCallback(BoolCallback outerCallback, Networ } if (outerCallback) { - Common::JSONObject info = json->asObject(); - (*outerCallback)(BoolResponse(nullptr, info.contains("id"))); + if (Networking::CurlJsonRequest::jsonIsObject(json, "BoxStorage::createDirectoryInnerCallback")) { + Common::JSONObject info = json->asObject(); + (*outerCallback)(BoolResponse(nullptr, info.contains("id"))); + } else { + (*outerCallback)(BoolResponse(nullptr, false)); + } delete outerCallback; } -- cgit v1.2.3 From 166d1121e5973868b24aa3db6156028edb1d6a72 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 13:45:24 +0600 Subject: CLOUD: Update TokenRefreshers Box's, Google Drive's and OneDrive's token refreshing requests have more JSON checks now. --- backends/cloud/box/boxtokenrefresher.cpp | 67 ++++++++++---------- .../googledrive/googledrivetokenrefresher.cpp | 70 ++++++++++---------- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 74 +++++++++++----------- 3 files changed, 109 insertions(+), 102 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxtokenrefresher.cpp b/backends/cloud/box/boxtokenrefresher.cpp index c798b97343..ca05eef838 100644 --- a/backends/cloud/box/boxtokenrefresher.cpp +++ b/backends/cloud/box/boxtokenrefresher.cpp @@ -63,41 +63,44 @@ void BoxTokenRefresher::finishJson(Common::JSONValue *json) { return; } - Common::JSONObject result = json->asObject(); - if (result.contains("type") && result.getVal("type")->isString() && result.getVal("type")->asString() == "error") { - //new token needed => request token & then retry original request - long httpCode = -1; - if (_stream) { - httpCode = _stream->httpResponseCode(); - debug(9, "BoxTokenRefresher: code %ld", httpCode); - } - - bool irrecoverable = true; - - Common::String code, message; - if (result.contains("code")) { - code = result.getVal("code")->asString(); - debug(9, "BoxTokenRefresher: code = %s", code.c_str()); - } - - if (result.contains("message")) { - message = result.getVal("message")->asString(); - debug(9, "BoxTokenRefresher: message = %s", message.c_str()); - } - - //TODO: decide when token refreshment will help - //if (code == "unauthenticated") irrecoverable = false; - - if (irrecoverable) { - finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpCode)); + if (jsonIsObject(json, "BoxTokenRefresher")) { + Common::JSONObject result = json->asObject(); + if (result.contains("type") && result.getVal("type")->isString() && result.getVal("type")->asString() == "error") { + //new token needed => request token & then retry original request + long httpCode = -1; + if (_stream) { + httpCode = _stream->httpResponseCode(); + debug(9, "BoxTokenRefresher: code %ld", httpCode); + } + + bool irrecoverable = true; + + Common::String code, message; + if (jsonContainsString(result, "code", "BoxTokenRefresher")) { + code = result.getVal("code")->asString(); + debug(9, "BoxTokenRefresher: code = %s", code.c_str()); + } + + if (jsonContainsString(result, "message", "BoxTokenRefresher")) { + message = result.getVal("message")->asString(); + debug(9, "BoxTokenRefresher: message = %s", message.c_str()); + } + + //TODO: decide when token refreshment will help + //for now refreshment is used only when HTTP 401 is passed in finishError() + //if (code == "unauthenticated") irrecoverable = false; + + if (irrecoverable) { + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpCode)); + delete json; + return; + } + + pause(); delete json; + _parentStorage->getAccessToken(new Common::Callback(this, &BoxTokenRefresher::tokenRefreshed)); return; } - - pause(); - delete json; - _parentStorage->getAccessToken(new Common::Callback(this, &BoxTokenRefresher::tokenRefreshed)); - return; } //notify user of success diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp index 99661c262e..7d68510655 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.cpp +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -63,43 +63,45 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { return; } - Common::JSONObject result = json->asObject(); - long httpResponseCode = -1; - if (result.contains("error")) { - //new token needed => request token & then retry original request - if (_stream) { - httpResponseCode = _stream->httpResponseCode(); - debug(9, "GoogleDriveTokenRefresher: code = %ld", httpResponseCode); - } - - Common::JSONObject error = result.getVal("error")->asObject(); - bool irrecoverable = true; - - uint32 code = -1; - Common::String message; - if (error.contains("code") && error.getVal("code")->isIntegerNumber()) { - code = error.getVal("code")->asIntegerNumber(); - debug(9, "GoogleDriveTokenRefresher: code = %u", code); - } - - if (error.contains("message")) { - message = error.getVal("message")->asString(); - debug(9, "GoogleDriveTokenRefresher: message = %s", message.c_str()); - } - - if (code == 401 || message == "Invalid Credentials") - irrecoverable = false; - - if (irrecoverable) { - finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpResponseCode)); + if (jsonIsObject(json, "GoogleDriveTokenRefresher")) { + Common::JSONObject result = json->asObject(); + long httpResponseCode = -1; + if (jsonContainsAttribute(result, "error", "GoogleDriveTokenRefresher") && jsonIsObject(result.getVal("error"), "GoogleDriveTokenRefresher")) { + //new token needed => request token & then retry original request + if (_stream) { + httpResponseCode = _stream->httpResponseCode(); + debug(9, "GoogleDriveTokenRefresher: code = %ld", httpResponseCode); + } + + Common::JSONObject error = result.getVal("error")->asObject(); + bool irrecoverable = true; + + uint32 code = -1; + Common::String message; + if (jsonContainsIntegerNumber(error, "code", "GoogleDriveTokenRefresher")) { + code = error.getVal("code")->asIntegerNumber(); + debug(9, "GoogleDriveTokenRefresher: code = %u", code); + } + + if (jsonContainsString(error, "message", "GoogleDriveTokenRefresher")) { + message = error.getVal("message")->asString(); + debug(9, "GoogleDriveTokenRefresher: message = %s", message.c_str()); + } + + if (code == 401 || message == "Invalid Credentials") + irrecoverable = false; + + if (irrecoverable) { + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpResponseCode)); + delete json; + return; + } + + pause(); delete json; + _parentStorage->getAccessToken(new Common::Callback(this, &GoogleDriveTokenRefresher::tokenRefreshed)); return; } - - pause(); - delete json; - _parentStorage->getAccessToken(new Common::Callback(this, &GoogleDriveTokenRefresher::tokenRefreshed)); - return; } //notify user of success diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 5e3bce96af..5ee2772ba7 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -63,48 +63,50 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { return; } - Common::JSONObject result = json->asObject(); - long httpResponseCode = -1; - if (result.contains("error")) { - //new token needed => request token & then retry original request - if (_stream) { - httpResponseCode = _stream->httpResponseCode(); - debug(9, "OneDriveTokenRefresher: code = %ld", httpResponseCode); - } - - Common::JSONObject error = result.getVal("error")->asObject(); - bool irrecoverable = true; - - Common::String code, message; - if (error.contains("code")) { - code = error.getVal("code")->asString(); - debug(9, "OneDriveTokenRefresher: code = %s", code.c_str()); - } - - if (error.contains("message")) { - message = error.getVal("message")->asString(); - debug(9, "OneDriveTokenRefresher: message = %s", message.c_str()); - } - - //determine whether token refreshing would help in this situation - if (code == "itemNotFound") { - if (message.contains("application ID")) + if (jsonIsObject(json, "OneDriveTokenRefresher")) { + Common::JSONObject result = json->asObject(); + long httpResponseCode = -1; + if (jsonContainsAttribute(result, "error", "OneDriveTokenRefresher") && jsonIsObject(result.getVal("error"), "OneDriveTokenRefresher")) { + //new token needed => request token & then retry original request + if (_stream) { + httpResponseCode = _stream->httpResponseCode(); + debug(9, "OneDriveTokenRefresher: code = %ld", httpResponseCode); + } + + Common::JSONObject error = result.getVal("error")->asObject(); + bool irrecoverable = true; + + Common::String code, message; + if (jsonContainsString(error, "code", "OneDriveTokenRefresher")) { + code = error.getVal("code")->asString(); + debug(9, "OneDriveTokenRefresher: code = %s", code.c_str()); + } + + if (jsonContainsString(error, "message", "OneDriveTokenRefresher")) { + message = error.getVal("message")->asString(); + debug(9, "OneDriveTokenRefresher: message = %s", message.c_str()); + } + + //determine whether token refreshing would help in this situation + if (code == "itemNotFound") { + if (message.contains("application ID")) + irrecoverable = false; + } + + if (code == "unauthenticated") irrecoverable = false; - } - if (code == "unauthenticated") - irrecoverable = false; + if (irrecoverable) { + finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpResponseCode)); + delete json; + return; + } - if (irrecoverable) { - finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpResponseCode)); + pause(); delete json; + _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); return; } - - pause(); - delete json; - _parentStorage->getAccessToken(new Common::Callback(this, &OneDriveTokenRefresher::tokenRefreshed)); - return; } //notify user of success -- cgit v1.2.3 From a2e019972779575bcc9038949bca73d78f7bf07b Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 13:58:02 +0600 Subject: CLOUD: Update BoxUploadRequest More JSON checks there. --- backends/cloud/box/boxuploadrequest.cpp | 93 +++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 40 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index f68ba6a580..929c9ceb75 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -145,56 +145,69 @@ void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { if (error.httpResponseCode != 200 && error.httpResponseCode != 201) warning("BoxUploadRequest: looks like an error (bad HTTP code)"); - //TODO: add more JSON warnings there + //check JSON and show warnings if it's malformed Common::JSONValue *json = response.value; - if (json) { - if (json->isObject()) { - Common::JSONObject object = json->asObject(); - if (object.contains("entries") && object.getVal("entries")->isArray()) { - Common::JSONArray entries = object.getVal("entries")->asArray(); - if (entries.size() > 0) { - Common::JSONObject entry = entries[0]->asObject(); - - //finished - Common::String id = entry.getVal("id")->asString(); - Common::String name = entry.getVal("name")->asString(); - bool isDirectory = (entry.getVal("type")->asString() == "folder"); - uint32 size = 0, timestamp = 0; - if (entry.contains("size")) { - if (entry.getVal("size")->isString()) - size = entry.getVal("size")->asString().asUint64(); - else if (entry.getVal("size")->isIntegerNumber()) - size = entry.getVal("size")->asIntegerNumber(); - else - warning("strange type for field 'size'"); - } - if (entry.contains("modified_at") && entry.getVal("modified_at")->isString()) - timestamp = ISO8601::convertToTimestamp(entry.getVal("modified_at")->asString()); - - //as we list directory by id, we can't determine full path for the file, so we leave it empty - finishUpload(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); - return; + 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 object = json->asObject(); + if (Networking::CurlJsonRequest::jsonContainsArray(object, "entries", "BoxUploadRequest")) { + Common::JSONArray entries = object.getVal("entries")->asArray(); + if (entries.size() == 0) { + warning("BoxUploadRequest: 'entries' found, but it's empty"); + } else if (Networking::CurlJsonRequest::jsonIsObject(entries[0], "BoxUploadRequest")) { + warning("BoxUploadRequest: 'entries' first item is not an object"); + } else { + Common::JSONObject item = entries[0]->asObject(); + + if (Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(item, "modified_at", "BoxUploadRequest") && + Networking::CurlJsonRequest::jsonContainsStringOrIntegerNumber(item, "size", "BoxUploadRequest")) { + + //finished + Common::String id = item.getVal("id")->asString(); + Common::String name = item.getVal("name")->asString(); + bool isDirectory = (item.getVal("type")->asString() == "folder"); + uint32 size; + if (item.getVal("size")->isString()) { + size = item.getVal("size")->asString().asUint64(); + } else { + size = item.getVal("size")->asIntegerNumber(); } - } + uint32 timestamp = ISO8601::convertToTimestamp(item.getVal("modified_at")->asString()); - //TODO: check errors - /* - if (object.contains("error")) { - warning("Box returned error: %s", json->stringify(true).c_str()); + finishUpload(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); delete json; - error.response = json->stringify(true); - finishError(error); return; } - */ } + } - warning("BoxUploadRequest: no file info to return"); - finishUpload(StorageFile(_savePath, 0, 0, false)); - } else { - warning("BoxUploadRequest: null, not json"); + //TODO: check errors + /* + if (object.contains("error")) { + warning("Box returned error: %s", json->stringify(true).c_str()); + delete json; + error.response = json->stringify(true); finishError(error); + return; } + */ + + warning("BoxUploadRequest: no file info to return"); + finishUpload(StorageFile(_savePath, 0, 0, false)); delete json; } -- cgit v1.2.3 From 6be736b5ed92800e1cd329d0de4ed0bb7ff2ea38 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 14:10:54 +0600 Subject: CLOUD: Update Dropbox Requests Adding more JSON checks there. --- .../dropbox/dropboxcreatedirectoryrequest.cpp | 14 ++++- backends/cloud/dropbox/dropboxinforequest.cpp | 65 ++++++++++++++++++---- 2 files changed, 65 insertions(+), 14 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index 6cc6801bc0..97090b44f8 100644 --- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp +++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp @@ -79,19 +79,27 @@ void DropboxCreateDirectoryRequest::responseCallback(Networking::JsonResponse re if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - if (!json) { - warning("DropboxCreateDirectoryRequest: NULL passed instead of JSON"); + 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 info = json->asObject(); if (info.contains("id")) { finishCreation(true); } else { - if (info.contains("error_summary") && info.getVal("error_summary")->isString()) { + if (Networking::CurlJsonRequest::jsonContainsString(info, "error_summary", "DropboxCreateDirectoryRequest")) { Common::String summary = info.getVal("error_summary")->asString(); if (summary.contains("path") && summary.contains("conflict") && summary.contains("folder")) { + // existing directory - not an error for CreateDirectoryRequest finishCreation(false); delete json; return; diff --git a/backends/cloud/dropbox/dropboxinforequest.cpp b/backends/cloud/dropbox/dropboxinforequest.cpp index c5cbb9d917..6cdbe3321b 100644 --- a/backends/cloud/dropbox/dropboxinforequest.cpp +++ b/backends/cloud/dropbox/dropboxinforequest.cpp @@ -76,18 +76,34 @@ void DropboxInfoRequest::userResponseCallback(Networking::JsonResponse response) if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - if (!json) { - warning("DropboxInfoRequest: NULL passed instead of JSON"); + 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; + } + //Dropbox documentation states there are no errors for this API method Common::JSONObject info = json->asObject(); - Common::JSONObject nameInfo = info.getVal("name")->asObject(); - _uid = info.getVal("account_id")->asString(); - _name = nameInfo.getVal("display_name")->asString(); - _email = info.getVal("email")->asString(); + if (Networking::CurlJsonRequest::jsonContainsAttribute(info, "name", "DropboxInfoRequest") && + Networking::CurlJsonRequest::jsonIsObject(info.getVal("name"), "DropboxInfoRequest")) { + Common::JSONObject nameInfo = info.getVal("name")->asObject(); + if (Networking::CurlJsonRequest::jsonContainsString(nameInfo, "display_name", "DropboxInfoRequest")) { + _name = nameInfo.getVal("display_name")->asString(); + } + } + if (Networking::CurlJsonRequest::jsonContainsString(info, "account_id", "DropboxInfoRequest")) { + _uid = info.getVal("account_id")->asString(); + } + if (Networking::CurlJsonRequest::jsonContainsString(info, "email", "DropboxInfoRequest")) { + _email = info.getVal("email")->asString(); + } CloudMan.setStorageUsername(kStorageDropboxId, _email); delete json; @@ -114,17 +130,44 @@ void DropboxInfoRequest::quotaResponseCallback(Networking::JsonResponse response if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - if (!json) { - warning("DropboxInfoRequest: NULL passed instead of JSON"); + 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; + } + //Dropbox documentation states there are no errors for this API method Common::JSONObject info = json->asObject(); - Common::JSONObject allocation = info.getVal("allocation")->asObject(); - uint64 used = info.getVal("used")->asIntegerNumber(); - uint64 allocated = allocation.getVal("allocated")->asIntegerNumber(); + + if (!Networking::CurlJsonRequest::jsonContainsIntegerNumber(info, "used", "DropboxInfoRequest")) { + error.response = "Passed JSON misses 'used' attribute!"; + finishError(error); + delete json; + return; + } + + uint64 used = info.getVal("used")->asIntegerNumber(), allocated = 0; + + if (Networking::CurlJsonRequest::jsonContainsAttribute(info, "allocation", "DropboxInfoRequest") && + Networking::CurlJsonRequest::jsonIsObject(info.getVal("allocation"), "DropboxInfoRequest")) { + Common::JSONObject allocation = info.getVal("allocation")->asObject(); + if (!Networking::CurlJsonRequest::jsonContainsIntegerNumber(allocation, "allocated", "DropboxInfoRequest")) { + error.response = "Passed JSON misses 'allocation/allocated' attribute!"; + finishError(error); + delete json; + return; + } + + allocated = allocation.getVal("allocated")->asIntegerNumber(); + } + finishInfo(StorageInfo(_uid, _name, _email, used, allocated)); delete json; } -- cgit v1.2.3 From 364c74df930633bf897cacf391f6dc24dbc183b8 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 14:13:38 +0600 Subject: CLOUD: Update DropboxStorage JSON checks added. --- backends/cloud/dropbox/dropboxstorage.cpp | 39 +++++++++++++++++++------------ 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index 789f6b497c..d12070316b 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -92,25 +92,34 @@ void DropboxStorage::getAccessToken(Common::String code) { void DropboxStorage::codeFlowComplete(Networking::JsonResponse response) { Common::JSONValue *json = (Common::JSONValue *)response.value; - if (json) { - Common::JSONObject result = json->asObject(); - if (!result.contains("access_token") || !result.contains("uid")) { - warning("DropboxStorage: bad response, no token/uid passed"); - debug(9, "%s", json->stringify(true).c_str()); - CloudMan.removeStorage(this); - } else { - _token = result.getVal("access_token")->asString(); - _uid = result.getVal("uid")->asString(); - ConfMan.removeKey("dropbox_code", ConfMan.kCloudDomain); - CloudMan.replaceStorage(this, kStorageDropboxId); - ConfMan.flushToDisk(); - } + if (json == nullptr) { + debug(9, "DropboxStorage::codeFlowComplete: got NULL instead of JSON!"); + CloudMan.removeStorage(this); + return; + } + if (!json->isObject()) { + debug(9, "DropboxStorage::codeFlowComplete: Passed JSON is not an object!"); + CloudMan.removeStorage(this); delete json; - } else { - debug(9, "DropboxStorage::codeFlowComplete: got NULL instead of JSON!"); + return; + } + + Common::JSONObject result = json->asObject(); + if (!Networking::CurlJsonRequest::jsonContainsString(result, "access_token", "DropboxStorage::codeFlowComplete") || + !Networking::CurlJsonRequest::jsonContainsString(result, "uid", "DropboxStorage::codeFlowComplete")) { + warning("DropboxStorage: bad response, no token/uid passed"); + debug(9, "%s", json->stringify(true).c_str()); CloudMan.removeStorage(this); + } else { + _token = result.getVal("access_token")->asString(); + _uid = result.getVal("uid")->asString(); + ConfMan.removeKey("dropbox_code", ConfMan.kCloudDomain); + CloudMan.replaceStorage(this, kStorageDropboxId); + ConfMan.flushToDisk(); } + + delete json; } void DropboxStorage::codeFlowFailed(Networking::ErrorResponse error) { -- cgit v1.2.3 From b3aa9f663f3ac0ac325225c1eaf8f78fb8bf9009 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 14:19:37 +0600 Subject: CLOUD: Update DropboxUploadRequest JSON checks. --- backends/cloud/dropbox/dropboxuploadrequest.cpp | 70 +++++++++++++------------ 1 file changed, 36 insertions(+), 34 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index dd3a381b7a..945493b1eb 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -132,51 +132,53 @@ void DropboxUploadRequest::partUploadedCallback(Networking::JsonResponse respons if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - // TODO: add more JSON-related warnings Common::JSONValue *json = response.value; - if (json) { - bool needsFinishRequest = false; + if (json == nullptr) { + error.response = "Failed to parse JSON, null passed!"; + finishError(error); + return; + } - if (json->isObject()) { - Common::JSONObject object = json->asObject(); + bool needsFinishRequest = false; - //debug(9, "%s", json->stringify(true).c_str()); + if (json->isObject()) { + Common::JSONObject object = json->asObject(); - if (object.contains("error") || object.contains("error_summary")) { - warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); - error.response = json->stringify(true); - finishError(error); - delete json; - return; - } + //debug(9, "%s", json->stringify(true).c_str()); - if (object.contains("server_modified")) { - //finished - Common::String path = object.getVal("path_lower")->asString(); - uint32 size = object.getVal("size")->asIntegerNumber(); - uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("server_modified")->asString()); - finishUpload(StorageFile(path, size, timestamp, false)); - return; + if (object.contains("error") || object.contains("error_summary")) { + if (Networking::CurlJsonRequest::jsonContainsString(object, "error_summary", "DropboxUploadRequest")) { + warning("Dropbox returned error: %s", object.getVal("error_summary")->asString().c_str()); } + error.response = json->stringify(true); + finishError(error); + delete json; + return; + } - if (_sessionId == "") { - if (object.contains("session_id")) - _sessionId = object.getVal("session_id")->asString(); - else - warning("DropboxUploadRequest: no session_id found"); - needsFinishRequest = true; - } + if (Networking::CurlJsonRequest::jsonContainsString(object, "path_lower", "DropboxUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(object, "server_modified", "DropboxUploadRequest") && + Networking::CurlJsonRequest::jsonContainsIntegerNumber(object, "size", "DropboxUploadRequest")) { + //finished + Common::String path = object.getVal("path_lower")->asString(); + uint32 size = object.getVal("size")->asIntegerNumber(); + uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("server_modified")->asString()); + finishUpload(StorageFile(path, size, timestamp, false)); + return; } - if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { - warning("DropboxUploadRequest: no file info to return"); - finishUpload(StorageFile(_savePath, 0, 0, false)); - } else { - uploadNextPart(); + if (_sessionId == "") { + if (Networking::CurlJsonRequest::jsonContainsString(object, "session_id", "DropboxUploadRequest")) + _sessionId = object.getVal("session_id")->asString(); + needsFinishRequest = true; } + } + + if (!needsFinishRequest && (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1)) { + warning("DropboxUploadRequest: no file info to return"); + finishUpload(StorageFile(_savePath, 0, 0, false)); } else { - warning("DropboxUploadRequest: null, not json"); - finishError(error); + uploadNextPart(); } delete json; -- cgit v1.2.3 From a381e06fda82508d16367b9999593de45c907e90 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 14:30:32 +0600 Subject: CLOUD: Update GoogleDriveStorage More JSON checks in callbacks. --- backends/cloud/box/boxstorage.cpp | 3 +- backends/cloud/googledrive/googledrivestorage.cpp | 61 +++++++++++++++++------ 2 files changed, 48 insertions(+), 16 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index 6209de0b70..70864679e7 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -118,7 +118,8 @@ void BoxStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResponse Common::JSONValue *json = response.value; if (!json) { warning("BoxStorage: got NULL instead of JSON"); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); delete callback; return; } diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 789dfaf53a..eb04e7e439 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -117,18 +117,27 @@ void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonR warning("GoogleDriveStorage: got NULL instead of JSON"); if (callback) (*callback)(BoolResponse(nullptr, false)); + delete callback; + return; + } + + if (!Networking::CurlJsonRequest::jsonIsObject(json, "GoogleDriveStorage")) { + if (callback) + (*callback)(BoolResponse(nullptr, false)); + delete json; + delete callback; return; } Common::JSONObject result = json->asObject(); - if (!result.contains("access_token")) { + if (!Networking::CurlJsonRequest::jsonContainsString(result, "access_token", "GoogleDriveStorage")) { warning("GoogleDriveStorage: bad response, no token passed"); debug(9, "%s", json->stringify().c_str()); if (callback) (*callback)(BoolResponse(nullptr, false)); } else { _token = result.getVal("access_token")->asString(); - if (!result.contains("refresh_token")) + if (!Networking::CurlJsonRequest::jsonContainsString(result, "refresh_token", "GoogleDriveStorage")) warning("GoogleDriveStorage: no refresh_token passed"); else _refreshToken = result.getVal("refresh_token")->asString(); @@ -137,6 +146,7 @@ void GoogleDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonR (*callback)(BoolResponse(nullptr, true)); } delete json; + delete callback; } void GoogleDriveStorage::codeFlowComplete(BoolResponse response) { @@ -169,7 +179,13 @@ Common::String GoogleDriveStorage::name() const { void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("GoogleDriveStorage: NULL passed instead of JSON"); + warning("GoogleDriveStorage::infoInnerCallback: NULL passed instead of JSON"); + delete outerCallback; + return; + } + + if (!Networking::CurlJsonRequest::jsonIsObject(json, "GoogleDriveStorage::infoInnerCallback")) { + delete json; delete outerCallback; return; } @@ -179,22 +195,33 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne Common::String uid, name, email; uint64 quotaUsed = 0, quotaAllocated = 0; - if (info.contains("user") && info.getVal("user")->isObject()) { + if (Networking::CurlJsonRequest::jsonContainsAttribute(info, "user", "GoogleDriveStorage::infoInnerCallback") && + Networking::CurlJsonRequest::jsonIsObject(info.getVal("user"), "GoogleDriveStorage::infoInnerCallback")) { //"me":true, "kind":"drive#user","photoLink": "", //"displayName":"Alexander Tkachev","emailAddress":"alexander@tkachov.ru","permissionId":"" Common::JSONObject user = info.getVal("user")->asObject(); - uid = user.getVal("permissionId")->asString(); //not sure it's user's id, but who cares anyway? - name = user.getVal("displayName")->asString(); - email = user.getVal("emailAddress")->asString(); + if (Networking::CurlJsonRequest::jsonContainsString(user, "permissionId", "GoogleDriveStorage::infoInnerCallback")) + uid = user.getVal("permissionId")->asString(); //not sure it's user's id, but who cares anyway? + if (Networking::CurlJsonRequest::jsonContainsString(user, "displayName", "GoogleDriveStorage::infoInnerCallback")) + name = user.getVal("displayName")->asString(); + if (Networking::CurlJsonRequest::jsonContainsString(user, "emailAddress", "GoogleDriveStorage::infoInnerCallback")) + email = user.getVal("emailAddress")->asString(); } - if (info.contains("storageQuota") && info.getVal("storageQuota")->isObject()) { + if (Networking::CurlJsonRequest::jsonContainsAttribute(info, "storageQuota", "GoogleDriveStorage::infoInnerCallback") && + Networking::CurlJsonRequest::jsonIsObject(info.getVal("storageQuota"), "GoogleDriveStorage::infoInnerCallback")) { //"usageInDrive":"6332462","limit":"18253611008","usage":"6332462","usageInDriveTrash":"0" Common::JSONObject storageQuota = info.getVal("storageQuota")->asObject(); - Common::String usage = storageQuota.getVal("usage")->asString(); - Common::String limit = storageQuota.getVal("limit")->asString(); - quotaUsed = usage.asUint64(); - quotaAllocated = limit.asUint64(); + + if (Networking::CurlJsonRequest::jsonContainsString(storageQuota, "usage", "GoogleDriveStorage::infoInnerCallback")) { + Common::String usage = storageQuota.getVal("usage")->asString(); + quotaUsed = usage.asUint64(); + } + + if (Networking::CurlJsonRequest::jsonContainsString(storageQuota, "limit", "GoogleDriveStorage::infoInnerCallback")) { + Common::String limit = storageQuota.getVal("limit")->asString(); + quotaAllocated = limit.asUint64(); + } } CloudMan.setStorageUsername(kStorageGoogleDriveId, email); @@ -210,14 +237,18 @@ void GoogleDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Ne void GoogleDriveStorage::createDirectoryInnerCallback(BoolCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("GoogleDriveStorage: NULL passed instead of JSON"); + warning("GoogleDriveStorage::createDirectoryInnerCallback: NULL passed instead of JSON"); delete outerCallback; return; } if (outerCallback) { - Common::JSONObject info = json->asObject(); - (*outerCallback)(BoolResponse(nullptr, info.contains("id"))); + if (Networking::CurlJsonRequest::jsonIsObject(json, "GoogleDriveStorage::createDirectoryInnerCallback")) { + Common::JSONObject info = json->asObject(); + (*outerCallback)(BoolResponse(nullptr, info.contains("id"))); + } else { + (*outerCallback)(BoolResponse(nullptr, false)); + } delete outerCallback; } -- cgit v1.2.3 From d34b9b91add07c8bed2d2cef6421fc1b93b2e09e Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 14:40:21 +0600 Subject: CLOUD: Update GoogleDriveUploadRequest JSON checks in callback. --- .../cloud/googledrive/googledriveuploadrequest.cpp | 68 +++++++++++----------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledriveuploadrequest.cpp b/backends/cloud/googledrive/googledriveuploadrequest.cpp index 14f43eecde..5f61dcd2a8 100644 --- a/backends/cloud/googledrive/googledriveuploadrequest.cpp +++ b/backends/cloud/googledrive/googledriveuploadrequest.cpp @@ -275,44 +275,46 @@ void GoogleDriveUploadRequest::partUploadedCallback(Networking::JsonResponse res } Common::JSONValue *json = response.value; - if (json) { - if (json->isObject()) { - Common::JSONObject object = json->asObject(); - - if (object.contains("error")) { - warning("GoogleDrive returned error: %s", json->stringify(true).c_str()); - error.response = json->stringify(true); - finishError(error); - delete json; - return; - } + if (json == nullptr) { + error.response = "Failed to parse JSON, null passed!"; + finishError(error); + return; + } - if (object.contains("id") && object.contains("name")) { - //finished - Common::String id = object.getVal("id")->asString(); - Common::String name = object.getVal("name")->asString(); - bool isDirectory = (object.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); - uint32 size = 0, timestamp = 0; - if (object.contains("size") && object.getVal("size")->isString()) - size = object.getVal("size")->asString().asUint64(); - if (object.contains("modifiedTime") && object.getVal("modifiedTime")->isString()) - timestamp = ISO8601::convertToTimestamp(object.getVal("modifiedTime")->asString()); - - //as we list directory by id, we can't determine full path for the file, so we leave it empty - finishUpload(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); - return; - } + if (json->isObject()) { + Common::JSONObject object = json->asObject(); + + if (object.contains("error")) { + warning("GoogleDrive returned error: %s", json->stringify(true).c_str()); + error.response = json->stringify(true); + finishError(error); + delete json; + return; } - if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { - warning("GoogleDriveUploadRequest: no file info to return"); - finishUpload(StorageFile(_savePath, 0, 0, false)); - } else { - uploadNextPart(); + if (Networking::CurlJsonRequest::jsonContainsString(object, "id", "GoogleDriveUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(object, "name", "GoogleDriveUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(object, "mimeType", "GoogleDriveUploadRequest")) { + //finished + Common::String id = object.getVal("id")->asString(); + Common::String name = object.getVal("name")->asString(); + bool isDirectory = (object.getVal("mimeType")->asString() == "application/vnd.google-apps.folder"); + uint32 size = 0, timestamp = 0; + if (Networking::CurlJsonRequest::jsonContainsString(object, "size", "GoogleDriveUploadRequest", true)) + size = object.getVal("size")->asString().asUint64(); + if (Networking::CurlJsonRequest::jsonContainsString(object, "modifiedTime", "GoogleDriveUploadRequest", true)) + timestamp = ISO8601::convertToTimestamp(object.getVal("modifiedTime")->asString()); + + finishUpload(StorageFile(id, _savePath, name, size, timestamp, isDirectory)); + return; } + } + + if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { + warning("GoogleDriveUploadRequest: no file info to return"); + finishUpload(StorageFile(_savePath, 0, 0, false)); } else { - warning("GoogleDriveUploadRequest: null, not json"); - finishError(error); + uploadNextPart(); } delete json; -- cgit v1.2.3 From fc8e29d5832728a513cab0f10be218c6a632758a Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 14:53:44 +0600 Subject: CLOUD: Update OneDrive Added JSON checks. New jsonContainsObject() method added to CurlJsonRequest. --- backends/cloud/googledrive/googledrivestorage.cpp | 2 +- .../onedrive/onedrivecreatedirectoryrequest.cpp | 11 +++- backends/cloud/onedrive/onedrivestorage.cpp | 74 ++++++++++++++++------ 3 files changed, 65 insertions(+), 22 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index eb04e7e439..1b4b8baf56 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -93,7 +93,7 @@ void GoogleDriveStorage::getAccessToken(BoolCallback callback, Networking::Error Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &GoogleDriveStorage::tokenRefreshed, callback); if (errorCallback == nullptr) errorCallback = getErrorPrintingCallback(); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, GOOGLEDRIVE_OAUTH2_TOKEN); //TODO + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, GOOGLEDRIVE_OAUTH2_TOKEN); if (codeFlow) { request->addPostField("code=" + code); request->addPostField("grant_type=authorization_code"); diff --git a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp index 4d6d8fceda..fc7e4f58b0 100644 --- a/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp +++ b/backends/cloud/onedrive/onedrivecreatedirectoryrequest.cpp @@ -101,12 +101,19 @@ void OneDriveCreateDirectoryRequest::responseCallback(Networking::JsonResponse r if (rq && rq->getNetworkReadStream()) error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode(); - if (!json) { - warning("OneDriveCreateDirectoryRequest: NULL passed instead of JSON"); + 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 info = json->asObject(); if (info.contains("id")) { finishCreation(true); diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 9fde2ed2c7..4b70bb73b9 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -116,12 +116,24 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResp Common::JSONValue *json = response.value; if (!json) { warning("OneDriveStorage: got NULL instead of JSON"); - if (callback) (*callback)(BoolResponse(nullptr, false)); + if (callback) + (*callback)(BoolResponse(nullptr, false)); + delete callback; + return; + } + + if (!Networking::CurlJsonRequest::jsonIsObject(json, "OneDriveStorage")) { + if (callback) + (*callback)(BoolResponse(nullptr, false)); + delete json; + delete callback; return; } Common::JSONObject result = json->asObject(); - if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) { + if (!Networking::CurlJsonRequest::jsonContainsString(result, "access_token", "OneDriveStorage") || + !Networking::CurlJsonRequest::jsonContainsString(result, "user_id", "OneDriveStorage") || + !Networking::CurlJsonRequest::jsonContainsString(result, "refresh_token", "OneDriveStorage")) { warning("OneDriveStorage: bad response, no token or user_id passed"); debug(9, "%s", json->stringify().c_str()); if (callback) @@ -135,6 +147,7 @@ void OneDriveStorage::tokenRefreshed(BoolCallback callback, Networking::JsonResp (*callback)(BoolResponse(nullptr, true)); } delete json; + delete callback; } void OneDriveStorage::codeFlowComplete(BoolResponse response) { @@ -168,7 +181,13 @@ Common::String OneDriveStorage::name() const { void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking::JsonResponse response) { Common::JSONValue *json = response.value; if (!json) { - warning("OneDriveStorage: NULL passed instead of JSON"); + warning("OneDriveStorage::infoInnerCallback: NULL passed instead of JSON"); + delete outerCallback; + return; + } + + if (!Networking::CurlJsonRequest::jsonIsObject(json, "OneDriveStorage::infoInnerCallback")) { + delete json; delete outerCallback; return; } @@ -178,16 +197,18 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo Common::String uid, name, email; uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one - if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) { + if (Networking::CurlJsonRequest::jsonContainsObject(info, "createdBy", "OneDriveStorage::infoInnerCallback")) { Common::JSONObject createdBy = info.getVal("createdBy")->asObject(); - if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) { + if (Networking::CurlJsonRequest::jsonContainsObject(createdBy, "user", "OneDriveStorage::infoInnerCallback")) { Common::JSONObject user = createdBy.getVal("user")->asObject(); - uid = user.getVal("id")->asString(); - name = user.getVal("displayName")->asString(); + if (Networking::CurlJsonRequest::jsonContainsString(user, "id", "OneDriveStorage::infoInnerCallback")) + uid = user.getVal("id")->asString(); + if (Networking::CurlJsonRequest::jsonContainsString(user, "displayName", "OneDriveStorage::infoInnerCallback")) + name = user.getVal("displayName")->asString(); } } - if (info.contains("size") && info.getVal("size")->isIntegerNumber()) { + if (Networking::CurlJsonRequest::jsonContainsIntegerNumber(info, "size", "OneDriveStorage::infoInnerCallback")) { quotaUsed = info.getVal("size")->asIntegerNumber(); } @@ -207,28 +228,43 @@ void OneDriveStorage::infoInnerCallback(StorageInfoCallback outerCallback, Netwo } void OneDriveStorage::fileInfoCallback(Networking::NetworkReadStreamCallback outerCallback, Networking::JsonResponse response) { - if (!response.value) { - warning("OneDriveStorage::fileInfoCallback: NULL, not JSON"); + Common::JSONValue *json = response.value; + if (!json) { + warning("OneDriveStorage::fileInfoCallback: NULL passed instead of JSON"); if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); + delete outerCallback; return; } - Common::JSONObject result = response.value->asObject(); - if (result.contains("@content.downloadUrl")) { - const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); + if (!Networking::CurlJsonRequest::jsonIsObject(json, "OneDriveStorage::fileInfoCallback")) { if (outerCallback) - (*outerCallback)(Networking::NetworkReadStreamResponse( - response.request, - new Networking::NetworkReadStream(url, nullptr, "") - )); - } else { + (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); + delete json; + delete outerCallback; + return; + } + + Common::JSONObject result = response.value->asObject(); + if (!Networking::CurlJsonRequest::jsonContainsString(result, "@content.downloadUrl", "OneDriveStorage::fileInfoCallback")) { warning("OneDriveStorage: downloadUrl not found in passed JSON"); debug(9, "%s", response.value->stringify().c_str()); if (outerCallback) (*outerCallback)(Networking::NetworkReadStreamResponse(response.request, nullptr)); + delete json; + delete outerCallback; + return; } - delete response.value; + + const char *url = result.getVal("@content.downloadUrl")->asString().c_str(); + if (outerCallback) + (*outerCallback)(Networking::NetworkReadStreamResponse( + response.request, + new Networking::NetworkReadStream(url, nullptr, "") + )); + + delete json; + delete outerCallback; } Networking::Request *OneDriveStorage::listDirectory(Common::String path, ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { -- cgit v1.2.3 From d5aca1f4fae400250b87d35e3517416dd4f26a8f Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 14:59:01 +0600 Subject: CLOUD: Update OneDriveUploadRequest More JSON checks. --- backends/cloud/onedrive/onedriveuploadrequest.cpp | 70 ++++++++++++----------- 1 file changed, 36 insertions(+), 34 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/onedrive/onedriveuploadrequest.cpp b/backends/cloud/onedrive/onedriveuploadrequest.cpp index 172266ce2a..41e6e2a37b 100644 --- a/backends/cloud/onedrive/onedriveuploadrequest.cpp +++ b/backends/cloud/onedrive/onedriveuploadrequest.cpp @@ -125,44 +125,46 @@ void OneDriveUploadRequest::partUploadedCallback(Networking::JsonResponse respon 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("OneDriveUploadRequest: error: %s", json->stringify(true).c_str()); - error.response = json->stringify(true); - finishError(error); - delete json; - return; - } - - if (object.contains("id") && object.contains("name")) { - //finished - Common::String path = _savePath; - uint32 size = object.getVal("size")->asIntegerNumber(); - uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("lastModifiedDateTime")->asString()); - finishUpload(StorageFile(path, size, timestamp, false)); - return; - } - - if (_uploadUrl == "") { - if (object.contains("uploadUrl")) - _uploadUrl = object.getVal("uploadUrl")->asString(); - else - warning("OneDriveUploadRequest: no uploadUrl found"); - } + if (json == nullptr) { + error.response = "Failed to parse JSON, null passed!"; + finishError(error); + return; + } + + if (json->isObject()) { + Common::JSONObject object = json->asObject(); + + if (object.contains("error")) { + warning("OneDriveUploadRequest: error: %s", json->stringify(true).c_str()); + error.response = json->stringify(true); + finishError(error); + delete json; + return; } - if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { - warning("OneDriveUploadRequest: no file info to return"); - finishUpload(StorageFile(_savePath, 0, 0, false)); - } else { - uploadNextPart(); + if (Networking::CurlJsonRequest::jsonContainsString(object, "id", "OneDriveUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(object, "name", "OneDriveUploadRequest") && + Networking::CurlJsonRequest::jsonContainsIntegerNumber(object, "size", "OneDriveUploadRequest") && + Networking::CurlJsonRequest::jsonContainsString(object, "lastModifiedDateTime", "OneDriveUploadRequest")) { + //finished + Common::String path = _savePath; + uint32 size = object.getVal("size")->asIntegerNumber(); + uint32 timestamp = ISO8601::convertToTimestamp(object.getVal("lastModifiedDateTime")->asString()); + finishUpload(StorageFile(path, size, timestamp, false)); + return; } + + if (_uploadUrl == "") { + if (Networking::CurlJsonRequest::jsonContainsString(object, "uploadUrl", "OneDriveUploadRequest")) + _uploadUrl = object.getVal("uploadUrl")->asString(); + } + } + + if (_contentsStream->eos() || _contentsStream->pos() >= _contentsStream->size() - 1) { + warning("OneDriveUploadRequest: no file info to return"); + finishUpload(StorageFile(_savePath, 0, 0, false)); } else { - warning("OneDriveUploadRequest: null, not json"); - finishError(error); + uploadNextPart(); } delete json; -- cgit v1.2.3 From bb529e6fd0bcbd69f804c599c9d685181560a337 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 15:04:56 +0600 Subject: CLOUD: Update SavesSyncRequest Add JSON checks in the callback. --- backends/cloud/savessyncrequest.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 889c6b936b..9c487bb987 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -22,6 +22,8 @@ #include "backends/cloud/savessyncrequest.h" #include "backends/cloud/cloudmanager.h" +#include "backends/networking/curl/curljsonrequest.h" +#include "backends/saves/default/default-saves.h" #include "common/config-manager.h" #include "common/debug.h" #include "common/file.h" @@ -29,7 +31,6 @@ #include "common/savefile.h" #include "common/system.h" #include "gui/saveload-dialog.h" -#include namespace Cloud { @@ -152,7 +153,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er Common::JSONObject object = value->asObject(); //Dropbox-related error: - if (object.contains("error_summary")) { + if (Networking::CurlJsonRequest::jsonContainsString(object, "error_summary", "SavesSyncRequest", true)) { Common::String summary = object.getVal("error_summary")->asString(); if (summary.contains("not_found")) { irrecoverable = false; @@ -160,9 +161,9 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er } //OneDrive-related error: - if (object.contains("error") && object.getVal("error")->isObject()) { + if (Networking::CurlJsonRequest::jsonContainsObject(object, "error", "SavesSyncRequest", true)) { Common::JSONObject errorNode = object.getVal("error")->asObject(); - if (errorNode.contains("code") && errorNode.contains("message")) { + if (Networking::CurlJsonRequest::jsonContainsString(errorNode, "code", "SavesSyncRequest")) { Common::String code = errorNode.getVal("code")->asString(); if (code == "itemNotFound") { irrecoverable = false; -- cgit v1.2.3 From 37859a92039fe6df705024f45f84e1fbc4df806d Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Tue, 26 Jul 2016 15:54:48 +0600 Subject: CLOUD: Fix Requests Remove unnecessary JSON warnings, fix a few places. --- backends/cloud/box/boxuploadrequest.cpp | 2 +- backends/cloud/googledrive/googledrivetokenrefresher.cpp | 2 +- backends/cloud/onedrive/onedrivetokenrefresher.cpp | 2 +- backends/cloud/savessyncrequest.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxuploadrequest.cpp b/backends/cloud/box/boxuploadrequest.cpp index 929c9ceb75..5084aa5652 100644 --- a/backends/cloud/box/boxuploadrequest.cpp +++ b/backends/cloud/box/boxuploadrequest.cpp @@ -165,7 +165,7 @@ void BoxUploadRequest::uploadedCallback(Networking::JsonResponse response) { Common::JSONArray entries = object.getVal("entries")->asArray(); if (entries.size() == 0) { warning("BoxUploadRequest: 'entries' found, but it's empty"); - } else if (Networking::CurlJsonRequest::jsonIsObject(entries[0], "BoxUploadRequest")) { + } else if (!Networking::CurlJsonRequest::jsonIsObject(entries[0], "BoxUploadRequest")) { warning("BoxUploadRequest: 'entries' first item is not an object"); } else { Common::JSONObject item = entries[0]->asObject(); diff --git a/backends/cloud/googledrive/googledrivetokenrefresher.cpp b/backends/cloud/googledrive/googledrivetokenrefresher.cpp index 7d68510655..8cc492d6b4 100644 --- a/backends/cloud/googledrive/googledrivetokenrefresher.cpp +++ b/backends/cloud/googledrive/googledrivetokenrefresher.cpp @@ -66,7 +66,7 @@ void GoogleDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (jsonIsObject(json, "GoogleDriveTokenRefresher")) { Common::JSONObject result = json->asObject(); long httpResponseCode = -1; - if (jsonContainsAttribute(result, "error", "GoogleDriveTokenRefresher") && jsonIsObject(result.getVal("error"), "GoogleDriveTokenRefresher")) { + if (result.contains("error") && jsonIsObject(result.getVal("error"), "GoogleDriveTokenRefresher")) { //new token needed => request token & then retry original request if (_stream) { httpResponseCode = _stream->httpResponseCode(); diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp index 5ee2772ba7..ce7895f41c 100644 --- a/backends/cloud/onedrive/onedrivetokenrefresher.cpp +++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp @@ -66,7 +66,7 @@ void OneDriveTokenRefresher::finishJson(Common::JSONValue *json) { if (jsonIsObject(json, "OneDriveTokenRefresher")) { Common::JSONObject result = json->asObject(); long httpResponseCode = -1; - if (jsonContainsAttribute(result, "error", "OneDriveTokenRefresher") && jsonIsObject(result.getVal("error"), "OneDriveTokenRefresher")) { + if (result.contains("error") && jsonIsObject(result.getVal("error"), "OneDriveTokenRefresher")) { //new token needed => request token & then retry original request if (_stream) { httpResponseCode = _stream->httpResponseCode(); diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp index 9c487bb987..fff46c3a83 100644 --- a/backends/cloud/savessyncrequest.cpp +++ b/backends/cloud/savessyncrequest.cpp @@ -153,7 +153,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er Common::JSONObject object = value->asObject(); //Dropbox-related error: - if (Networking::CurlJsonRequest::jsonContainsString(object, "error_summary", "SavesSyncRequest", true)) { + if (object.contains("error_summary") && object.getVal("error_summary")->isString()) { Common::String summary = object.getVal("error_summary")->asString(); if (summary.contains("not_found")) { irrecoverable = false; @@ -161,7 +161,7 @@ void SavesSyncRequest::directoryListedErrorCallback(Networking::ErrorResponse er } //OneDrive-related error: - if (Networking::CurlJsonRequest::jsonContainsObject(object, "error", "SavesSyncRequest", true)) { + if (object.contains("error") && object.getVal("error")->isObject()) { Common::JSONObject errorNode = object.getVal("error")->asObject(); if (Networking::CurlJsonRequest::jsonContainsString(errorNode, "code", "SavesSyncRequest")) { Common::String code = errorNode.getVal("code")->asString(); -- cgit v1.2.3 From 0558ba423cb9cdd5f9cd29a1c47a0530399b2399 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 29 Jul 2016 05:34:35 +0300 Subject: CLOUD: Fix warnings --- backends/cloud/storagefile.h | 2 +- backends/cloud/storageinfo.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/storagefile.h b/backends/cloud/storagefile.h index 1324cafc93..1183524f48 100644 --- a/backends/cloud/storagefile.h +++ b/backends/cloud/storagefile.h @@ -57,7 +57,7 @@ public: uint32 timestamp() const { return _timestamp; } bool isDirectory() const { return _isDirectory; } - void setPath(Common::String path) { _path = path; } + void setPath(Common::String path_) { _path = path_; } }; } // End of namespace Cloud diff --git a/backends/cloud/storageinfo.h b/backends/cloud/storageinfo.h index 469f0402c0..f1fb540974 100644 --- a/backends/cloud/storageinfo.h +++ b/backends/cloud/storageinfo.h @@ -37,8 +37,8 @@ class StorageInfo { uint64 _usedBytes, _allocatedBytes; public: - StorageInfo(Common::String uid, Common::String name, Common::String email, uint64 used, uint64 allocated): - _uid(uid), _name(name), _email(email), _usedBytes(used), _allocatedBytes(allocated) {} + StorageInfo(Common::String uid_, Common::String name_, Common::String email_, uint64 used_, uint64 allocated): + _uid(uid_), _name(name_), _email(email_), _usedBytes(used_), _allocatedBytes(allocated) {} Common::String uid() const { return _uid; } Common::String name() const { return _name; } -- cgit v1.2.3 From 02a997e468041ca0d7a2e9ac95e0b7dd6144c6eb Mon Sep 17 00:00:00 2001 From: Peter Bozsó Date: Wed, 3 Aug 2016 10:54:18 +0200 Subject: CLOUD: Remove unused includes --- backends/cloud/box/boxstorage.h | 1 - backends/cloud/dropbox/dropboxuploadrequest.cpp | 1 - backends/cloud/id/idstorage.cpp | 1 - 3 files changed, 3 deletions(-) (limited to 'backends/cloud') diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index 018562379f..2dd516d894 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -24,7 +24,6 @@ #define BACKENDS_CLOUD_BOX_BOXSTORAGE_H #include "backends/cloud/id/idstorage.h" -#include "common/callback.h" #include "backends/networking/curl/curljsonrequest.h" namespace Cloud { diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp index 945493b1eb..2c9dcc4109 100644 --- a/backends/cloud/dropbox/dropboxuploadrequest.cpp +++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp @@ -27,7 +27,6 @@ #include "backends/networking/curl/curljsonrequest.h" #include "backends/networking/curl/networkreadstream.h" #include "common/json.h" -#include "common/debug.h" namespace Cloud { namespace Dropbox { diff --git a/backends/cloud/id/idstorage.cpp b/backends/cloud/id/idstorage.cpp index 36f2df642c..0ffa8c068c 100644 --- a/backends/cloud/id/idstorage.cpp +++ b/backends/cloud/id/idstorage.cpp @@ -28,7 +28,6 @@ #include "backends/cloud/id/idresolveidrequest.h" #include "backends/cloud/id/idstreamfilerequest.h" #include "common/debug.h" -#include "common/json.h" namespace Cloud { namespace Id { -- cgit v1.2.3