// static std::string LLURI::unescape(const std::string& str) { std::ostringstream ostr; std::string::const_iterator it = str.begin(); std::string::const_iterator end = str.end(); for(; it != end; ++it) { if((*it) == '%') { ++it; if(it == end) break; if(is_char_hex(*it)) { U8 c = hex_as_nybble(*it++); c = c << 4; if (it == end) break; if(is_char_hex(*it)) { c |= hex_as_nybble(*it); ostr.put((char)c); } else { ostr.put((char)c); ostr.put(*it); } } else { ostr.put('%'); ostr.put(*it); } } else { ostr.put(*it); } } return ostr.str(); }
bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const { // binary: b##"ff3120ab1" // or: b(len)"..." // I want to manually control those values here to make sure the // parser doesn't break when someone changes a constant somewhere // else. const U32 BINARY_BUFFER_SIZE = 256; const U32 STREAM_GET_COUNT = 255; // need to read the base out. char buf[BINARY_BUFFER_SIZE]; /* Flawfinder: ignore */ get(istr, buf, STREAM_GET_COUNT, '"'); char c = get(istr); if(c != '"') return false; if(0 == strncmp("b(", buf, 2)) { // We probably have a valid raw binary stream. determine // the size, and read it. S32 len = strtol(buf + 2, NULL, 0); if(mCheckLimits && (len > mMaxBytesLeft)) return false; std::vector<U8> value; if(len) { value.resize(len); account(fullread(istr, (char *)&value[0], len)); } c = get(istr); // strip off the trailing double-quote data = value; } else if(0 == strncmp("b64", buf, 3)) { // *FIX: A bit inefficient, but works for now. To make the // format better, I would need to add a hint into the // serialization format that indicated how long it was. std::stringstream coded_stream; get(istr, *(coded_stream.rdbuf()), '\"'); c = get(istr); std::string encoded(coded_stream.str()); S32 len = apr_base64_decode_len(encoded.c_str()); std::vector<U8> value; if(len) { value.resize(len); len = apr_base64_decode_binary(&value[0], encoded.c_str()); value.resize(len); } data = value; } else if(0 == strncmp("b16", buf, 3)) { // yay, base 16. We pop the next character which is either a // double quote or base 16 data. If it's a double quote, we're // done parsing. If it's not, put the data back, and read the // stream until the next double quote. char* read; /*Flawfinder: ignore*/ U8 byte; U8 byte_buffer[BINARY_BUFFER_SIZE]; U8* write; std::vector<U8> value; c = get(istr); while(c != '"') { putback(istr, c); read = buf; write = byte_buffer; get(istr, buf, STREAM_GET_COUNT, '"'); c = get(istr); while(*read != '\0') /*Flawfinder: ignore*/ { byte = hex_as_nybble(*read++); byte = byte << 4; byte |= hex_as_nybble(*read++); *write++ = byte; } // copy the data out of the byte buffer value.insert(value.end(), byte_buffer, write); } data = value; } else { return false; } return true; }
int deserialize_string_delim( std::istream& istr, std::string& value, char delim) { std::ostringstream write_buffer; bool found_escape = false; bool found_hex = false; bool found_digit = false; U8 byte = 0; int count = 0; while (true) { char next_char = istr.get(); ++count; if(istr.fail()) { // If our stream is empty, break out value = write_buffer.str(); return LLSDParser::PARSE_FAILURE; } if(found_escape) { // next character(s) is a special sequence. if(found_hex) { if(found_digit) { found_digit = false; found_hex = false; found_escape = false; byte = byte << 4; byte |= hex_as_nybble(next_char); write_buffer << byte; byte = 0; } else { // next character is the first nybble of // found_digit = true; byte = hex_as_nybble(next_char); } } else if(next_char == 'x') { found_hex = true; } else { switch(next_char) { case 'a': write_buffer << '\a'; break; case 'b': write_buffer << '\b'; break; case 'f': write_buffer << '\f'; break; case 'n': write_buffer << '\n'; break; case 'r': write_buffer << '\r'; break; case 't': write_buffer << '\t'; break; case 'v': write_buffer << '\v'; break; default: write_buffer << next_char; break; } found_escape = false; } } else if(next_char == '\\') { found_escape = true; } else if(next_char == delim) { break; } else { write_buffer << next_char; } } value = write_buffer.str(); return count; }