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 = result.asUint64() + 1; uploadNextPart(); return true; } } return false; }
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 == 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 (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 { uploadNextPart(); } delete json; }
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; uploadNextPart(); }
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::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 == 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("GoogleDrive returned error: %s", json->stringify(true).c_str()); error.response = json->stringify(true); finishError(error); delete json; return; } 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 { uploadNextPart(); } delete json; }