ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

curljsonrequest.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #define FORBIDDEN_SYMBOL_ALLOW_ALL
00024 
00025 #include <curl/curl.h>
00026 #include "backends/networking/curl/curljsonrequest.h"
00027 #include "backends/networking/curl/connectionmanager.h"
00028 #include "backends/networking/curl/networkreadstream.h"
00029 #include "common/debug.h"
00030 #include "common/json.h"
00031 
00032 namespace Networking {
00033 
00034 CurlJsonRequest::CurlJsonRequest(JsonCallback cb, ErrorCallback ecb, Common::String url) :
00035     CurlRequest(nullptr, ecb, url), _jsonCallback(cb), _contentsStream(DisposeAfterUse::YES),
00036     _buffer(new byte[CURL_JSON_REQUEST_BUFFER_SIZE]) {}
00037 
00038 CurlJsonRequest::~CurlJsonRequest() {
00039     delete _jsonCallback;
00040     delete[] _buffer;
00041 }
00042 
00043 char *CurlJsonRequest::getPreparedContents() {
00044     //write one more byte in the end
00045     byte zero[1] = {0};
00046     _contentsStream.write(zero, 1);
00047 
00048     //replace all "bad" bytes with '.' character
00049     byte *result = _contentsStream.getData();
00050     uint32 size = _contentsStream.size();
00051     for (uint32 i = 0; i < size; ++i) {
00052         if (result[i] == '\n')
00053                 result[i] = ' '; //yeah, kinda stupid
00054         else if (result[i] < 0x20 || result[i] > 0x7f)
00055             result[i] = '.';
00056     }
00057 
00058     //make it zero-terminated string
00059     result[size - 1] = '\0';
00060 
00061     return (char *)result;
00062 }
00063 
00064 void CurlJsonRequest::handle() {
00065     if (!_stream) _stream = makeStream();
00066 
00067     if (_stream) {
00068         uint32 readBytes = _stream->read(_buffer, CURL_JSON_REQUEST_BUFFER_SIZE);
00069         if (readBytes != 0)
00070             if (_contentsStream.write(_buffer, readBytes) != readBytes)
00071                 warning("CurlJsonRequest: unable to write all the bytes into MemoryWriteStreamDynamic");
00072 
00073         if (_stream->eos()) {
00074             char *contents = getPreparedContents();
00075             Common::JSONValue *json = Common::JSON::parse(contents);
00076             if (json) {
00077                 finishJson(json); //it's JSON even if's not 200 OK? That's fine!..
00078             } else {
00079                 if (_stream->httpResponseCode() == 200) //no JSON, but 200 OK? That's fine!..
00080                     finishJson(nullptr);
00081                 else
00082                     finishError(ErrorResponse(this, false, true, contents, _stream->httpResponseCode()));
00083             }
00084         }
00085     }
00086 }
00087 
00088 void CurlJsonRequest::restart() {
00089     if (_stream)
00090         delete _stream;
00091     _stream = nullptr;
00092     _contentsStream = Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
00093     //with no stream available next handle() will create another one
00094 }
00095 
00096 void CurlJsonRequest::finishJson(Common::JSONValue *json) {
00097     Request::finishSuccess();
00098     if (_jsonCallback)
00099         (*_jsonCallback)(JsonResponse(this, json)); //potential memory leak, free it in your callbacks!
00100     else
00101         delete json;
00102 }
00103 
00104 bool CurlJsonRequest::jsonIsObject(Common::JSONValue *item, const char *warningPrefix) {
00105     if (item == nullptr) {
00106         warning("%s: passed item is NULL", warningPrefix);
00107         return false;
00108     }
00109 
00110     if (item->isObject()) return true;
00111 
00112     warning("%s: passed item is not an object", warningPrefix);
00113     debug(9, "%s", item->stringify(true).c_str());
00114     return false;
00115 }
00116 
00117 bool CurlJsonRequest::jsonContainsObject(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
00118     if (!item.contains(key)) {
00119         if (isOptional) {
00120             return true;
00121         }
00122 
00123         warning("%s: passed item misses the \"%s\" attribute", warningPrefix, key);
00124         return false;
00125     }
00126 
00127     if (item.getVal(key)->isObject()) return true;
00128 
00129     warning("%s: passed item's \"%s\" attribute is not an object", warningPrefix, key);
00130     debug(9, "%s", item.getVal(key)->stringify(true).c_str());
00131     return false;
00132 }
00133 
00134 bool CurlJsonRequest::jsonContainsString(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
00135     if (!item.contains(key)) {
00136         if (isOptional) {
00137             return true;
00138         }
00139 
00140         warning("%s: passed item misses the \"%s\" attribute", warningPrefix, key);
00141         return false;
00142     }
00143 
00144     if (item.getVal(key)->isString()) return true;
00145 
00146     warning("%s: passed item's \"%s\" attribute is not a string", warningPrefix, key);
00147     debug(9, "%s", item.getVal(key)->stringify(true).c_str());
00148     return false;
00149 }
00150 
00151 bool CurlJsonRequest::jsonContainsIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
00152     if (!item.contains(key)) {
00153         if (isOptional) {
00154             return true;
00155         }
00156 
00157         warning("%s: passed item misses the \"%s\" attribute", warningPrefix, key);
00158         return false;
00159     }
00160 
00161     if (item.getVal(key)->isIntegerNumber()) return true;
00162 
00163     warning("%s: passed item's \"%s\" attribute is not an integer", warningPrefix, key);
00164     debug(9, "%s", item.getVal(key)->stringify(true).c_str());
00165     return false;
00166 }
00167 
00168 bool CurlJsonRequest::jsonContainsArray(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
00169     if (!item.contains(key)) {
00170         if (isOptional) {
00171             return true;
00172         }
00173 
00174         warning("%s: passed item misses the \"%s\" attribute", warningPrefix, key);
00175         return false;
00176     }
00177 
00178     if (item.getVal(key)->isArray()) return true;
00179 
00180     warning("%s: passed item's \"%s\" attribute is not an array", warningPrefix, key);
00181     debug(9, "%s", item.getVal(key)->stringify(true).c_str());
00182     return false;
00183 }
00184 
00185 bool CurlJsonRequest::jsonContainsStringOrIntegerNumber(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
00186     if (!item.contains(key)) {
00187         if (isOptional) {
00188             return true;
00189         }
00190 
00191         warning("%s: passed item misses the \"%s\" attribute", warningPrefix, key);
00192         return false;
00193     }
00194 
00195     if (item.getVal(key)->isString() || item.getVal(key)->isIntegerNumber()) return true;
00196 
00197     warning("%s: passed item's \"%s\" attribute is neither a string or an integer", warningPrefix, key);
00198     debug(9, "%s", item.getVal(key)->stringify(true).c_str());
00199     return false;
00200 }
00201 
00202 bool CurlJsonRequest::jsonContainsAttribute(Common::JSONObject &item, const char *key, const char *warningPrefix, bool isOptional) {
00203     if (!item.contains(key)) {
00204         if (isOptional) {
00205             return true;
00206         }
00207 
00208         warning("%s: passed item misses the \"%s\" attribute", warningPrefix, key);
00209         return false;
00210     }
00211 
00212     return true;
00213 }
00214 
00215 } // End of namespace Networking


Generated on Sat Mar 16 2019 05:01:23 for ResidualVM by doxygen 1.7.1
curved edge   curved edge