diff options
-rw-r--r-- | backends/cloud/dropbox/dropboxstorage.cpp | 1 | ||||
-rw-r--r-- | backends/networking/curl/connectionmanager.cpp | 2 | ||||
-rw-r--r-- | backends/networking/curl/curljsonrequest.cpp | 36 | ||||
-rw-r--r-- | backends/networking/curl/curljsonrequest.h | 6 | ||||
-rw-r--r-- | backends/networking/curl/networkreadstream.cpp | 9 | ||||
-rw-r--r-- | backends/networking/curl/networkreadstream.h | 16 |
6 files changed, 59 insertions, 11 deletions
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 diff --git a/backends/networking/curl/connectionmanager.cpp b/backends/networking/curl/connectionmanager.cpp index ceff8b62a4..8c718e019b 100644 --- a/backends/networking/curl/connectionmanager.cpp +++ b/backends/networking/curl/connectionmanager.cpp @@ -56,7 +56,7 @@ void ConnectionManager::handle() { NetworkReadStream *stream; curl_easy_getinfo(easyHandle, CURLINFO_PRIVATE, &stream); - if (stream) stream->done(); //I'm not sure it's OK to notify "done()" on failure + if (stream) stream->finished(); if (curlMsg->msg == CURLMSG_DONE) { debug("ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result)); diff --git a/backends/networking/curl/curljsonrequest.cpp b/backends/networking/curl/curljsonrequest.cpp index acd9675aed..f5a7a7c8d0 100644 --- a/backends/networking/curl/curljsonrequest.cpp +++ b/backends/networking/curl/curljsonrequest.cpp @@ -30,7 +30,7 @@ namespace Networking { -CurlJsonRequest::CurlJsonRequest(Callback cb, const char *url) : Request(cb), _stream(0) { +CurlJsonRequest::CurlJsonRequest(Callback cb, const char *url) : Request(cb), _stream(0), _contentsStream(DisposeAfterUse::YES) { _url = url; } @@ -38,6 +38,24 @@ CurlJsonRequest::~CurlJsonRequest() { if (_stream) delete _stream; } +char *CurlJsonRequest::getPreparedContents() { + //write one more byte in the end + byte zero[1] = { 0 }; + _contentsStream.write(zero, 1); + + //replace all "bad" bytes with '.' character + byte *result = _contentsStream.getData(); + uint32 size = _contentsStream.size(); + for (uint32 i = 0; i < size; ++i) + if (result[i] < 0x20 || result[i] > 0x7f) + result[i] = '.'; + + //make it zero-terminated string + result[size - 1] = '\0'; + + return (char *)result; +} + bool CurlJsonRequest::handle(ConnectionManager &manager) { if (!_stream) _stream = manager.makeRequest(_url); @@ -45,13 +63,17 @@ bool CurlJsonRequest::handle(ConnectionManager &manager) { const int kBufSize = 16*1024; char buf[kBufSize+1]; uint32 readBytes = _stream->read(buf, kBufSize); - if (readBytes != 0) _contents += Common::String(buf, readBytes); - if (_stream->eos()) { - //TODO: check that stream's CURL easy handle's HTTP response code is 200 OK - debug("CurlJsonRequest: contents:\n%s", _contents.c_str()); + if (readBytes != 0) + if (_contentsStream.write(buf, readBytes) != readBytes) + warning("MemoryWriteStreamDynamic was unable to write all the bytes"); + + if (_stream->eos()) { + if (_stream->httpResponseCode() != 200) + warning("HTTP response code is not 200 OK"); + if (_callback) { - Common::JSONValue *json = Common::JSON::parse(_contents.c_str()); //TODO: somehow fix JSON to work with UTF-8 - debug("CurlJsonRequest: JSONValue pointer = %p", json); + char *contents = getPreparedContents(); + Common::JSONValue *json = Common::JSON::parse(contents); _callback(json); //potential memory leak, free it in your callbacks! } return true; diff --git a/backends/networking/curl/curljsonrequest.h b/backends/networking/curl/curljsonrequest.h index 73e0144c64..e9634393dc 100644 --- a/backends/networking/curl/curljsonrequest.h +++ b/backends/networking/curl/curljsonrequest.h @@ -24,6 +24,7 @@ #define BACKENDS_NETWORKING_CURL_CURLJSONREQUEST_H #include "backends/cloud/request.h" +#include "common/memstream.h" namespace Networking { @@ -32,7 +33,10 @@ class NetworkReadStream; class CurlJsonRequest : public Cloud::Request { const char *_url; NetworkReadStream *_stream; - Common::String _contents; + Common::MemoryWriteStreamDynamic _contentsStream; + + /** Prepares raw bytes from _contentsStream to be parsed with Common::JSON::parse(). */ + char *getPreparedContents(); public: CurlJsonRequest(Callback cb, const char *url); diff --git a/backends/networking/curl/networkreadstream.cpp b/backends/networking/curl/networkreadstream.cpp index 5049ae507b..b8cb81aca2 100644 --- a/backends/networking/curl/networkreadstream.cpp +++ b/backends/networking/curl/networkreadstream.cpp @@ -63,8 +63,15 @@ uint32 NetworkReadStream::read(void *dataPtr, uint32 dataSize) { return actuallyRead; } -void NetworkReadStream::done() { +void NetworkReadStream::finished() { _requestComplete = true; } +long NetworkReadStream::httpResponseCode() { + long responseCode = -1; + if (_easy) + curl_easy_getinfo(_easy, CURLINFO_RESPONSE_CODE, &responseCode); + return responseCode; +} + } //end of namespace Cloud diff --git a/backends/networking/curl/networkreadstream.h b/backends/networking/curl/networkreadstream.h index 9c7d8f83b6..0333e4fb16 100644 --- a/backends/networking/curl/networkreadstream.h +++ b/backends/networking/curl/networkreadstream.h @@ -67,7 +67,21 @@ public: */ virtual uint32 read(void *dataPtr, uint32 dataSize); - void done(); + /** + * This method is called by ConnectionManager to indicate + * that transfer is finished. + * + * @note It's called on failure too. + */ + void finished(); + + /** + * Returns HTTP response code from inner CURL handle. + * It returns -1 to indicate there is no inner handle. + * + * @note This method should be called when eos() == true. + */ + long httpResponseCode(); }; } //end of namespace Cloud |