Remove a lot of superfluous ifndef USE_CURL checks
[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 #include "main.h" // for g_settings
29 #include "settings.h"
30 #include "version.h"
31 #include "httpfetch.h"
32 #include "porting.h"
33
34 Json::Value                 fetchJsonValue(const std::string &url,
35                 struct curl_slist *chunk) {
36
37         HTTPFetchRequest fetchrequest;
38         HTTPFetchResult fetchresult;
39         fetchrequest.url = url;
40         fetchrequest.caller = HTTPFETCH_SYNC;
41
42 #if USE_CURL
43         struct curl_slist* runptr = chunk;
44         while(runptr) {
45                 fetchrequest.extra_headers.push_back(runptr->data);
46                 runptr = runptr->next;
47         }
48 #endif
49         httpfetch_sync(fetchrequest,fetchresult);
50
51         if (!fetchresult.succeeded) {
52                 return Json::Value();
53         }
54         Json::Value root;
55         Json::Reader reader;
56         std::istringstream stream(fetchresult.data);
57
58         if (!reader.parse( stream, root ) )
59         {
60                 errorstream << "URL: " << url << std::endl;
61                 errorstream << "Failed to parse json data " << reader.getFormattedErrorMessages();
62                 errorstream << "data: \"" << fetchresult.data << "\"" << std::endl;
63                 return Json::Value();
64         }
65
66         if (root.isArray()) {
67                 return root;
68         }
69         if ((root["list"].isArray())) {
70                 return root["list"];
71         }
72         else {
73                 return root;
74         }
75
76         return Json::Value();
77 }
78
79 std::vector<ModStoreMod>    readModStoreList(Json::Value& modlist) {
80                 std::vector<ModStoreMod> retval;
81
82         if (modlist.isArray()) {
83                 for (unsigned int i = 0; i < modlist.size(); i++)
84                 {
85                         ModStoreMod toadd;
86                         toadd.valid = true;
87
88                         //id
89                         if (modlist[i]["id"].asString().size()) {
90                                 std::string id_raw = modlist[i]["id"].asString();
91                                 char* endptr = 0;
92                                 int numbervalue = strtol(id_raw.c_str(),&endptr,10);
93
94                                 if ((id_raw != "") && (*endptr == 0)) {
95                                         toadd.id = numbervalue;
96                                 }
97                                 else {
98                                         errorstream << "readModStoreList: missing id" << std::endl;
99                                         toadd.valid = false;
100                                 }
101                         }
102                         else {
103                                 errorstream << "readModStoreList: missing id" << std::endl;
104                                 toadd.valid = false;
105                         }
106
107                         //title
108                         if (modlist[i]["title"].asString().size()) {
109                                 toadd.title = modlist[i]["title"].asString();
110                         }
111                         else {
112                                 errorstream << "readModStoreList: missing title" << std::endl;
113                                 toadd.valid = false;
114                         }
115
116                         //basename
117                         if (modlist[i]["basename"].asString().size()) {
118                                 toadd.basename = modlist[i]["basename"].asString();
119                         }
120                         else {
121                                 errorstream << "readModStoreList: missing basename" << std::endl;
122                                 toadd.valid = false;
123                         }
124
125                         //author
126
127                         //rating
128
129                         //version
130
131                         if (toadd.valid) {
132                                 retval.push_back(toadd);
133                         }
134                 }
135         }
136         return retval;
137 }
138
139 ModStoreModDetails          readModStoreModDetails(Json::Value& details) {
140
141         ModStoreModDetails retval;
142
143         retval.valid = true;
144
145         //version set
146         if (details["version_set"].isArray()) {
147                 for (unsigned int i = 0; i < details["version_set"].size(); i++)
148                 {
149                         ModStoreVersionEntry toadd;
150
151                         if (details["version_set"][i]["id"].asString().size()) {
152                                 std::string id_raw = details["version_set"][i]["id"].asString();
153                                 char* endptr = 0;
154                                 int numbervalue = strtol(id_raw.c_str(),&endptr,10);
155
156                                 if ((id_raw != "") && (*endptr == 0)) {
157                                         toadd.id = numbervalue;
158                                 }
159                         }
160                         else {
161                                 errorstream << "readModStoreModDetails: missing version_set id" << std::endl;
162                                 retval.valid = false;
163                         }
164
165                         //date
166                         if (details["version_set"][i]["date"].asString().size()) {
167                                 toadd.date = details["version_set"][i]["date"].asString();
168                         }
169
170                         //file
171                         if (details["version_set"][i]["file"].asString().size()) {
172                                 toadd.file = details["version_set"][i]["file"].asString();
173                         }
174                         else {
175                                 errorstream << "readModStoreModDetails: missing version_set file" << std::endl;
176                                 retval.valid = false;
177                         }
178
179                         //approved
180
181                         //mtversion
182
183                         if( retval.valid ) {
184                                 retval.versions.push_back(toadd);
185                         }
186                         else {
187                                 break;
188                         }
189                 }
190         }
191
192         if (retval.versions.size() < 1) {
193                 infostream << "readModStoreModDetails: not a single version specified!" << std::endl;
194                 retval.valid = false;
195         }
196
197         //categories
198         if (details["categories"].isObject()) {
199                 for (unsigned int i = 0; i < details["categories"].size(); i++) {
200                         ModStoreCategoryInfo toadd;
201
202                         if (details["categories"][i]["id"].asString().size()) {
203
204                                 std::string id_raw = details["categories"][i]["id"].asString();
205                                 char* endptr = 0;
206                                 int numbervalue = strtol(id_raw.c_str(),&endptr,10);
207
208                                 if ((id_raw != "") && (*endptr == 0)) {
209                                         toadd.id = numbervalue;
210                                 }
211                         }
212                         else {
213                                 errorstream << "readModStoreModDetails: missing categories id" << std::endl;
214                                 retval.valid = false;
215                         }
216                         if (details["categories"][i]["title"].asString().size()) {
217                                 toadd.name = details["categories"][i]["title"].asString();
218                         }
219                         else {
220                                 errorstream << "readModStoreModDetails: missing categories title" << std::endl;
221                                 retval.valid = false;
222                         }
223
224                         if( retval.valid ) {
225                                 retval.categories.push_back(toadd);
226                         }
227                         else {
228                                 break;
229                         }
230                 }
231         }
232
233         //author
234         if (details["author"].isObject()) {
235                 if (details["author"]["id"].asString().size()) {
236
237                         std::string id_raw = details["author"]["id"].asString();
238                         char* endptr = 0;
239                         int numbervalue = strtol(id_raw.c_str(),&endptr,10);
240
241                         if ((id_raw != "") && (*endptr == 0)) {
242                                 retval.author.id = numbervalue;
243                         }
244                         else {
245                                 errorstream << "readModStoreModDetails: missing author id (convert)" << std::endl;
246                                 retval.valid = false;
247                         }
248                 }
249                 else {
250                         errorstream << "readModStoreModDetails: missing author id" << std::endl;
251                         retval.valid = false;
252                 }
253
254                 if (details["author"]["username"].asString().size()) {
255                         retval.author.username = details["author"]["username"].asString();
256                 }
257                 else {
258                         errorstream << "readModStoreModDetails: missing author username" << std::endl;
259                         retval.valid = false;
260                 }
261         }
262         else {
263                 errorstream << "readModStoreModDetails: missing author" << std::endl;
264                 retval.valid = false;
265         }
266
267         //license
268         if (details["license"].isObject()) {
269                 if (details["license"]["id"].asString().size()) {
270
271                         std::string id_raw = details["license"]["id"].asString();
272                         char* endptr = 0;
273                         int numbervalue = strtol(id_raw.c_str(),&endptr,10);
274
275                         if ((id_raw != "") && (*endptr == 0)) {
276                                 retval.license.id = numbervalue;
277                         }
278                 }
279                 else {
280                         errorstream << "readModStoreModDetails: missing license id" << std::endl;
281                         retval.valid = false;
282                 }
283
284                 if (details["license"]["short"].asString().size()) {
285                         retval.license.shortinfo = details["license"]["short"].asString();
286                 }
287                 else {
288                         errorstream << "readModStoreModDetails: missing license short" << std::endl;
289                         retval.valid = false;
290                 }
291
292                 if (details["license"]["link"].asString().size()) {
293                         retval.license.url = details["license"]["link"].asString();
294                 }
295
296         }
297
298         //titlepic
299         if (details["titlepic"].isObject()) {
300                 if (details["titlepic"]["id"].asString().size()) {
301
302                         std::string id_raw = details["titlepic"]["id"].asString();
303                         char* endptr = 0;
304                         int numbervalue = strtol(id_raw.c_str(),&endptr,10);
305
306                         if ((id_raw != "") && (*endptr == 0)) {
307                                 retval.titlepic.id = numbervalue;
308                         }
309                 }
310
311                 if (details["titlepic"]["file"].asString().size()) {
312                         retval.titlepic.file = details["titlepic"]["file"].asString();
313                 }
314
315                 if (details["titlepic"]["desc"].asString().size()) {
316                         retval.titlepic.description = details["titlepic"]["desc"].asString();
317                 }
318
319                 if (details["titlepic"]["mod"].asString().size()) {
320
321                         std::string mod_raw = details["titlepic"]["mod"].asString();
322                         char* endptr = 0;
323                         int numbervalue = strtol(mod_raw.c_str(),&endptr,10);
324
325                         if ((mod_raw != "") && (*endptr == 0)) {
326                                 retval.titlepic.mod = numbervalue;
327                         }
328                 }
329         }
330
331         //id
332         if (details["id"].asString().size()) {
333
334                 std::string id_raw = details["id"].asString();
335                 char* endptr = 0;
336                 int numbervalue = strtol(id_raw.c_str(),&endptr,10);
337
338                 if ((id_raw != "") && (*endptr == 0)) {
339                         retval.id = numbervalue;
340                 }
341         }
342         else {
343                 errorstream << "readModStoreModDetails: missing id" << std::endl;
344                 retval.valid = false;
345         }
346
347         //title
348         if (details["title"].asString().size()) {
349                 retval.title = details["title"].asString();
350         }
351         else {
352                 errorstream << "readModStoreModDetails: missing title" << std::endl;
353                 retval.valid = false;
354         }
355
356         //basename
357         if (details["basename"].asString().size()) {
358                 retval.basename = details["basename"].asString();
359         }
360         else {
361                 errorstream << "readModStoreModDetails: missing basename" << std::endl;
362                 retval.valid = false;
363         }
364
365         //description
366         if (details["desc"].asString().size()) {
367                 retval.description = details["desc"].asString();
368         }
369
370         //repository
371         if (details["replink"].asString().size()) {
372                 retval.repository = details["replink"].asString();
373         }
374
375         //value
376         if (details["rating"].asString().size()) {
377
378                 std::string id_raw = details["rating"].asString();
379                 char* endptr = 0;
380                 float numbervalue = strtof(id_raw.c_str(),&endptr);
381
382                 if ((id_raw != "") && (*endptr == 0)) {
383                         retval.rating = numbervalue;
384                 }
385         }
386         else {
387                 retval.rating = 0.0;
388         }
389
390         //depends
391         if (details["depends"].isArray()) {
392                 //TODO
393         }
394
395         //softdepends
396         if (details["softdep"].isArray()) {
397                 //TODO
398         }
399
400         //screenshot url
401         if (details["screenshot_url"].asString().size()) {
402                 retval.screenshot_url = details["screenshot_url"].asString();
403         }
404
405         return retval;
406 }