3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "convert_json.h"
28 #include "main.h" // for g_settings
32 #include <curl/curl.h>
34 static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
36 ((std::string*)userp)->append((char*)contents, size * nmemb);
42 Json::Value fetchJsonValue(const std::string url,
43 struct curl_slist *chunk) {
45 std::string liststring;
48 curl = curl_easy_init();
53 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
54 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
55 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
56 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &liststring);
57 curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, g_settings->getS32("curl_timeout"));
58 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, g_settings->getS32("curl_timeout"));
61 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
63 res = curl_easy_perform(curl);
65 errorstream<<"Jsonreader: "<< url <<" not found (" << curl_easy_strerror(res) << ")" <<std::endl;
66 curl_easy_cleanup(curl);
71 std::istringstream stream(liststring);
72 if (!liststring.size()) {
76 if (!reader.parse( stream, root ) )
78 errorstream << "URL: " << url << std::endl;
79 errorstream << "Failed to parse json data " << reader.getFormattedErrorMessages();
80 errorstream << "data: \"" << liststring << "\"" << std::endl;
87 if ((root["list"].isArray())) {
97 std::vector<ModStoreMod> readModStoreList(Json::Value& modlist) {
98 std::vector<ModStoreMod> retval;
100 if (modlist.isArray()) {
101 for (unsigned int i = 0; i < modlist.size(); i++)
107 if (modlist[i]["id"].asString().size()) {
108 const char* id_raw = modlist[i]["id"].asString().c_str();
110 int numbervalue = strtol(id_raw,&endptr,10);
112 if ((*id_raw != 0) && (*endptr == 0)) {
113 toadd.id = numbervalue;
117 errorstream << "readModStoreList: missing id" << std::endl;
122 if (modlist[i]["title"].asString().size()) {
123 toadd.title = modlist[i]["title"].asString();
126 errorstream << "readModStoreList: missing title" << std::endl;
131 if (modlist[i]["basename"].asString().size()) {
132 toadd.basename = modlist[i]["basename"].asString();
135 errorstream << "readModStoreList: missing basename" << std::endl;
146 retval.push_back(toadd);
153 ModStoreModDetails readModStoreModDetails(Json::Value& details) {
155 ModStoreModDetails retval;
160 if (details["version_set"].isArray()) {
161 for (unsigned int i = 0; i < details["version_set"].size(); i++)
163 ModStoreVersionEntry toadd;
165 if (details["version_set"][i]["id"].asString().size()) {
166 const char* id_raw = details["version_set"][i]["id"].asString().c_str();
168 int numbervalue = strtol(id_raw,&endptr,10);
170 if ((*id_raw != 0) && (*endptr == 0)) {
171 toadd.id = numbervalue;
175 errorstream << "readModStoreModDetails: missing version_set id" << std::endl;
176 retval.valid = false;
180 if (details["version_set"][i]["date"].asString().size()) {
181 toadd.date = details["version_set"][i]["date"].asString();
185 if (details["version_set"][i]["file"].asString().size()) {
186 toadd.file = details["version_set"][i]["file"].asString();
189 errorstream << "readModStoreModDetails: missing version_set file" << std::endl;
190 retval.valid = false;
198 retval.versions.push_back(toadd);
206 if (retval.versions.size() < 1) {
207 errorstream << "readModStoreModDetails: not a single version specified!" << std::endl;
208 retval.valid = false;
212 if (details["categories"].isObject()) {
213 for (unsigned int i = 0; i < details["categories"].size(); i++) {
214 ModStoreCategoryInfo toadd;
216 if (details["categories"][i]["id"].asString().size()) {
218 const char* id_raw = details["categories"][i]["id"].asString().c_str();
220 int numbervalue = strtol(id_raw,&endptr,10);
222 if ((*id_raw != 0) && (*endptr == 0)) {
223 toadd.id = numbervalue;
227 errorstream << "readModStoreModDetails: missing categories id" << std::endl;
228 retval.valid = false;
230 if (details["categories"][i]["title"].asString().size()) {
231 toadd.name = details["categories"][i]["title"].asString();
234 errorstream << "readModStoreModDetails: missing categories title" << std::endl;
235 retval.valid = false;
239 retval.categories.push_back(toadd);
248 if (details["author"].isObject()) {
249 if (details["author"]["id"].asString().size()) {
251 const char* id_raw = details["author"]["id"].asString().c_str();
253 int numbervalue = strtol(id_raw,&endptr,10);
255 if ((*id_raw != 0) && (*endptr == 0)) {
256 retval.author.id = numbervalue;
259 errorstream << "readModStoreModDetails: missing author id (convert)" << std::endl;
260 retval.valid = false;
264 errorstream << "readModStoreModDetails: missing author id" << std::endl;
265 retval.valid = false;
268 if (details["author"]["username"].asString().size()) {
269 retval.author.username = details["author"]["username"].asString();
272 errorstream << "readModStoreModDetails: missing author username" << std::endl;
273 retval.valid = false;
277 errorstream << "readModStoreModDetails: missing author" << std::endl;
278 retval.valid = false;
282 if (details["license"].isObject()) {
283 if (details["license"]["id"].asString().size()) {
285 const char* id_raw = details["license"]["id"].asString().c_str();
287 int numbervalue = strtol(id_raw,&endptr,10);
289 if ((*id_raw != 0) && (*endptr == 0)) {
290 retval.license.id = numbervalue;
294 errorstream << "readModStoreModDetails: missing license id" << std::endl;
295 retval.valid = false;
298 if (details["license"]["short"].asString().size()) {
299 retval.license.shortinfo = details["license"]["short"].asString();
302 errorstream << "readModStoreModDetails: missing license short" << std::endl;
303 retval.valid = false;
306 if (details["license"]["link"].asString().size()) {
307 retval.license.url = details["license"]["link"].asString();
313 if (details["titlepic"].isObject()) {
314 if (details["titlepic"]["id"].asString().size()) {
316 const char* id_raw = details["titlepic"]["id"].asString().c_str();
318 int numbervalue = strtol(id_raw,&endptr,10);
320 if ((*id_raw != 0) && (*endptr == 0)) {
321 retval.titlepic.id = numbervalue;
325 if (details["titlepic"]["file"].asString().size()) {
326 retval.titlepic.file = details["titlepic"]["file"].asString();
329 if (details["titlepic"]["desc"].asString().size()) {
330 retval.titlepic.description = details["titlepic"]["desc"].asString();
333 if (details["titlepic"]["mod"].asString().size()) {
335 const char* mod_raw = details["titlepic"]["mod"].asString().c_str();
337 int numbervalue = strtol(mod_raw,&endptr,10);
339 if ((*mod_raw != 0) && (*endptr == 0)) {
340 retval.titlepic.mod = numbervalue;
346 if (details["id"].asString().size()) {
348 const char* id_raw = details["id"].asString().c_str();
350 int numbervalue = strtol(id_raw,&endptr,10);
352 if ((*id_raw != 0) && (*endptr == 0)) {
353 retval.id = numbervalue;
357 errorstream << "readModStoreModDetails: missing id" << std::endl;
358 retval.valid = false;
362 if (details["title"].asString().size()) {
363 retval.title = details["title"].asString();
366 errorstream << "readModStoreModDetails: missing title" << std::endl;
367 retval.valid = false;
371 if (details["basename"].asString().size()) {
372 retval.basename = details["basename"].asString();
375 errorstream << "readModStoreModDetails: missing basename" << std::endl;
376 retval.valid = false;
380 if (details["desc"].asString().size()) {
381 retval.description = details["desc"].asString();
385 if (details["replink"].asString().size()) {
386 retval.repository = details["replink"].asString();
390 if (details["rating"].asString().size()) {
392 const char* id_raw = details["rating"].asString().c_str();
394 float numbervalue = strtof(id_raw,&endptr);
396 if ((*id_raw != 0) && (*endptr == 0)) {
397 retval.rating = numbervalue;
405 if (details["depends"].isArray()) {
410 if (details["softdep"].isArray()) {
415 if (details["screenshot_url"].asString().size()) {
416 retval.screenshot_url = details["screenshot_url"].asString();