X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Futil%2Fserialize.cpp;h=61d369bc487f3a5ae8099c228cb09568237bc47d;hb=984e063374c032ed17764931fd00c19afb92ebb9;hp=0d38b960866c157fc1ac01683e4a27a6058300a6;hpb=515e7028ac5121bc6a5205b12aae731eed630b05;p=oweals%2Fminetest.git diff --git a/src/util/serialize.cpp b/src/util/serialize.cpp index 0d38b9608..61d369bc4 100644 --- a/src/util/serialize.cpp +++ b/src/util/serialize.cpp @@ -28,6 +28,77 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include +SerializationError eof_ser_err("Attempted read past end of data"); + +//// +//// BufReader +//// + +bool BufReader::getStringNoEx(std::string *val) +{ + u16 num_chars; + if (!getU16NoEx(&num_chars)) + return false; + + if (pos + num_chars > size) { + pos -= sizeof(num_chars); + return false; + } + + val->assign((const char *)data + pos, num_chars); + pos += num_chars; + + return true; +} + +bool BufReader::getWideStringNoEx(std::wstring *val) +{ + u16 num_chars; + if (!getU16NoEx(&num_chars)) + return false; + + if (pos + num_chars * 2 > size) { + pos -= sizeof(num_chars); + return false; + } + + for (size_t i = 0; i != num_chars; i++) { + val->push_back(readU16(data + pos)); + pos += 2; + } + + return true; +} + +bool BufReader::getLongStringNoEx(std::string *val) +{ + u32 num_chars; + if (!getU32NoEx(&num_chars)) + return false; + + if (pos + num_chars > size) { + pos -= sizeof(num_chars); + return false; + } + + val->assign((const char *)data + pos, num_chars); + pos += num_chars; + + return true; +} + +bool BufReader::getRawDataNoEx(void *val, size_t len) +{ + if (pos + len > size) + return false; + + memcpy(val, data + pos, len); + pos += len; + + return true; +} + + //// //// String //// @@ -37,7 +108,7 @@ std::string serializeString(const std::string &plain) std::string s; char buf[2]; - if (plain.size() > 65535) + if (plain.size() > STRING_MAX_LEN) throw SerializationError("String too long for serializeString"); writeU16((u8 *)&buf[0], plain.size()); @@ -79,8 +150,8 @@ std::string serializeWideString(const std::wstring &plain) std::string s; char buf[2]; - if (plain.size() > 65535) - throw SerializationError("String too long for serializeString"); + if (plain.size() > WIDE_STRING_MAX_LEN) + throw SerializationError("String too long for serializeWideString"); writeU16((u8 *)buf, plain.size()); s.append(buf, 2); @@ -99,7 +170,7 @@ std::wstring deSerializeWideString(std::istream &is) is.read(buf, 2); if (is.gcount() != 2) - throw SerializationError("deSerializeString: size not read"); + throw SerializationError("deSerializeWideString: size not read"); u16 s_size = readU16((u8 *)buf); if (s_size == 0) @@ -127,7 +198,7 @@ std::string serializeLongString(const std::string &plain) { char buf[4]; - if (plain.size() > LONG_STRING_MAX) + if (plain.size() > LONG_STRING_MAX_LEN) throw SerializationError("String too long for serializeLongString"); writeU32((u8*)&buf[0], plain.size()); @@ -151,15 +222,15 @@ std::string deSerializeLongString(std::istream &is) return s; // We don't really want a remote attacker to force us to allocate 4GB... - if (s_size > LONG_STRING_MAX) { + if (s_size > LONG_STRING_MAX_LEN) { throw SerializationError("deSerializeLongString: " "string too long: " + itos(s_size) + " bytes"); } Buffer buf2(s_size); is.read(&buf2[0], s_size); - if (is.gcount() != s_size) - throw SerializationError("deSerializeString: couldn't read all chars"); + if ((u32)is.gcount() != s_size) + throw SerializationError("deSerializeLongString: couldn't read all chars"); s.reserve(s_size); s.append(&buf2[0], s_size); @@ -283,6 +354,55 @@ std::string deSerializeJsonString(std::istream &is) return os.str(); } +std::string serializeJsonStringIfNeeded(const std::string &s) +{ + for (size_t i = 0; i < s.size(); ++i) { + if (s[i] <= 0x1f || s[i] >= 0x7f || s[i] == ' ' || s[i] == '\"') + return serializeJsonString(s); + } + return s; +} + +std::string deSerializeJsonStringIfNeeded(std::istream &is) +{ + std::ostringstream tmp_os; + bool expect_initial_quote = true; + bool is_json = false; + bool was_backslash = false; + for (;;) { + char c = is.get(); + if (is.eof()) + break; + + if (expect_initial_quote && c == '"') { + tmp_os << c; + is_json = true; + } else if(is_json) { + tmp_os << c; + if (was_backslash) + was_backslash = false; + else if (c == '\\') + was_backslash = true; + else if (c == '"') + break; // Found end of string + } else { + if (c == ' ') { + // Found end of word + is.unget(); + break; + } else { + tmp_os << c; + } + } + expect_initial_quote = false; + } + if (is_json) { + std::istringstream tmp_is(tmp_os.str(), std::ios::binary); + return deSerializeJsonString(tmp_is); + } else + return tmp_os.str(); +} + //// //// String/Struct conversions ////