serialize.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /*
  2. Minetest
  3. Copyright (C) 2010-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 "serialize.h"
  17. #include "pointer.h"
  18. #include "porting.h"
  19. #include "util/string.h"
  20. #include "exceptions.h"
  21. #include "irrlichttypes.h"
  22. #include <sstream>
  23. #include <iomanip>
  24. #include <vector>
  25. ////
  26. //// BufReader
  27. ////
  28. bool BufReader::getStringNoEx(std::string *val)
  29. {
  30. u16 num_chars;
  31. if (!getU16NoEx(&num_chars))
  32. return false;
  33. if (pos + num_chars > size) {
  34. pos -= sizeof(num_chars);
  35. return false;
  36. }
  37. val->assign((const char *)data + pos, num_chars);
  38. pos += num_chars;
  39. return true;
  40. }
  41. bool BufReader::getWideStringNoEx(std::wstring *val)
  42. {
  43. u16 num_chars;
  44. if (!getU16NoEx(&num_chars))
  45. return false;
  46. if (pos + num_chars * 2 > size) {
  47. pos -= sizeof(num_chars);
  48. return false;
  49. }
  50. for (size_t i = 0; i != num_chars; i++) {
  51. val->push_back(readU16(data + pos));
  52. pos += 2;
  53. }
  54. return true;
  55. }
  56. bool BufReader::getLongStringNoEx(std::string *val)
  57. {
  58. u32 num_chars;
  59. if (!getU32NoEx(&num_chars))
  60. return false;
  61. if (pos + num_chars > size) {
  62. pos -= sizeof(num_chars);
  63. return false;
  64. }
  65. val->assign((const char *)data + pos, num_chars);
  66. pos += num_chars;
  67. return true;
  68. }
  69. bool BufReader::getRawDataNoEx(void *val, size_t len)
  70. {
  71. if (pos + len > size)
  72. return false;
  73. memcpy(val, data + pos, len);
  74. pos += len;
  75. return true;
  76. }
  77. ////
  78. //// String
  79. ////
  80. std::string serializeString(const std::string &plain)
  81. {
  82. std::string s;
  83. char buf[2];
  84. if (plain.size() > STRING_MAX_LEN)
  85. throw SerializationError("String too long for serializeString");
  86. writeU16((u8 *)&buf[0], plain.size());
  87. s.append(buf, 2);
  88. s.append(plain);
  89. return s;
  90. }
  91. std::string deSerializeString(std::istream &is)
  92. {
  93. std::string s;
  94. char buf[2];
  95. is.read(buf, 2);
  96. if (is.gcount() != 2)
  97. throw SerializationError("deSerializeString: size not read");
  98. u16 s_size = readU16((u8 *)buf);
  99. if (s_size == 0)
  100. return s;
  101. Buffer<char> buf2(s_size);
  102. is.read(&buf2[0], s_size);
  103. if (is.gcount() != s_size)
  104. throw SerializationError("deSerializeString: couldn't read all chars");
  105. s.reserve(s_size);
  106. s.append(&buf2[0], s_size);
  107. return s;
  108. }
  109. ////
  110. //// Wide String
  111. ////
  112. std::string serializeWideString(const std::wstring &plain)
  113. {
  114. std::string s;
  115. char buf[2];
  116. if (plain.size() > WIDE_STRING_MAX_LEN)
  117. throw SerializationError("String too long for serializeWideString");
  118. writeU16((u8 *)buf, plain.size());
  119. s.append(buf, 2);
  120. for (wchar_t i : plain) {
  121. writeU16((u8 *)buf, i);
  122. s.append(buf, 2);
  123. }
  124. return s;
  125. }
  126. std::wstring deSerializeWideString(std::istream &is)
  127. {
  128. std::wstring s;
  129. char buf[2];
  130. is.read(buf, 2);
  131. if (is.gcount() != 2)
  132. throw SerializationError("deSerializeWideString: size not read");
  133. u16 s_size = readU16((u8 *)buf);
  134. if (s_size == 0)
  135. return s;
  136. s.reserve(s_size);
  137. for (u32 i = 0; i < s_size; i++) {
  138. is.read(&buf[0], 2);
  139. if (is.gcount() != 2) {
  140. throw SerializationError(
  141. "deSerializeWideString: couldn't read all chars");
  142. }
  143. wchar_t c16 = readU16((u8 *)buf);
  144. s.append(&c16, 1);
  145. }
  146. return s;
  147. }
  148. ////
  149. //// Long String
  150. ////
  151. std::string serializeLongString(const std::string &plain)
  152. {
  153. char buf[4];
  154. if (plain.size() > LONG_STRING_MAX_LEN)
  155. throw SerializationError("String too long for serializeLongString");
  156. writeU32((u8*)&buf[0], plain.size());
  157. std::string s;
  158. s.append(buf, 4);
  159. s.append(plain);
  160. return s;
  161. }
  162. std::string deSerializeLongString(std::istream &is)
  163. {
  164. std::string s;
  165. char buf[4];
  166. is.read(buf, 4);
  167. if (is.gcount() != 4)
  168. throw SerializationError("deSerializeLongString: size not read");
  169. u32 s_size = readU32((u8 *)buf);
  170. if (s_size == 0)
  171. return s;
  172. // We don't really want a remote attacker to force us to allocate 4GB...
  173. if (s_size > LONG_STRING_MAX_LEN) {
  174. throw SerializationError("deSerializeLongString: "
  175. "string too long: " + itos(s_size) + " bytes");
  176. }
  177. Buffer<char> buf2(s_size);
  178. is.read(&buf2[0], s_size);
  179. if ((u32)is.gcount() != s_size)
  180. throw SerializationError("deSerializeLongString: couldn't read all chars");
  181. s.reserve(s_size);
  182. s.append(&buf2[0], s_size);
  183. return s;
  184. }
  185. ////
  186. //// JSON
  187. ////
  188. std::string serializeJsonString(const std::string &plain)
  189. {
  190. std::ostringstream os(std::ios::binary);
  191. os << "\"";
  192. for (char c : plain) {
  193. switch (c) {
  194. case '"':
  195. os << "\\\"";
  196. break;
  197. case '\\':
  198. os << "\\\\";
  199. break;
  200. case '/':
  201. os << "\\/";
  202. break;
  203. case '\b':
  204. os << "\\b";
  205. break;
  206. case '\f':
  207. os << "\\f";
  208. break;
  209. case '\n':
  210. os << "\\n";
  211. break;
  212. case '\r':
  213. os << "\\r";
  214. break;
  215. case '\t':
  216. os << "\\t";
  217. break;
  218. default: {
  219. if (c >= 32 && c <= 126) {
  220. os << c;
  221. } else {
  222. u32 cnum = (u8)c;
  223. os << "\\u" << std::hex << std::setw(4)
  224. << std::setfill('0') << cnum;
  225. }
  226. break;
  227. }
  228. }
  229. }
  230. os << "\"";
  231. return os.str();
  232. }
  233. std::string deSerializeJsonString(std::istream &is)
  234. {
  235. std::ostringstream os(std::ios::binary);
  236. char c, c2;
  237. // Parse initial doublequote
  238. is >> c;
  239. if (c != '"')
  240. throw SerializationError("JSON string must start with doublequote");
  241. // Parse characters
  242. for (;;) {
  243. c = is.get();
  244. if (is.eof())
  245. throw SerializationError("JSON string ended prematurely");
  246. if (c == '"') {
  247. return os.str();
  248. }
  249. if (c == '\\') {
  250. c2 = is.get();
  251. if (is.eof())
  252. throw SerializationError("JSON string ended prematurely");
  253. switch (c2) {
  254. case 'b':
  255. os << '\b';
  256. break;
  257. case 'f':
  258. os << '\f';
  259. break;
  260. case 'n':
  261. os << '\n';
  262. break;
  263. case 'r':
  264. os << '\r';
  265. break;
  266. case 't':
  267. os << '\t';
  268. break;
  269. case 'u': {
  270. int hexnumber;
  271. char hexdigits[4 + 1];
  272. is.read(hexdigits, 4);
  273. if (is.eof())
  274. throw SerializationError("JSON string ended prematurely");
  275. hexdigits[4] = 0;
  276. std::istringstream tmp_is(hexdigits, std::ios::binary);
  277. tmp_is >> std::hex >> hexnumber;
  278. os << (char)hexnumber;
  279. break;
  280. }
  281. default:
  282. os << c2;
  283. break;
  284. }
  285. } else {
  286. os << c;
  287. }
  288. }
  289. return os.str();
  290. }
  291. std::string serializeJsonStringIfNeeded(const std::string &s)
  292. {
  293. for (size_t i = 0; i < s.size(); ++i) {
  294. if (s[i] <= 0x1f || s[i] >= 0x7f || s[i] == ' ' || s[i] == '\"')
  295. return serializeJsonString(s);
  296. }
  297. return s;
  298. }
  299. std::string deSerializeJsonStringIfNeeded(std::istream &is)
  300. {
  301. std::ostringstream tmp_os;
  302. bool expect_initial_quote = true;
  303. bool is_json = false;
  304. bool was_backslash = false;
  305. for (;;) {
  306. char c = is.get();
  307. if (is.eof())
  308. break;
  309. if (expect_initial_quote && c == '"') {
  310. tmp_os << c;
  311. is_json = true;
  312. } else if(is_json) {
  313. tmp_os << c;
  314. if (was_backslash)
  315. was_backslash = false;
  316. else if (c == '\\')
  317. was_backslash = true;
  318. else if (c == '"')
  319. break; // Found end of string
  320. } else {
  321. if (c == ' ') {
  322. // Found end of word
  323. is.unget();
  324. break;
  325. }
  326. tmp_os << c;
  327. }
  328. expect_initial_quote = false;
  329. }
  330. if (is_json) {
  331. std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
  332. return deSerializeJsonString(tmp_is);
  333. }
  334. return tmp_os.str();
  335. }
  336. ////
  337. //// String/Struct conversions
  338. ////
  339. bool deSerializeStringToStruct(std::string valstr,
  340. std::string format, void *out, size_t olen)
  341. {
  342. size_t len = olen;
  343. std::vector<std::string *> strs_alloced;
  344. std::string *str;
  345. char *f, *snext;
  346. size_t pos;
  347. char *s = &valstr[0];
  348. char *buf = new char[len];
  349. char *bufpos = buf;
  350. char *fmtpos, *fmt = &format[0];
  351. while ((f = strtok_r(fmt, ",", &fmtpos)) && s) {
  352. fmt = nullptr;
  353. bool is_unsigned = false;
  354. int width = 0;
  355. char valtype = *f;
  356. width = (int)strtol(f + 1, &f, 10);
  357. if (width && valtype == 's')
  358. valtype = 'i';
  359. switch (valtype) {
  360. case 'u':
  361. is_unsigned = true;
  362. /* FALLTHROUGH */
  363. case 'i':
  364. if (width == 16) {
  365. bufpos += PADDING(bufpos, u16);
  366. if ((bufpos - buf) + sizeof(u16) <= len) {
  367. if (is_unsigned)
  368. *(u16 *)bufpos = (u16)strtoul(s, &s, 10);
  369. else
  370. *(s16 *)bufpos = (s16)strtol(s, &s, 10);
  371. }
  372. bufpos += sizeof(u16);
  373. } else if (width == 32) {
  374. bufpos += PADDING(bufpos, u32);
  375. if ((bufpos - buf) + sizeof(u32) <= len) {
  376. if (is_unsigned)
  377. *(u32 *)bufpos = (u32)strtoul(s, &s, 10);
  378. else
  379. *(s32 *)bufpos = (s32)strtol(s, &s, 10);
  380. }
  381. bufpos += sizeof(u32);
  382. } else if (width == 64) {
  383. bufpos += PADDING(bufpos, u64);
  384. if ((bufpos - buf) + sizeof(u64) <= len) {
  385. if (is_unsigned)
  386. *(u64 *)bufpos = (u64)strtoull(s, &s, 10);
  387. else
  388. *(s64 *)bufpos = (s64)strtoll(s, &s, 10);
  389. }
  390. bufpos += sizeof(u64);
  391. }
  392. s = strchr(s, ',');
  393. break;
  394. case 'b':
  395. snext = strchr(s, ',');
  396. if (snext)
  397. *snext++ = 0;
  398. bufpos += PADDING(bufpos, bool);
  399. if ((bufpos - buf) + sizeof(bool) <= len)
  400. *(bool *)bufpos = is_yes(std::string(s));
  401. bufpos += sizeof(bool);
  402. s = snext;
  403. break;
  404. case 'f':
  405. bufpos += PADDING(bufpos, float);
  406. if ((bufpos - buf) + sizeof(float) <= len)
  407. *(float *)bufpos = strtof(s, &s);
  408. bufpos += sizeof(float);
  409. s = strchr(s, ',');
  410. break;
  411. case 's':
  412. while (*s == ' ' || *s == '\t')
  413. s++;
  414. if (*s++ != '"') //error, expected string
  415. goto fail;
  416. snext = s;
  417. while (snext[0] && !(snext[-1] != '\\' && snext[0] == '"'))
  418. snext++;
  419. *snext++ = 0;
  420. bufpos += PADDING(bufpos, std::string *);
  421. str = new std::string(s);
  422. pos = 0;
  423. while ((pos = str->find("\\\"", pos)) != std::string::npos)
  424. str->erase(pos, 1);
  425. if ((bufpos - buf) + sizeof(std::string *) <= len)
  426. *(std::string **)bufpos = str;
  427. bufpos += sizeof(std::string *);
  428. strs_alloced.push_back(str);
  429. s = *snext ? snext + 1 : nullptr;
  430. break;
  431. case 'v':
  432. while (*s == ' ' || *s == '\t')
  433. s++;
  434. if (*s++ != '(') //error, expected vector
  435. goto fail;
  436. if (width == 2) {
  437. bufpos += PADDING(bufpos, v2f);
  438. if ((bufpos - buf) + sizeof(v2f) <= len) {
  439. v2f *v = (v2f *)bufpos;
  440. v->X = strtof(s, &s);
  441. s++;
  442. v->Y = strtof(s, &s);
  443. }
  444. bufpos += sizeof(v2f);
  445. } else if (width == 3) {
  446. bufpos += PADDING(bufpos, v3f);
  447. if ((bufpos - buf) + sizeof(v3f) <= len) {
  448. v3f *v = (v3f *)bufpos;
  449. v->X = strtof(s, &s);
  450. s++;
  451. v->Y = strtof(s, &s);
  452. s++;
  453. v->Z = strtof(s, &s);
  454. }
  455. bufpos += sizeof(v3f);
  456. }
  457. s = strchr(s, ',');
  458. break;
  459. default: //error, invalid format specifier
  460. goto fail;
  461. }
  462. if (s && *s == ',')
  463. s++;
  464. if ((size_t)(bufpos - buf) > len) //error, buffer too small
  465. goto fail;
  466. }
  467. if (f && *f) { //error, mismatched number of fields and values
  468. fail:
  469. for (size_t i = 0; i != strs_alloced.size(); i++)
  470. delete strs_alloced[i];
  471. delete[] buf;
  472. return false;
  473. }
  474. memcpy(out, buf, olen);
  475. delete[] buf;
  476. return true;
  477. }
  478. // Casts *buf to a signed or unsigned fixed-width integer of 'w' width
  479. #define SIGN_CAST(w, buf) (is_unsigned ? *((u##w *) buf) : *((s##w *) buf))
  480. bool serializeStructToString(std::string *out,
  481. std::string format, void *value)
  482. {
  483. std::ostringstream os;
  484. std::string str;
  485. char *f;
  486. size_t strpos;
  487. char *bufpos = (char *) value;
  488. char *fmtpos, *fmt = &format[0];
  489. while ((f = strtok_r(fmt, ",", &fmtpos))) {
  490. fmt = nullptr;
  491. bool is_unsigned = false;
  492. int width = 0;
  493. char valtype = *f;
  494. width = (int)strtol(f + 1, &f, 10);
  495. if (width && valtype == 's')
  496. valtype = 'i';
  497. switch (valtype) {
  498. case 'u':
  499. is_unsigned = true;
  500. /* FALLTHROUGH */
  501. case 'i':
  502. if (width == 16) {
  503. bufpos += PADDING(bufpos, u16);
  504. os << SIGN_CAST(16, bufpos);
  505. bufpos += sizeof(u16);
  506. } else if (width == 32) {
  507. bufpos += PADDING(bufpos, u32);
  508. os << SIGN_CAST(32, bufpos);
  509. bufpos += sizeof(u32);
  510. } else if (width == 64) {
  511. bufpos += PADDING(bufpos, u64);
  512. os << SIGN_CAST(64, bufpos);
  513. bufpos += sizeof(u64);
  514. }
  515. break;
  516. case 'b':
  517. bufpos += PADDING(bufpos, bool);
  518. os << std::boolalpha << *((bool *) bufpos);
  519. bufpos += sizeof(bool);
  520. break;
  521. case 'f':
  522. bufpos += PADDING(bufpos, float);
  523. os << *((float *) bufpos);
  524. bufpos += sizeof(float);
  525. break;
  526. case 's':
  527. bufpos += PADDING(bufpos, std::string *);
  528. str = **((std::string **) bufpos);
  529. strpos = 0;
  530. while ((strpos = str.find('"', strpos)) != std::string::npos) {
  531. str.insert(strpos, 1, '\\');
  532. strpos += 2;
  533. }
  534. os << str;
  535. bufpos += sizeof(std::string *);
  536. break;
  537. case 'v':
  538. if (width == 2) {
  539. bufpos += PADDING(bufpos, v2f);
  540. v2f *v = (v2f *) bufpos;
  541. os << '(' << v->X << ", " << v->Y << ')';
  542. bufpos += sizeof(v2f);
  543. } else {
  544. bufpos += PADDING(bufpos, v3f);
  545. v3f *v = (v3f *) bufpos;
  546. os << '(' << v->X << ", " << v->Y << ", " << v->Z << ')';
  547. bufpos += sizeof(v3f);
  548. }
  549. break;
  550. default:
  551. return false;
  552. }
  553. os << ", ";
  554. }
  555. *out = os.str();
  556. // Trim off the trailing comma and space
  557. if (out->size() >= 2)
  558. out->resize(out->size() - 2);
  559. return true;
  560. }
  561. #undef SIGN_CAST
  562. ////
  563. //// Other
  564. ////
  565. std::string serializeHexString(const std::string &data, bool insert_spaces)
  566. {
  567. std::string result;
  568. result.reserve(data.size() * (2 + insert_spaces));
  569. static const char hex_chars[] = "0123456789abcdef";
  570. const size_t len = data.size();
  571. for (size_t i = 0; i != len; i++) {
  572. u8 byte = data[i];
  573. result.push_back(hex_chars[(byte >> 4) & 0x0F]);
  574. result.push_back(hex_chars[(byte >> 0) & 0x0F]);
  575. if (insert_spaces && i != len - 1)
  576. result.push_back(' ');
  577. }
  578. return result;
  579. }