convert_json.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include <vector>
  17. #include <iostream>
  18. #include <sstream>
  19. #include "convert_json.h"
  20. #include "mods.h"
  21. #include "config.h"
  22. #include "log.h"
  23. #include "main.h" // for g_settings
  24. #include "settings.h"
  25. #include "httpfetch.h"
  26. #include "porting.h"
  27. Json::Value fetchJsonValue(const std::string &url,
  28. std::vector<std::string> *extra_headers)
  29. {
  30. HTTPFetchRequest fetch_request;
  31. HTTPFetchResult fetch_result;
  32. fetch_request.url = url;
  33. fetch_request.caller = HTTPFETCH_SYNC;
  34. if (extra_headers != NULL)
  35. fetch_request.extra_headers = *extra_headers;
  36. httpfetch_sync(fetch_request, fetch_result);
  37. if (!fetch_result.succeeded) {
  38. return Json::Value();
  39. }
  40. Json::Value root;
  41. Json::Reader reader;
  42. std::istringstream stream(fetch_result.data);
  43. if (!reader.parse(stream, root)) {
  44. errorstream << "URL: " << url << std::endl;
  45. errorstream << "Failed to parse json data " << reader.getFormattedErrorMessages();
  46. errorstream << "data: \"" << fetch_result.data << "\"" << std::endl;
  47. return Json::Value();
  48. }
  49. return root;
  50. }
  51. std::vector<ModStoreMod> readModStoreList(Json::Value& modlist) {
  52. std::vector<ModStoreMod> retval;
  53. if (modlist.isArray()) {
  54. for (unsigned int i = 0; i < modlist.size(); i++)
  55. {
  56. ModStoreMod toadd;
  57. toadd.valid = true;
  58. //id
  59. if (modlist[i]["id"].asString().size()) {
  60. std::string id_raw = modlist[i]["id"].asString();
  61. char* endptr = 0;
  62. int numbervalue = strtol(id_raw.c_str(),&endptr,10);
  63. if ((id_raw != "") && (*endptr == 0)) {
  64. toadd.id = numbervalue;
  65. }
  66. else {
  67. errorstream << "readModStoreList: missing id" << std::endl;
  68. toadd.valid = false;
  69. }
  70. }
  71. else {
  72. errorstream << "readModStoreList: missing id" << std::endl;
  73. toadd.valid = false;
  74. }
  75. //title
  76. if (modlist[i]["title"].asString().size()) {
  77. toadd.title = modlist[i]["title"].asString();
  78. }
  79. else {
  80. errorstream << "readModStoreList: missing title" << std::endl;
  81. toadd.valid = false;
  82. }
  83. //basename
  84. if (modlist[i]["basename"].asString().size()) {
  85. toadd.basename = modlist[i]["basename"].asString();
  86. }
  87. else {
  88. errorstream << "readModStoreList: missing basename" << std::endl;
  89. toadd.valid = false;
  90. }
  91. //author
  92. //rating
  93. //version
  94. if (toadd.valid) {
  95. retval.push_back(toadd);
  96. }
  97. }
  98. }
  99. return retval;
  100. }
  101. ModStoreModDetails readModStoreModDetails(Json::Value& details) {
  102. ModStoreModDetails retval;
  103. retval.valid = true;
  104. //version set
  105. if (details["version_set"].isArray()) {
  106. for (unsigned int i = 0; i < details["version_set"].size(); i++)
  107. {
  108. ModStoreVersionEntry toadd;
  109. if (details["version_set"][i]["id"].asString().size()) {
  110. std::string id_raw = details["version_set"][i]["id"].asString();
  111. char* endptr = 0;
  112. int numbervalue = strtol(id_raw.c_str(),&endptr,10);
  113. if ((id_raw != "") && (*endptr == 0)) {
  114. toadd.id = numbervalue;
  115. }
  116. }
  117. else {
  118. errorstream << "readModStoreModDetails: missing version_set id" << std::endl;
  119. retval.valid = false;
  120. }
  121. //date
  122. if (details["version_set"][i]["date"].asString().size()) {
  123. toadd.date = details["version_set"][i]["date"].asString();
  124. }
  125. //file
  126. if (details["version_set"][i]["file"].asString().size()) {
  127. toadd.file = details["version_set"][i]["file"].asString();
  128. }
  129. else {
  130. errorstream << "readModStoreModDetails: missing version_set file" << std::endl;
  131. retval.valid = false;
  132. }
  133. //approved
  134. //mtversion
  135. if( retval.valid ) {
  136. retval.versions.push_back(toadd);
  137. }
  138. else {
  139. break;
  140. }
  141. }
  142. }
  143. if (retval.versions.size() < 1) {
  144. infostream << "readModStoreModDetails: not a single version specified!" << std::endl;
  145. retval.valid = false;
  146. }
  147. //categories
  148. if (details["categories"].isObject()) {
  149. for (unsigned int i = 0; i < details["categories"].size(); i++) {
  150. ModStoreCategoryInfo toadd;
  151. if (details["categories"][i]["id"].asString().size()) {
  152. std::string id_raw = details["categories"][i]["id"].asString();
  153. char* endptr = 0;
  154. int numbervalue = strtol(id_raw.c_str(),&endptr,10);
  155. if ((id_raw != "") && (*endptr == 0)) {
  156. toadd.id = numbervalue;
  157. }
  158. }
  159. else {
  160. errorstream << "readModStoreModDetails: missing categories id" << std::endl;
  161. retval.valid = false;
  162. }
  163. if (details["categories"][i]["title"].asString().size()) {
  164. toadd.name = details["categories"][i]["title"].asString();
  165. }
  166. else {
  167. errorstream << "readModStoreModDetails: missing categories title" << std::endl;
  168. retval.valid = false;
  169. }
  170. if( retval.valid ) {
  171. retval.categories.push_back(toadd);
  172. }
  173. else {
  174. break;
  175. }
  176. }
  177. }
  178. //author
  179. if (details["author"].isObject()) {
  180. if (details["author"]["id"].asString().size()) {
  181. std::string id_raw = details["author"]["id"].asString();
  182. char* endptr = 0;
  183. int numbervalue = strtol(id_raw.c_str(),&endptr,10);
  184. if ((id_raw != "") && (*endptr == 0)) {
  185. retval.author.id = numbervalue;
  186. }
  187. else {
  188. errorstream << "readModStoreModDetails: missing author id (convert)" << std::endl;
  189. retval.valid = false;
  190. }
  191. }
  192. else {
  193. errorstream << "readModStoreModDetails: missing author id" << std::endl;
  194. retval.valid = false;
  195. }
  196. if (details["author"]["username"].asString().size()) {
  197. retval.author.username = details["author"]["username"].asString();
  198. }
  199. else {
  200. errorstream << "readModStoreModDetails: missing author username" << std::endl;
  201. retval.valid = false;
  202. }
  203. }
  204. else {
  205. errorstream << "readModStoreModDetails: missing author" << std::endl;
  206. retval.valid = false;
  207. }
  208. //license
  209. if (details["license"].isObject()) {
  210. if (details["license"]["id"].asString().size()) {
  211. std::string id_raw = details["license"]["id"].asString();
  212. char* endptr = 0;
  213. int numbervalue = strtol(id_raw.c_str(),&endptr,10);
  214. if ((id_raw != "") && (*endptr == 0)) {
  215. retval.license.id = numbervalue;
  216. }
  217. }
  218. else {
  219. errorstream << "readModStoreModDetails: missing license id" << std::endl;
  220. retval.valid = false;
  221. }
  222. if (details["license"]["short"].asString().size()) {
  223. retval.license.shortinfo = details["license"]["short"].asString();
  224. }
  225. else {
  226. errorstream << "readModStoreModDetails: missing license short" << std::endl;
  227. retval.valid = false;
  228. }
  229. if (details["license"]["link"].asString().size()) {
  230. retval.license.url = details["license"]["link"].asString();
  231. }
  232. }
  233. //titlepic
  234. if (details["titlepic"].isObject()) {
  235. if (details["titlepic"]["id"].asString().size()) {
  236. std::string id_raw = details["titlepic"]["id"].asString();
  237. char* endptr = 0;
  238. int numbervalue = strtol(id_raw.c_str(),&endptr,10);
  239. if ((id_raw != "") && (*endptr == 0)) {
  240. retval.titlepic.id = numbervalue;
  241. }
  242. }
  243. if (details["titlepic"]["file"].asString().size()) {
  244. retval.titlepic.file = details["titlepic"]["file"].asString();
  245. }
  246. if (details["titlepic"]["desc"].asString().size()) {
  247. retval.titlepic.description = details["titlepic"]["desc"].asString();
  248. }
  249. if (details["titlepic"]["mod"].asString().size()) {
  250. std::string mod_raw = details["titlepic"]["mod"].asString();
  251. char* endptr = 0;
  252. int numbervalue = strtol(mod_raw.c_str(),&endptr,10);
  253. if ((mod_raw != "") && (*endptr == 0)) {
  254. retval.titlepic.mod = numbervalue;
  255. }
  256. }
  257. }
  258. //id
  259. if (details["id"].asString().size()) {
  260. std::string id_raw = details["id"].asString();
  261. char* endptr = 0;
  262. int numbervalue = strtol(id_raw.c_str(),&endptr,10);
  263. if ((id_raw != "") && (*endptr == 0)) {
  264. retval.id = numbervalue;
  265. }
  266. }
  267. else {
  268. errorstream << "readModStoreModDetails: missing id" << std::endl;
  269. retval.valid = false;
  270. }
  271. //title
  272. if (details["title"].asString().size()) {
  273. retval.title = details["title"].asString();
  274. }
  275. else {
  276. errorstream << "readModStoreModDetails: missing title" << std::endl;
  277. retval.valid = false;
  278. }
  279. //basename
  280. if (details["basename"].asString().size()) {
  281. retval.basename = details["basename"].asString();
  282. }
  283. else {
  284. errorstream << "readModStoreModDetails: missing basename" << std::endl;
  285. retval.valid = false;
  286. }
  287. //description
  288. if (details["desc"].asString().size()) {
  289. retval.description = details["desc"].asString();
  290. }
  291. //repository
  292. if (details["replink"].asString().size()) {
  293. retval.repository = details["replink"].asString();
  294. }
  295. //value
  296. if (details["rating"].asString().size()) {
  297. std::string id_raw = details["rating"].asString();
  298. char* endptr = 0;
  299. float numbervalue = strtof(id_raw.c_str(),&endptr);
  300. if ((id_raw != "") && (*endptr == 0)) {
  301. retval.rating = numbervalue;
  302. }
  303. }
  304. else {
  305. retval.rating = 0.0;
  306. }
  307. //depends
  308. if (details["depends"].isArray()) {
  309. //TODO
  310. }
  311. //softdepends
  312. if (details["softdep"].isArray()) {
  313. //TODO
  314. }
  315. //screenshot url
  316. if (details["screenshot_url"].asString().size()) {
  317. retval.screenshot_url = details["screenshot_url"].asString();
  318. }
  319. return retval;
  320. }