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