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