CLOUD: Upload ListDirectory Requests
Lots of checks to avoid JSON-related segfaults added.
This commit is contained in:
parent
f95073f008
commit
f3959e1401
6 changed files with 117 additions and 39 deletions
|
@ -43,15 +43,13 @@ BoxListDirectoryByIdRequest::BoxListDirectoryByIdRequest(BoxStorage *storage, Co
|
||||||
|
|
||||||
BoxListDirectoryByIdRequest::~BoxListDirectoryByIdRequest() {
|
BoxListDirectoryByIdRequest::~BoxListDirectoryByIdRequest() {
|
||||||
_ignoreCallback = true;
|
_ignoreCallback = true;
|
||||||
if (_workingRequest)
|
if (_workingRequest) _workingRequest->finish();
|
||||||
_workingRequest->finish();
|
|
||||||
delete _listDirectoryCallback;
|
delete _listDirectoryCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoxListDirectoryByIdRequest::start() {
|
void BoxListDirectoryByIdRequest::start() {
|
||||||
_ignoreCallback = true;
|
_ignoreCallback = true;
|
||||||
if (_workingRequest)
|
if (_workingRequest) _workingRequest->finish();
|
||||||
_workingRequest->finish();
|
|
||||||
_files.clear();
|
_files.clear();
|
||||||
_ignoreCallback = false;
|
_ignoreCallback = false;
|
||||||
|
|
||||||
|
@ -76,8 +74,11 @@ void BoxListDirectoryByIdRequest::makeRequest(uint32 offset) {
|
||||||
|
|
||||||
void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) {
|
void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) {
|
||||||
_workingRequest = nullptr;
|
_workingRequest = nullptr;
|
||||||
if (_ignoreCallback)
|
if (_ignoreCallback) {
|
||||||
|
delete response.value;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (response.request)
|
if (response.request)
|
||||||
_date = response.request->date();
|
_date = response.request->date();
|
||||||
|
|
||||||
|
@ -103,7 +104,7 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp
|
||||||
Common::JSONObject responseObject = json->asObject();
|
Common::JSONObject responseObject = json->asObject();
|
||||||
//debug(9, "%s", json->stringify(true).c_str());
|
//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")) {
|
if (responseObject.contains("error") || responseObject.contains("error_summary")) {
|
||||||
warning("Box returned error: %s", responseObject.getVal("error_summary")->asString().c_str());
|
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();
|
Common::JSONArray items = responseObject.getVal("entries")->asArray();
|
||||||
for (uint32 i = 0; i < items.size(); ++i) {
|
for (uint32 i = 0; i < items.size(); ++i) {
|
||||||
if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "BoxListDirectoryByIdRequest"))
|
if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "BoxListDirectoryByIdRequest")) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
Common::JSONObject item = items[i]->asObject();
|
Common::JSONObject item = items[i]->asObject();
|
||||||
|
|
||||||
if (!Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxListDirectoryByIdRequest"))
|
if (!Networking::CurlJsonRequest::jsonContainsString(item, "id", "BoxListDirectoryByIdRequest")) continue;
|
||||||
continue;
|
if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxListDirectoryByIdRequest")) continue;
|
||||||
if (!Networking::CurlJsonRequest::jsonContainsString(item, "name", "BoxListDirectoryByIdRequest"))
|
if (!Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxListDirectoryByIdRequest")) continue;
|
||||||
continue;
|
if (!Networking::CurlJsonRequest::jsonContainsString(item, "modified_at", "BoxListDirectoryByIdRequest")) continue;
|
||||||
if (!Networking::CurlJsonRequest::jsonContainsString(item, "type", "BoxListDirectoryByIdRequest"))
|
if (!Networking::CurlJsonRequest::jsonContainsStringOrIntegerNumber(item, "size", "BoxListDirectoryByIdRequest")) continue;
|
||||||
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 id = item.getVal("id")->asString();
|
||||||
Common::String name = item.getVal("name")->asString();
|
Common::String name = item.getVal("name")->asString();
|
||||||
|
@ -172,20 +166,16 @@ void BoxListDirectoryByIdRequest::responseCallback(Networking::JsonResponse resp
|
||||||
received += responseObject.getVal("limit")->asIntegerNumber();
|
received += responseObject.getVal("limit")->asIntegerNumber();
|
||||||
bool hasMore = (received < totalCount);
|
bool hasMore = (received < totalCount);
|
||||||
|
|
||||||
if (hasMore)
|
if (hasMore) makeRequest(received);
|
||||||
makeRequest(received);
|
else finishListing(_files);
|
||||||
else
|
|
||||||
finishListing(_files);
|
|
||||||
|
|
||||||
delete json;
|
delete json;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoxListDirectoryByIdRequest::errorCallback(Networking::ErrorResponse error) {
|
void BoxListDirectoryByIdRequest::errorCallback(Networking::ErrorResponse error) {
|
||||||
_workingRequest = nullptr;
|
_workingRequest = nullptr;
|
||||||
if (_ignoreCallback)
|
if (_ignoreCallback) return;
|
||||||
return;
|
if (error.request) _date = error.request->date();
|
||||||
if (error.request)
|
|
||||||
_date = error.request->date();
|
|
||||||
finishError(error);
|
finishError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +187,7 @@ Common::String BoxListDirectoryByIdRequest::date() const { return _date; }
|
||||||
|
|
||||||
void BoxListDirectoryByIdRequest::finishListing(Common::Array<StorageFile> &files) {
|
void BoxListDirectoryByIdRequest::finishListing(Common::Array<StorageFile> &files) {
|
||||||
Request::finishSuccess();
|
Request::finishSuccess();
|
||||||
if (_listDirectoryCallback)
|
if (_listDirectoryCallback) (*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files));
|
||||||
(*_listDirectoryCallback)(Storage::ListDirectoryResponse(this, files));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End of namespace Box
|
} // End of namespace Box
|
||||||
|
|
|
@ -71,8 +71,10 @@ void DropboxListDirectoryRequest::start() {
|
||||||
|
|
||||||
void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse response) {
|
void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse response) {
|
||||||
_workingRequest = nullptr;
|
_workingRequest = nullptr;
|
||||||
if (_ignoreCallback)
|
if (_ignoreCallback) {
|
||||||
|
delete response.value;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (response.request)
|
if (response.request)
|
||||||
_date = response.request->date();
|
_date = response.request->date();
|
||||||
|
|
|
@ -72,8 +72,10 @@ void GoogleDriveListDirectoryByIdRequest::makeRequest(Common::String pageToken)
|
||||||
|
|
||||||
void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) {
|
void GoogleDriveListDirectoryByIdRequest::responseCallback(Networking::JsonResponse response) {
|
||||||
_workingRequest = nullptr;
|
_workingRequest = nullptr;
|
||||||
if (_ignoreCallback)
|
if (_ignoreCallback) {
|
||||||
|
delete response.value;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (response.request)
|
if (response.request)
|
||||||
_date = response.request->date();
|
_date = response.request->date();
|
||||||
|
|
||||||
|
|
|
@ -104,20 +104,40 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo
|
||||||
if (rq && rq->getNetworkReadStream())
|
if (rq && rq->getNetworkReadStream())
|
||||||
error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
|
error.httpResponseCode = rq->getNetworkReadStream()->httpResponseCode();
|
||||||
|
|
||||||
if (!json) {
|
if (json == nullptr) {
|
||||||
error.failed = true;
|
error.response = "Failed to parse JSON, null passed!";
|
||||||
finishError(error);
|
finishError(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!json->isObject()) {
|
||||||
|
error.response = "Passed JSON is not an object!";
|
||||||
|
finishError(error);
|
||||||
|
delete json;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Common::JSONObject object = json->asObject();
|
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();
|
Common::JSONArray items = object.getVal("value")->asArray();
|
||||||
for (uint32 i = 0; i < items.size(); ++i) {
|
for (uint32 i = 0; i < items.size(); ++i) {
|
||||||
|
if (!Networking::CurlJsonRequest::jsonIsObject(items[i], "OneDriveListDirectoryRequest")) continue;
|
||||||
|
|
||||||
Common::JSONObject item = items[i]->asObject();
|
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();
|
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 size = item.getVal("size")->asIntegerNumber();
|
||||||
|
@ -132,6 +152,13 @@ void OneDriveListDirectoryRequest::listedDirectoryCallback(Networking::JsonRespo
|
||||||
|
|
||||||
bool hasMore = object.contains("@odata.nextLink");
|
bool hasMore = object.contains("@odata.nextLink");
|
||||||
if (hasMore) {
|
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());
|
makeRequest(object.getVal("@odata.nextLink")->asString());
|
||||||
} else {
|
} else {
|
||||||
listNextDirectory();
|
listNextDirectory();
|
||||||
|
|
|
@ -42,7 +42,7 @@ CurlJsonRequest::~CurlJsonRequest() {
|
||||||
|
|
||||||
char *CurlJsonRequest::getPreparedContents() {
|
char *CurlJsonRequest::getPreparedContents() {
|
||||||
//write one more byte in the end
|
//write one more byte in the end
|
||||||
byte zero[1] = { 0 };
|
byte zero[1] = {0};
|
||||||
_contentsStream.write(zero, 1);
|
_contentsStream.write(zero, 1);
|
||||||
|
|
||||||
//replace all "bad" bytes with '.' character
|
//replace all "bad" bytes with '.' character
|
||||||
|
@ -114,8 +114,12 @@ bool CurlJsonRequest::jsonIsObject(Common::JSONValue *item, const char *warningP
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CurlJsonRequest::jsonContainsString(Common::JSONObject &item, const char *key, const char *warningPrefix) {
|
bool CurlJsonRequest::jsonContainsString(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
|
||||||
if (!item.contains(key)) {
|
if (!item.contains(key)) {
|
||||||
|
if (isOptional) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
warning("%s: passed item misses the \"%s\" attribute!", warningPrefix, key);
|
warning("%s: passed item misses the \"%s\" attribute!", warningPrefix, key);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -127,8 +131,12 @@ bool CurlJsonRequest::jsonContainsString(Common::JSONObject &item, const char *k
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CurlJsonRequest::jsonContainsIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix) {
|
bool CurlJsonRequest::jsonContainsIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
|
||||||
if (!item.contains(key)) {
|
if (!item.contains(key)) {
|
||||||
|
if (isOptional) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
warning("%s: passed item misses the \"%s\" attribute!", warningPrefix, key);
|
warning("%s: passed item misses the \"%s\" attribute!", warningPrefix, key);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -140,4 +148,51 @@ bool CurlJsonRequest::jsonContainsIntegerNumber(Common::JSONObject &item, const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CurlJsonRequest::jsonContainsArray(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
|
||||||
|
if (!item.contains(key)) {
|
||||||
|
if (isOptional) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
warning("%s: passed item misses the \"%s\" attribute!", warningPrefix, key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.getVal(key)->isArray()) return true;
|
||||||
|
|
||||||
|
warning("%s: passed item's \"%s\" attribute is not an array!", warningPrefix, key);
|
||||||
|
debug(9, "%s", item.getVal(key)->stringify(true).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurlJsonRequest::jsonContainsStringOrIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
|
||||||
|
if (!item.contains(key)) {
|
||||||
|
if (isOptional) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
warning("%s: passed item misses the \"%s\" attribute!", warningPrefix, key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.getVal(key)->isString() || item.getVal(key)->isIntegerNumber()) return true;
|
||||||
|
|
||||||
|
warning("%s: passed item's \"%s\" attribute is neither a string or an integer!", warningPrefix, key);
|
||||||
|
debug(9, "%s", item.getVal(key)->stringify(true).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurlJsonRequest::jsonContainsAttribute(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
|
||||||
|
if (!item.contains(key)) {
|
||||||
|
if (isOptional) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
warning("%s: passed item misses the \"%s\" attribute!", warningPrefix, key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Networking
|
} // End of namespace Networking
|
||||||
|
|
|
@ -54,8 +54,11 @@ public:
|
||||||
virtual void restart();
|
virtual void restart();
|
||||||
|
|
||||||
static bool jsonIsObject(Common::JSONValue *item, const char *warningPrefix);
|
static bool jsonIsObject(Common::JSONValue *item, const char *warningPrefix);
|
||||||
static bool jsonContainsString(Common::JSONObject &item, const char *key, const char *warningPrefix);
|
static bool jsonContainsString(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional = false);
|
||||||
static bool jsonContainsIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix);
|
static bool jsonContainsIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional = false);
|
||||||
|
static bool jsonContainsArray(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional = false);
|
||||||
|
static bool jsonContainsStringOrIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional = false);
|
||||||
|
static bool jsonContainsAttribute(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Networking
|
} // End of namespace Networking
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue