Replace C++ mainmenu by formspec powered one
[oweals/minetest.git] / src / convert_json.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #include <vector>
21 #include <iostream>
22 #include <sstream>
23
24 #include "convert_json.h"
25 #include "mods.h"
26 #include "config.h"
27 #include "log.h"
28
29 #if USE_CURL
30 #include <curl/curl.h>
31
32 static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
33 {
34     ((std::string*)userp)->append((char*)contents, size * nmemb);
35     return size * nmemb;
36 }
37
38 #endif
39
40 Json::Value                 fetchJsonValue(const std::string url,
41                                                                                                         struct curl_slist *chunk) {
42 #if USE_CURL
43         std::string liststring;
44         CURL *curl;
45
46         curl = curl_easy_init();
47         if (curl)
48         {
49                 CURLcode res;
50
51                 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
52                 curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
53                 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
54                 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &liststring);
55
56                 if (chunk != 0)
57                         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
58
59
60                 res = curl_easy_perform(curl);
61                 if (res != CURLE_OK)
62                         errorstream<<"Jsonreader: "<< url <<" not found (internet connection?)"<<std::endl;
63                 curl_easy_cleanup(curl);
64         }
65
66         Json::Value root;
67         Json::Reader reader;
68         std::istringstream stream(liststring);
69         if (!liststring.size()) {
70                 return Json::Value();
71         }
72
73         if (!reader.parse( stream, root ) )
74         {
75                 errorstream << "URL: " << url << std::endl;
76                 errorstream << "Failed to parse json data " << reader.getFormattedErrorMessages();
77                 errorstream << "data: \"" << liststring << "\"" << std::endl;
78                 return Json::Value();
79         }
80
81         if (root.isArray()) {
82                 return root;
83         }
84         if ((root["list"].isArray())) {
85                 return root["list"];
86         }
87         else {
88                 return root;
89         }
90 #endif
91         return Json::Value();
92 }
93
94 std::vector<ModStoreMod>    readModStoreList(Json::Value& modlist) {
95         std::vector<ModStoreMod> retval;
96
97         if (modlist.isArray()) {
98                 for (unsigned int i = 0; i < modlist.size(); i++)
99                 {
100                         ModStoreMod toadd;
101                         toadd.valid = true;
102
103                         //id
104                         if (modlist[i]["id"].asString().size()) {
105                                 const char* id_raw = modlist[i]["id"].asString().c_str();
106                                 char* endptr = 0;
107                                 int numbervalue = strtol(id_raw,&endptr,10);
108
109                                 if ((*id_raw != 0) && (*endptr == 0)) {
110                                         toadd.id = numbervalue;
111                                 }
112                         }
113                         else {
114                                 toadd.valid = false;
115                         }
116
117                         //title
118                         if (modlist[i]["title"].asString().size()) {
119                                 toadd.title = modlist[i]["title"].asString();
120                         }
121                         else {
122                                 toadd.valid = false;
123                         }
124
125                         //basename
126                         if (modlist[i]["basename"].asString().size()) {
127                                 toadd.basename = modlist[i]["basename"].asString();
128                         }
129                         else {
130                                 toadd.valid = false;
131                         }
132
133                         //author
134
135                         //rating
136
137                         //version
138
139                         if (toadd.valid) {
140                                 retval.push_back(toadd);
141                         }
142                 }
143         }
144         return retval;
145 }
146
147 ModStoreModDetails          readModStoreModDetails(Json::Value& details) {
148
149         ModStoreModDetails retval;
150
151         retval.valid = true;
152
153         //version set
154         if (details["version_set"].isArray()) {
155                 for (unsigned int i = 0; i < details["version_set"].size(); i++)
156                 {
157                         ModStoreVersionEntry toadd;
158
159                         if (details["version_set"][i]["id"].asString().size()) {
160                                 const char* id_raw = details["version_set"][i]["id"].asString().c_str();
161                                 char* endptr = 0;
162                                 int numbervalue = strtol(id_raw,&endptr,10);
163
164                                 if ((*id_raw != 0) && (*endptr == 0)) {
165                                         toadd.id = numbervalue;
166                                 }
167                         }
168                         else {
169                                 retval.valid = false;
170                         }
171
172                         //date
173                         if (details["version_set"][i]["date"].asString().size()) {
174                                 toadd.date = details["version_set"][i]["date"].asString();
175                         }
176
177                         //file
178                         if (details["version_set"][i]["file"].asString().size()) {
179                                 toadd.file = details["version_set"][i]["file"].asString();
180                         }
181                         else {
182                                 retval.valid = false;
183                         }
184
185                         //approved
186
187                         //mtversion
188
189                         if( retval.valid ) {
190                                 retval.versions.push_back(toadd);
191                         }
192                         else {
193                                 break;
194                         }
195                 }
196         }
197
198         if (retval.versions.size() < 1) {
199                 retval.valid = false;
200         }
201
202         //categories
203         if (details["categories"].isObject()) {
204                 for (unsigned int i = 0; i < details["categories"].size(); i++) {
205                         ModStoreCategoryInfo toadd;
206
207                         if (details["categories"][i]["id"].asString().size()) {
208
209                                 const char* id_raw = details["categories"][i]["id"].asString().c_str();
210                                 char* endptr = 0;
211                                 int numbervalue = strtol(id_raw,&endptr,10);
212
213                                 if ((*id_raw != 0) && (*endptr == 0)) {
214                                         toadd.id = numbervalue;
215                                 }
216                         }
217                         else {
218                                 retval.valid = false;
219                         }
220                         if (details["categories"][i]["title"].asString().size()) {
221                                 toadd.name = details["categories"][i]["title"].asString();
222                         }
223                         else {
224                                 retval.valid = false;
225                         }
226
227                         if( retval.valid ) {
228                                 retval.categories.push_back(toadd);
229                         }
230                         else {
231                                 break;
232                         }
233                 }
234         }
235
236         //author
237         if (details["author"].isObject()) {
238                 if (details["author"]["id"].asString().size()) {
239
240                         const char* id_raw = details["author"]["id"].asString().c_str();
241                         char* endptr = 0;
242                         int numbervalue = strtol(id_raw,&endptr,10);
243
244                         if ((*id_raw != 0) && (*endptr == 0)) {
245                                 retval.author.id = numbervalue;
246                         }
247                         else {
248                                 retval.valid = false;
249                         }
250                 }
251                 else {
252                         retval.valid = false;
253                 }
254
255                 if (details["author"]["username"].asString().size()) {
256                         retval.author.username = details["author"]["username"].asString();
257                 }
258                 else {
259                         retval.valid = false;
260                 }
261         }
262         else {
263                 retval.valid = false;
264         }
265
266         //license
267         if (details["license"].isObject()) {
268                 if (details["license"]["id"].asString().size()) {
269
270                         const char* id_raw = details["license"]["id"].asString().c_str();
271                         char* endptr = 0;
272                         int numbervalue = strtol(id_raw,&endptr,10);
273
274                         if ((*id_raw != 0) && (*endptr == 0)) {
275                                 retval.license.id = numbervalue;
276                         }
277                 }
278                 else {
279                         retval.valid = false;
280                 }
281
282                 if (details["license"]["short"].asString().size()) {
283                         retval.license.shortinfo = details["license"]["short"].asString();
284                 }
285                 else {
286                         retval.valid = false;
287                 }
288
289                 if (details["license"]["link"].asString().size()) {
290                         retval.license.url = details["license"]["link"].asString();
291                 }
292
293         }
294
295         //id
296         if (details["id"].asString().size()) {
297
298                 const char* id_raw = details["id"].asString().c_str();
299                 char* endptr = 0;
300                 int numbervalue = strtol(id_raw,&endptr,10);
301
302                 if ((*id_raw != 0) && (*endptr == 0)) {
303                         retval.id = numbervalue;
304                 }
305         }
306         else {
307                 retval.valid = false;
308         }
309
310         //title
311         if (details["title"].asString().size()) {
312                 retval.title = details["title"].asString();
313         }
314         else {
315                 retval.valid = false;
316         }
317
318         //basename
319         if (details["basename"].asString().size()) {
320                 retval.basename = details["basename"].asString();
321         }
322         else {
323                 retval.valid = false;
324         }
325
326         //description
327         if (details["desc"].asString().size()) {
328                 retval.description = details["desc"].asString();
329         }
330
331         //repository
332         if (details["replink"].asString().size()) {
333                 retval.repository = details["replink"].asString();
334         }
335
336         //value
337         if (details["rating"].asString().size()) {
338
339                 const char* id_raw = details["rating"].asString().c_str();
340                 char* endptr = 0;
341                 float numbervalue = strtof(id_raw,&endptr);
342
343                 if ((*id_raw != 0) && (*endptr == 0)) {
344                         retval.rating = numbervalue;
345                 }
346         }
347         else {
348                 retval.rating = 0.0;
349         }
350
351         //depends
352         if (details["depends"].isArray()) {
353                 //TODO
354         }
355
356         //softdepends
357         if (details["softdep"].isArray()) {
358                 //TODO
359         }
360
361         //screenshot url
362         if (details["screenshot_url"].asString().size()) {
363                 retval.screenshot_url = details["screenshot_url"].asString();
364         }
365
366         return retval;
367 }