PageRenderTime 160ms CodeModel.GetById 10ms app.highlight 137ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llcommon/llsdserialize.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2170 lines | 1783 code | 166 blank | 221 comment | 197 complexity | 7f8958a866a6dd9d98ef17dd5e8ad27b MD5 | raw file
   1/** 
   2 * @file llsdserialize.cpp
   3 * @author Phoenix
   4 * @date 2006-03-05
   5 * @brief Implementation of LLSD parsers and formatters
   6 *
   7 * $LicenseInfo:firstyear=2006&license=viewerlgpl$
   8 * Second Life Viewer Source Code
   9 * Copyright (C) 2010, Linden Research, Inc.
  10 * 
  11 * This library is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU Lesser General Public
  13 * License as published by the Free Software Foundation;
  14 * version 2.1 of the License only.
  15 * 
  16 * This library is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19 * Lesser General Public License for more details.
  20 * 
  21 * You should have received a copy of the GNU Lesser General Public
  22 * License along with this library; if not, write to the Free Software
  23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  24 * 
  25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  26 * $/LicenseInfo$
  27 */
  28
  29#include "linden_common.h"
  30#include "llsdserialize.h"
  31#include "llpointer.h"
  32#include "llstreamtools.h" // for fullread
  33
  34#include <iostream>
  35#include "apr_base64.h"
  36
  37#ifdef LL_STANDALONE
  38# include <zlib.h>
  39#else
  40# include "zlib/zlib.h"  // for davep's dirty little zip functions
  41#endif
  42
  43#if !LL_WINDOWS
  44#include <netinet/in.h> // htonl & ntohl
  45#endif
  46
  47#include "lldate.h"
  48#include "llsd.h"
  49#include "llstring.h"
  50#include "lluri.h"
  51
  52// File constants
  53static const int MAX_HDR_LEN = 20;
  54static const char LEGACY_NON_HEADER[] = "<llsd>";
  55const std::string LLSD_BINARY_HEADER("LLSD/Binary");
  56const std::string LLSD_XML_HEADER("LLSD/XML");
  57
  58/**
  59 * LLSDSerialize
  60 */
  61
  62// static
  63void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
  64{
  65	LLPointer<LLSDFormatter> f = NULL;
  66
  67	switch (type)
  68	{
  69	case LLSD_BINARY:
  70		str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
  71		f = new LLSDBinaryFormatter;
  72		break;
  73
  74	case LLSD_XML:
  75		str << "<? " << LLSD_XML_HEADER << " ?>\n";
  76		f = new LLSDXMLFormatter;
  77		break;
  78
  79	default:
  80		llwarns << "serialize request for unknown ELLSD_Serialize" << llendl;
  81	}
  82
  83	if (f.notNull())
  84	{
  85		f->format(sd, str, options);
  86	}
  87}
  88
  89// static
  90bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
  91{
  92	LLPointer<LLSDParser> p = NULL;
  93	char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
  94	int i;
  95	int inbuf = 0;
  96	bool legacy_no_header = false;
  97	bool fail_if_not_legacy = false;
  98	std::string header;
  99
 100	/*
 101	 * Get the first line before anything.
 102	 */
 103	str.get(hdr_buf, MAX_HDR_LEN, '\n');
 104	if (str.fail())
 105	{
 106		str.clear();
 107		fail_if_not_legacy = true;
 108	}
 109
 110	if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
 111	{
 112		legacy_no_header = true;
 113		inbuf = str.gcount();
 114	}
 115	else
 116	{
 117		if (fail_if_not_legacy)
 118			goto fail;
 119		/*
 120		* Remove the newline chars
 121		*/
 122		for (i = 0; i < MAX_HDR_LEN; i++)
 123		{
 124			if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
 125				hdr_buf[i] == '\n')
 126			{
 127				hdr_buf[i] = 0;
 128				break;
 129			}
 130		}
 131		header = hdr_buf;
 132
 133		std::string::size_type start = std::string::npos;
 134		std::string::size_type end = std::string::npos;
 135		start = header.find_first_not_of("<? ");
 136		if (start != std::string::npos)
 137		{
 138			end = header.find_first_of(" ?", start);
 139		}
 140		if ((start == std::string::npos) || (end == std::string::npos))
 141			goto fail;
 142
 143		header = header.substr(start, end - start);
 144		ws(str);
 145	}
 146	/*
 147	 * Create the parser as appropriate
 148	 */
 149	if (legacy_no_header)
 150	{	// Create a LLSD XML parser, and parse the first chunk read above
 151		LLSDXMLParser* x = new LLSDXMLParser();
 152		x->parsePart(hdr_buf, inbuf);	// Parse the first part that was already read
 153		x->parseLines(str, sd);			// Parse the rest of it
 154		delete x;
 155		return true;
 156	}
 157
 158	if (header == LLSD_BINARY_HEADER)
 159	{
 160		p = new LLSDBinaryParser;
 161	}
 162	else if (header == LLSD_XML_HEADER)
 163	{
 164		p = new LLSDXMLParser;
 165	}
 166	else
 167	{
 168		llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
 169	}
 170
 171	if (p.notNull())
 172	{
 173		p->parse(str, sd, max_bytes);
 174		return true;
 175	}
 176
 177fail:
 178	llwarns << "deserialize LLSD parse failure" << llendl;
 179	return false;
 180}
 181
 182/**
 183 * Endian handlers
 184 */
 185#if LL_BIG_ENDIAN
 186U64 ll_htonll(U64 hostlonglong) { return hostlonglong; }
 187U64 ll_ntohll(U64 netlonglong) { return netlonglong; }
 188F64 ll_htond(F64 hostlonglong) { return hostlonglong; }
 189F64 ll_ntohd(F64 netlonglong) { return netlonglong; }
 190#else
 191// I read some comments one a indicating that doing an integer add
 192// here would be faster than a bitwise or. For now, the or has
 193// programmer clarity, since the intended outcome matches the
 194// operation.
 195U64 ll_htonll(U64 hostlonglong)
 196{
 197	return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
 198			((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
 199}
 200U64 ll_ntohll(U64 netlonglong)
 201{
 202	return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
 203			((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
 204}
 205union LLEndianSwapper
 206{
 207	F64 d;
 208	U64 i;
 209};
 210F64 ll_htond(F64 hostdouble)
 211{
 212	LLEndianSwapper tmp;
 213	tmp.d = hostdouble;
 214	tmp.i = ll_htonll(tmp.i);
 215	return tmp.d;
 216}
 217F64 ll_ntohd(F64 netdouble)
 218{
 219	LLEndianSwapper tmp;
 220	tmp.d = netdouble;
 221	tmp.i = ll_ntohll(tmp.i);
 222	return tmp.d;
 223}
 224#endif
 225
 226/**
 227 * Local functions.
 228 */
 229/**
 230 * @brief Figure out what kind of string it is (raw or delimited) and handoff.
 231 *
 232 * @param istr The stream to read from.
 233 * @param value [out] The string which was found.
 234 * @param max_bytes The maximum possible length of the string. Passing in
 235 * a negative value will skip this check.
 236 * @return Returns number of bytes read off of the stream. Returns
 237 * PARSE_FAILURE (-1) on failure.
 238 */
 239int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
 240
 241/**
 242 * @brief Parse a delimited string. 
 243 *
 244 * @param istr The stream to read from, with the delimiter already popped.
 245 * @param value [out] The string which was found.
 246 * @param d The delimiter to use.
 247 * @return Returns number of bytes read off of the stream. Returns
 248 * PARSE_FAILURE (-1) on failure.
 249 */
 250int deserialize_string_delim(std::istream& istr, std::string& value, char d);
 251
 252/**
 253 * @brief Read a raw string off the stream.
 254 *
 255 * @param istr The stream to read from, with the (len) parameter
 256 * leading the stream.
 257 * @param value [out] The string which was found.
 258 * @param d The delimiter to use.
 259 * @param max_bytes The maximum possible length of the string. Passing in
 260 * a negative value will skip this check.
 261 * @return Returns number of bytes read off of the stream. Returns
 262 * PARSE_FAILURE (-1) on failure.
 263 */
 264int deserialize_string_raw(
 265	std::istream& istr,
 266	std::string& value,
 267	S32 max_bytes);
 268
 269/**
 270 * @brief helper method for dealing with the different notation boolean format.
 271 *
 272 * @param istr The stream to read from with the leading character stripped.
 273 * @param data [out] the result of the parse.
 274 * @param compare The string to compare the boolean against
 275 * @param vale The value to assign to data if the parse succeeds.
 276 * @return Returns number of bytes read off of the stream. Returns
 277 * PARSE_FAILURE (-1) on failure.
 278 */
 279int deserialize_boolean(
 280	std::istream& istr,
 281	LLSD& data,
 282	const std::string& compare,
 283	bool value);
 284
 285/**
 286 * @brief Do notation escaping of a string to an ostream.
 287 *
 288 * @param value The string to escape and serialize
 289 * @param str The stream to serialize to.
 290 */
 291void serialize_string(const std::string& value, std::ostream& str);
 292
 293
 294/**
 295 * Local constants.
 296 */
 297static const std::string NOTATION_TRUE_SERIAL("true");
 298static const std::string NOTATION_FALSE_SERIAL("false");
 299
 300static const char BINARY_TRUE_SERIAL = '1';
 301static const char BINARY_FALSE_SERIAL = '0';
 302
 303
 304/**
 305 * LLSDParser
 306 */
 307LLSDParser::LLSDParser()
 308	: mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false)
 309{
 310}
 311
 312// virtual
 313LLSDParser::~LLSDParser()
 314{ }
 315
 316S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
 317{
 318	mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
 319	mMaxBytesLeft = max_bytes;
 320	return doParse(istr, data);
 321}
 322
 323
 324// Parse using routine to get() lines, faster than parse()
 325S32 LLSDParser::parseLines(std::istream& istr, LLSD& data)
 326{
 327	mCheckLimits = false;
 328	mParseLines = true;
 329	return doParse(istr, data);
 330}
 331
 332
 333int LLSDParser::get(std::istream& istr) const
 334{
 335	if(mCheckLimits) --mMaxBytesLeft;
 336	return istr.get();
 337}
 338
 339std::istream& LLSDParser::get(
 340	std::istream& istr,
 341	char* s,
 342	std::streamsize n,
 343	char delim) const
 344{
 345	istr.get(s, n, delim);
 346	if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
 347	return istr;
 348}
 349
 350std::istream& LLSDParser::get(
 351		std::istream& istr,
 352		std::streambuf& sb,
 353		char delim) const		
 354{
 355	istr.get(sb, delim);
 356	if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
 357	return istr;
 358}
 359
 360std::istream& LLSDParser::ignore(std::istream& istr) const
 361{
 362	istr.ignore();
 363	if(mCheckLimits) --mMaxBytesLeft;
 364	return istr;
 365}
 366
 367std::istream& LLSDParser::putback(std::istream& istr, char c) const
 368{
 369	istr.putback(c);
 370	if(mCheckLimits) ++mMaxBytesLeft;
 371	return istr;
 372}
 373
 374std::istream& LLSDParser::read(
 375	std::istream& istr,
 376	char* s,
 377	std::streamsize n) const
 378{
 379	istr.read(s, n);
 380	if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
 381	return istr;
 382}
 383
 384void LLSDParser::account(S32 bytes) const
 385{
 386	if(mCheckLimits) mMaxBytesLeft -= bytes;
 387}
 388
 389
 390/**
 391 * LLSDNotationParser
 392 */
 393LLSDNotationParser::LLSDNotationParser()
 394{
 395}	
 396
 397// virtual
 398LLSDNotationParser::~LLSDNotationParser()
 399{ }
 400
 401// virtual
 402S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 403{
 404	// map: { string:object, string:object }
 405	// array: [ object, object, object ]
 406	// undef: !
 407	// boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
 408	// integer: i####
 409	// real: r####
 410	// uuid: u####
 411	// string: "g'day" | 'have a "nice" day' | s(size)"raw data"
 412	// uri: l"escaped"
 413	// date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
 414	// binary: b##"ff3120ab1" | b(size)"raw data"
 415	char c;
 416	c = istr.peek();
 417	while(isspace(c))
 418	{
 419		// pop the whitespace.
 420		c = get(istr);
 421		c = istr.peek();
 422		continue;
 423	}
 424	if(!istr.good())
 425	{
 426		return 0;
 427	}
 428	S32 parse_count = 1;
 429	switch(c)
 430	{
 431	case '{':
 432	{
 433		S32 child_count = parseMap(istr, data);
 434		if((child_count == PARSE_FAILURE) || data.isUndefined())
 435		{
 436			parse_count = PARSE_FAILURE;
 437		}
 438		else
 439		{
 440			parse_count += child_count;
 441		}
 442		if(istr.fail())
 443		{
 444			llinfos << "STREAM FAILURE reading map." << llendl;
 445			parse_count = PARSE_FAILURE;
 446		}
 447		break;
 448	}
 449
 450	case '[':
 451	{
 452		S32 child_count = parseArray(istr, data);
 453		if((child_count == PARSE_FAILURE) || data.isUndefined())
 454		{
 455			parse_count = PARSE_FAILURE;
 456		}
 457		else
 458		{
 459			parse_count += child_count;
 460		}
 461		if(istr.fail())
 462		{
 463			llinfos << "STREAM FAILURE reading array." << llendl;
 464			parse_count = PARSE_FAILURE;
 465		}
 466		break;
 467	}
 468
 469	case '!':
 470		c = get(istr);
 471		data.clear();
 472		break;
 473
 474	case '0':
 475		c = get(istr);
 476		data = false;
 477		break;
 478
 479	case 'F':
 480	case 'f':
 481		ignore(istr);
 482		c = istr.peek();
 483		if(isalpha(c))
 484		{
 485			int cnt = deserialize_boolean(
 486				istr,
 487				data,
 488				NOTATION_FALSE_SERIAL,
 489				false);
 490			if(PARSE_FAILURE == cnt) parse_count = cnt;
 491			else account(cnt);
 492		}
 493		else
 494		{
 495			data = false;
 496		}
 497		if(istr.fail())
 498		{
 499			llinfos << "STREAM FAILURE reading boolean." << llendl;
 500			parse_count = PARSE_FAILURE;
 501		}
 502		break;
 503
 504	case '1':
 505		c = get(istr);
 506		data = true;
 507		break;
 508
 509	case 'T':
 510	case 't':
 511		ignore(istr);
 512		c = istr.peek();
 513		if(isalpha(c))
 514		{
 515			int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
 516			if(PARSE_FAILURE == cnt) parse_count = cnt;
 517			else account(cnt);
 518		}
 519		else
 520		{
 521			data = true;
 522		}
 523		if(istr.fail())
 524		{
 525			llinfos << "STREAM FAILURE reading boolean." << llendl;
 526			parse_count = PARSE_FAILURE;
 527		}
 528		break;
 529
 530	case 'i':
 531	{
 532		c = get(istr);
 533		S32 integer = 0;
 534		istr >> integer;
 535		data = integer;
 536		if(istr.fail())
 537		{
 538			llinfos << "STREAM FAILURE reading integer." << llendl;
 539			parse_count = PARSE_FAILURE;
 540		}
 541		break;
 542	}
 543
 544	case 'r':
 545	{
 546		c = get(istr);
 547		F64 real = 0.0;
 548		istr >> real;
 549		data = real;
 550		if(istr.fail())
 551		{
 552			llinfos << "STREAM FAILURE reading real." << llendl;
 553			parse_count = PARSE_FAILURE;
 554		}
 555		break;
 556	}
 557
 558	case 'u':
 559	{
 560		c = get(istr);
 561		LLUUID id;
 562		istr >> id;
 563		data = id;
 564		if(istr.fail())
 565		{
 566			llinfos << "STREAM FAILURE reading uuid." << llendl;
 567			parse_count = PARSE_FAILURE;
 568		}
 569		break;
 570	}
 571
 572	case '\"':
 573	case '\'':
 574	case 's':
 575		if(!parseString(istr, data))
 576		{
 577			parse_count = PARSE_FAILURE;
 578		}
 579		if(istr.fail())
 580		{
 581			llinfos << "STREAM FAILURE reading string." << llendl;
 582			parse_count = PARSE_FAILURE;
 583		}
 584		break;
 585
 586	case 'l':
 587	{
 588		c = get(istr); // pop the 'l'
 589		c = get(istr); // pop the delimiter
 590		std::string str;
 591		int cnt = deserialize_string_delim(istr, str, c);
 592		if(PARSE_FAILURE == cnt)
 593		{
 594			parse_count = PARSE_FAILURE;
 595		}
 596		else
 597		{
 598			data = LLURI(str);
 599			account(cnt);
 600		}
 601		if(istr.fail())
 602		{
 603			llinfos << "STREAM FAILURE reading link." << llendl;
 604			parse_count = PARSE_FAILURE;
 605		}
 606		break;
 607	}
 608
 609	case 'd':
 610	{
 611		c = get(istr); // pop the 'd'
 612		c = get(istr); // pop the delimiter
 613		std::string str;
 614		int cnt = deserialize_string_delim(istr, str, c);
 615		if(PARSE_FAILURE == cnt)
 616		{
 617			parse_count = PARSE_FAILURE;
 618		}
 619		else
 620		{
 621			data = LLDate(str);
 622			account(cnt);
 623		}
 624		if(istr.fail())
 625		{
 626			llinfos << "STREAM FAILURE reading date." << llendl;
 627			parse_count = PARSE_FAILURE;
 628		}
 629		break;
 630	}
 631
 632	case 'b':
 633		if(!parseBinary(istr, data))
 634		{
 635			parse_count = PARSE_FAILURE;
 636		}
 637		if(istr.fail())
 638		{
 639			llinfos << "STREAM FAILURE reading data." << llendl;
 640			parse_count = PARSE_FAILURE;
 641		}
 642		break;
 643
 644	default:
 645		parse_count = PARSE_FAILURE;
 646		llinfos << "Unrecognized character while parsing: int(" << (int)c
 647			<< ")" << llendl;
 648		break;
 649	}
 650	if(PARSE_FAILURE == parse_count)
 651	{
 652		data.clear();
 653	}
 654	return parse_count;
 655}
 656
 657S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
 658{
 659	// map: { string:object, string:object }
 660	map = LLSD::emptyMap();
 661	S32 parse_count = 0;
 662	char c = get(istr);
 663	if(c == '{')
 664	{
 665		// eat commas, white
 666		bool found_name = false;
 667		std::string name;
 668		c = get(istr);
 669		while(c != '}' && istr.good())
 670		{
 671			if(!found_name)
 672			{
 673				if((c == '\"') || (c == '\'') || (c == 's'))
 674				{
 675					putback(istr, c);
 676					found_name = true;
 677					int count = deserialize_string(istr, name, mMaxBytesLeft);
 678					if(PARSE_FAILURE == count) return PARSE_FAILURE;
 679					account(count);
 680				}
 681				c = get(istr);
 682			}
 683			else
 684			{
 685				if(isspace(c) || (c == ':'))
 686				{
 687					c = get(istr);
 688					continue;
 689				}
 690				putback(istr, c);
 691				LLSD child;
 692				S32 count = doParse(istr, child);
 693				if(count > 0)
 694				{
 695					// There must be a value for every key, thus
 696					// child_count must be greater than 0.
 697					parse_count += count;
 698					map.insert(name, child);
 699				}
 700				else
 701				{
 702					return PARSE_FAILURE;
 703				}
 704				found_name = false;
 705				c = get(istr);
 706			}
 707		}
 708		if(c != '}')
 709		{
 710			map.clear();
 711			return PARSE_FAILURE;
 712		}
 713	}
 714	return parse_count;
 715}
 716
 717S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
 718{
 719	// array: [ object, object, object ]
 720	array = LLSD::emptyArray();
 721	S32 parse_count = 0;
 722	char c = get(istr);
 723	if(c == '[')
 724	{
 725		// eat commas, white
 726		c = get(istr);
 727		while((c != ']') && istr.good())
 728		{
 729			LLSD child;
 730			if(isspace(c) || (c == ','))
 731			{
 732				c = get(istr);
 733				continue;
 734			}
 735			putback(istr, c);
 736			S32 count = doParse(istr, child);
 737			if(PARSE_FAILURE == count)
 738			{
 739				return PARSE_FAILURE;
 740			}
 741			else
 742			{
 743				parse_count += count;
 744				array.append(child);
 745			}
 746			c = get(istr);
 747		}
 748		if(c != ']')
 749		{
 750			return PARSE_FAILURE;
 751		}
 752	}
 753	return parse_count;
 754}
 755
 756bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
 757{
 758	std::string value;
 759	int count = deserialize_string(istr, value, mMaxBytesLeft);
 760	if(PARSE_FAILURE == count) return false;
 761	account(count);
 762	data = value;
 763	return true;
 764}
 765
 766bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
 767{
 768	// binary: b##"ff3120ab1"
 769	// or: b(len)"..."
 770
 771	// I want to manually control those values here to make sure the
 772	// parser doesn't break when someone changes a constant somewhere
 773	// else.
 774	const U32 BINARY_BUFFER_SIZE = 256;
 775	const U32 STREAM_GET_COUNT = 255;
 776
 777	// need to read the base out.
 778	char buf[BINARY_BUFFER_SIZE];		/* Flawfinder: ignore */
 779	get(istr, buf, STREAM_GET_COUNT, '"');
 780	char c = get(istr);
 781	if(c != '"') return false;
 782	if(0 == strncmp("b(", buf, 2))
 783	{
 784		// We probably have a valid raw binary stream. determine
 785		// the size, and read it.
 786		S32 len = strtol(buf + 2, NULL, 0);
 787		if(mCheckLimits && (len > mMaxBytesLeft)) return false;
 788		std::vector<U8> value;
 789		if(len)
 790		{
 791			value.resize(len);
 792			account(fullread(istr, (char *)&value[0], len));
 793		}
 794		c = get(istr); // strip off the trailing double-quote
 795		data = value;
 796	}
 797	else if(0 == strncmp("b64", buf, 3))
 798	{
 799		// *FIX: A bit inefficient, but works for now. To make the
 800		// format better, I would need to add a hint into the
 801		// serialization format that indicated how long it was.
 802		std::stringstream coded_stream;
 803		get(istr, *(coded_stream.rdbuf()), '\"');
 804		c = get(istr);
 805		std::string encoded(coded_stream.str());
 806		S32 len = apr_base64_decode_len(encoded.c_str());
 807		std::vector<U8> value;
 808		if(len)
 809		{
 810			value.resize(len);
 811			len = apr_base64_decode_binary(&value[0], encoded.c_str());
 812			value.resize(len);
 813		}
 814		data = value;
 815	}
 816	else if(0 == strncmp("b16", buf, 3))
 817	{
 818		// yay, base 16. We pop the next character which is either a
 819		// double quote or base 16 data. If it's a double quote, we're
 820		// done parsing. If it's not, put the data back, and read the
 821		// stream until the next double quote.
 822		char* read;	 /*Flawfinder: ignore*/
 823		U8 byte;
 824		U8 byte_buffer[BINARY_BUFFER_SIZE];
 825		U8* write;
 826		std::vector<U8> value;
 827		c = get(istr);
 828		while(c != '"')
 829		{
 830			putback(istr, c);
 831			read = buf;
 832			write = byte_buffer;
 833			get(istr, buf, STREAM_GET_COUNT, '"');
 834			c = get(istr);
 835			while(*read != '\0')	 /*Flawfinder: ignore*/
 836			{
 837				byte = hex_as_nybble(*read++);
 838				byte = byte << 4;
 839				byte |= hex_as_nybble(*read++);
 840				*write++ = byte;
 841			}
 842			// copy the data out of the byte buffer
 843			value.insert(value.end(), byte_buffer, write);
 844		}
 845		data = value;
 846	}
 847	else
 848	{
 849		return false;
 850	}
 851	return true;
 852}
 853
 854
 855/**
 856 * LLSDBinaryParser
 857 */
 858LLSDBinaryParser::LLSDBinaryParser()
 859{
 860}
 861
 862// virtual
 863LLSDBinaryParser::~LLSDBinaryParser()
 864{
 865}
 866
 867// virtual
 868S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 869{
 870/**
 871 * Undefined: '!'<br>
 872 * Boolean: 't' for true 'f' for false<br>
 873 * Integer: 'i' + 4 bytes network byte order<br>
 874 * Real: 'r' + 8 bytes IEEE double<br>
 875 * UUID: 'u' + 16 byte unsigned integer<br>
 876 * String: 's' + 4 byte integer size + string<br>
 877 *  strings also secretly support the notation format
 878 * Date: 'd' + 8 byte IEEE double for seconds since epoch<br>
 879 * URI: 'l' + 4 byte integer size + string uri<br>
 880 * Binary: 'b' + 4 byte integer size + binary data<br>
 881 * Array: '[' + 4 byte integer size  + all values + ']'<br>
 882 * Map: '{' + 4 byte integer size  every(key + value) + '}'<br>
 883 *  map keys are serialized as s + 4 byte integer size + string or in the
 884 *  notation format.
 885 */
 886	char c;
 887	c = get(istr);
 888	if(!istr.good())
 889	{
 890		return 0;
 891	}
 892	S32 parse_count = 1;
 893	switch(c)
 894	{
 895	case '{':
 896	{
 897		S32 child_count = parseMap(istr, data);
 898		if((child_count == PARSE_FAILURE) || data.isUndefined())
 899		{
 900			parse_count = PARSE_FAILURE;
 901		}
 902		else
 903		{
 904			parse_count += child_count;
 905		}
 906		if(istr.fail())
 907		{
 908			llinfos << "STREAM FAILURE reading binary map." << llendl;
 909			parse_count = PARSE_FAILURE;
 910		}
 911		break;
 912	}
 913
 914	case '[':
 915	{
 916		S32 child_count = parseArray(istr, data);
 917		if((child_count == PARSE_FAILURE) || data.isUndefined())
 918		{
 919			parse_count = PARSE_FAILURE;
 920		}
 921		else
 922		{
 923			parse_count += child_count;
 924		}
 925		if(istr.fail())
 926		{
 927			llinfos << "STREAM FAILURE reading binary array." << llendl;
 928			parse_count = PARSE_FAILURE;
 929		}
 930		break;
 931	}
 932
 933	case '!':
 934		data.clear();
 935		break;
 936
 937	case '0':
 938		data = false;
 939		break;
 940
 941	case '1':
 942		data = true;
 943		break;
 944
 945	case 'i':
 946	{
 947		U32 value_nbo = 0;
 948		read(istr, (char*)&value_nbo, sizeof(U32));	 /*Flawfinder: ignore*/
 949		data = (S32)ntohl(value_nbo);
 950		if(istr.fail())
 951		{
 952			llinfos << "STREAM FAILURE reading binary integer." << llendl;
 953		}
 954		break;
 955	}
 956
 957	case 'r':
 958	{
 959		F64 real_nbo = 0.0;
 960		read(istr, (char*)&real_nbo, sizeof(F64));	 /*Flawfinder: ignore*/
 961		data = ll_ntohd(real_nbo);
 962		if(istr.fail())
 963		{
 964			llinfos << "STREAM FAILURE reading binary real." << llendl;
 965		}
 966		break;
 967	}
 968
 969	case 'u':
 970	{
 971		LLUUID id;
 972		read(istr, (char*)(&id.mData), UUID_BYTES);	 /*Flawfinder: ignore*/
 973		data = id;
 974		if(istr.fail())
 975		{
 976			llinfos << "STREAM FAILURE reading binary uuid." << llendl;
 977		}
 978		break;
 979	}
 980
 981	case '\'':
 982	case '"':
 983	{
 984		std::string value;
 985		int cnt = deserialize_string_delim(istr, value, c);
 986		if(PARSE_FAILURE == cnt)
 987		{
 988			parse_count = PARSE_FAILURE;
 989		}
 990		else
 991		{
 992			data = value;
 993			account(cnt);
 994		}
 995		if(istr.fail())
 996		{
 997			llinfos << "STREAM FAILURE reading binary (notation-style) string."
 998				<< llendl;
 999			parse_count = PARSE_FAILURE;
1000		}
1001		break;
1002	}
1003
1004	case 's':
1005	{
1006		std::string value;
1007		if(parseString(istr, value))
1008		{
1009			data = value;
1010		}
1011		else
1012		{
1013			parse_count = PARSE_FAILURE;
1014		}
1015		if(istr.fail())
1016		{
1017			llinfos << "STREAM FAILURE reading binary string." << llendl;
1018			parse_count = PARSE_FAILURE;
1019		}
1020		break;
1021	}
1022
1023	case 'l':
1024	{
1025		std::string value;
1026		if(parseString(istr, value))
1027		{
1028			data = LLURI(value);
1029		}
1030		else
1031		{
1032			parse_count = PARSE_FAILURE;
1033		}
1034		if(istr.fail())
1035		{
1036			llinfos << "STREAM FAILURE reading binary link." << llendl;
1037			parse_count = PARSE_FAILURE;
1038		}
1039		break;
1040	}
1041
1042	case 'd':
1043	{
1044		F64 real = 0.0;
1045		read(istr, (char*)&real, sizeof(F64));	 /*Flawfinder: ignore*/
1046		data = LLDate(real);
1047		if(istr.fail())
1048		{
1049			llinfos << "STREAM FAILURE reading binary date." << llendl;
1050			parse_count = PARSE_FAILURE;
1051		}
1052		break;
1053	}
1054
1055	case 'b':
1056	{
1057		// We probably have a valid raw binary stream. determine
1058		// the size, and read it.
1059		U32 size_nbo = 0;
1060		read(istr, (char*)&size_nbo, sizeof(U32));	/*Flawfinder: ignore*/
1061		S32 size = (S32)ntohl(size_nbo);
1062		if(mCheckLimits && (size > mMaxBytesLeft))
1063		{
1064			parse_count = PARSE_FAILURE;
1065		}
1066		else
1067		{
1068			std::vector<U8> value;
1069			if(size > 0)
1070			{
1071				value.resize(size);
1072				account(fullread(istr, (char*)&value[0], size));
1073			}
1074			data = value;
1075		}
1076		if(istr.fail())
1077		{
1078			llinfos << "STREAM FAILURE reading binary." << llendl;
1079			parse_count = PARSE_FAILURE;
1080		}
1081		break;
1082	}
1083
1084	default:
1085		parse_count = PARSE_FAILURE;
1086		llinfos << "Unrecognized character while parsing: int(" << (int)c
1087			<< ")" << llendl;
1088		break;
1089	}
1090	if(PARSE_FAILURE == parse_count)
1091	{
1092		data.clear();
1093	}
1094	return parse_count;
1095}
1096
1097S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
1098{
1099	map = LLSD::emptyMap();
1100	U32 value_nbo = 0;
1101	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
1102	S32 size = (S32)ntohl(value_nbo);
1103	S32 parse_count = 0;
1104	S32 count = 0;
1105	char c = get(istr);
1106	while(c != '}' && (count < size) && istr.good())
1107	{
1108		std::string name;
1109		switch(c)
1110		{
1111		case 'k':
1112			if(!parseString(istr, name))
1113			{
1114				return PARSE_FAILURE;
1115			}
1116			break;
1117		case '\'':
1118		case '"':
1119		{
1120			int cnt = deserialize_string_delim(istr, name, c);
1121			if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
1122			account(cnt);
1123			break;
1124		}
1125		}
1126		LLSD child;
1127		S32 child_count = doParse(istr, child);
1128		if(child_count > 0)
1129		{
1130			// There must be a value for every key, thus child_count
1131			// must be greater than 0.
1132			parse_count += child_count;
1133			map.insert(name, child);
1134		}
1135		else
1136		{
1137			return PARSE_FAILURE;
1138		}
1139		++count;
1140		c = get(istr);
1141	}
1142	if((c != '}') || (count < size))
1143	{
1144		// Make sure it is correctly terminated and we parsed as many
1145		// as were said to be there.
1146		return PARSE_FAILURE;
1147	}
1148	return parse_count;
1149}
1150
1151S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
1152{
1153	array = LLSD::emptyArray();
1154	U32 value_nbo = 0;
1155	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
1156	S32 size = (S32)ntohl(value_nbo);
1157
1158	// *FIX: This would be a good place to reserve some space in the
1159	// array...
1160
1161	S32 parse_count = 0;
1162	S32 count = 0;
1163	char c = istr.peek();
1164	while((c != ']') && (count < size) && istr.good())
1165	{
1166		LLSD child;
1167		S32 child_count = doParse(istr, child);
1168		if(PARSE_FAILURE == child_count)
1169		{
1170			return PARSE_FAILURE;
1171		}
1172		if(child_count)
1173		{
1174			parse_count += child_count;
1175			array.append(child);
1176		}
1177		++count;
1178		c = istr.peek();
1179	}
1180	c = get(istr);
1181	if((c != ']') || (count < size))
1182	{
1183		// Make sure it is correctly terminated and we parsed as many
1184		// as were said to be there.
1185		return PARSE_FAILURE;
1186	}
1187	return parse_count;
1188}
1189
1190bool LLSDBinaryParser::parseString(
1191	std::istream& istr,
1192	std::string& value) const
1193{
1194	// *FIX: This is memory inefficient.
1195	U32 value_nbo = 0;
1196	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
1197	S32 size = (S32)ntohl(value_nbo);
1198	if(mCheckLimits && (size > mMaxBytesLeft)) return false;
1199	std::vector<char> buf;
1200	if(size)
1201	{
1202		buf.resize(size);
1203		account(fullread(istr, &buf[0], size));
1204		value.assign(buf.begin(), buf.end());
1205	}
1206	return true;
1207}
1208
1209
1210/**
1211 * LLSDFormatter
1212 */
1213LLSDFormatter::LLSDFormatter() :
1214	mBoolAlpha(false)
1215{
1216}
1217
1218// virtual
1219LLSDFormatter::~LLSDFormatter()
1220{ }
1221
1222void LLSDFormatter::boolalpha(bool alpha)
1223{
1224	mBoolAlpha = alpha;
1225}
1226
1227void LLSDFormatter::realFormat(const std::string& format)
1228{
1229	mRealFormat = format;
1230}
1231
1232void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const
1233{
1234	std::string buffer = llformat(mRealFormat.c_str(), real);
1235	ostr << buffer;
1236}
1237
1238/**
1239 * LLSDNotationFormatter
1240 */
1241LLSDNotationFormatter::LLSDNotationFormatter()
1242{
1243}
1244
1245// virtual
1246LLSDNotationFormatter::~LLSDNotationFormatter()
1247{ }
1248
1249// static
1250std::string LLSDNotationFormatter::escapeString(const std::string& in)
1251{
1252	std::ostringstream ostr;
1253	serialize_string(in, ostr);
1254	return ostr.str();
1255}
1256
1257// virtual
1258S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
1259{
1260	S32 format_count = 1;
1261	switch(data.type())
1262	{
1263	case LLSD::TypeMap:
1264	{
1265		ostr << "{";
1266		bool need_comma = false;
1267		LLSD::map_const_iterator iter = data.beginMap();
1268		LLSD::map_const_iterator end = data.endMap();
1269		for(; iter != end; ++iter)
1270		{
1271			if(need_comma) ostr << ",";
1272			need_comma = true;
1273			ostr << '\'';
1274			serialize_string((*iter).first, ostr);
1275			ostr << "':";
1276			format_count += format((*iter).second, ostr);
1277		}
1278		ostr << "}";
1279		break;
1280	}
1281
1282	case LLSD::TypeArray:
1283	{
1284		ostr << "[";
1285		bool need_comma = false;
1286		LLSD::array_const_iterator iter = data.beginArray();
1287		LLSD::array_const_iterator end = data.endArray();
1288		for(; iter != end; ++iter)
1289		{
1290			if(need_comma) ostr << ",";
1291			need_comma = true;
1292			format_count += format(*iter, ostr);
1293		}
1294		ostr << "]";
1295		break;
1296	}
1297
1298	case LLSD::TypeUndefined:
1299		ostr << "!";
1300		break;
1301
1302	case LLSD::TypeBoolean:
1303		if(mBoolAlpha ||
1304#if( LL_WINDOWS || __GNUC__ > 2)
1305		   (ostr.flags() & std::ios::boolalpha)
1306#else
1307		   (ostr.flags() & 0x0100)
1308#endif
1309			)
1310		{
1311			ostr << (data.asBoolean()
1312					 ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
1313		}
1314		else
1315		{
1316			ostr << (data.asBoolean() ? 1 : 0);
1317		}
1318		break;
1319
1320	case LLSD::TypeInteger:
1321		ostr << "i" << data.asInteger();
1322		break;
1323
1324	case LLSD::TypeReal:
1325		ostr << "r";
1326		if(mRealFormat.empty())
1327		{
1328			ostr << data.asReal();
1329		}
1330		else
1331		{
1332			formatReal(data.asReal(), ostr);
1333		}
1334		break;
1335
1336	case LLSD::TypeUUID:
1337		ostr << "u" << data.asUUID();
1338		break;
1339
1340	case LLSD::TypeString:
1341		ostr << '\'';
1342		serialize_string(data.asString(), ostr);
1343		ostr << '\'';
1344		break;
1345
1346	case LLSD::TypeDate:
1347		ostr << "d\"" << data.asDate() << "\"";
1348		break;
1349
1350	case LLSD::TypeURI:
1351		ostr << "l\"";
1352		serialize_string(data.asString(), ostr);
1353		ostr << "\"";
1354		break;
1355
1356	case LLSD::TypeBinary:
1357	{
1358		// *FIX: memory inefficient.
1359		std::vector<U8> buffer = data.asBinary();
1360		ostr << "b(" << buffer.size() << ")\"";
1361		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
1362		ostr << "\"";
1363		break;
1364	}
1365
1366	default:
1367		// *NOTE: This should never happen.
1368		ostr << "!";
1369		break;
1370	}
1371	return format_count;
1372}
1373
1374
1375/**
1376 * LLSDBinaryFormatter
1377 */
1378LLSDBinaryFormatter::LLSDBinaryFormatter()
1379{
1380}
1381
1382// virtual
1383LLSDBinaryFormatter::~LLSDBinaryFormatter()
1384{ }
1385
1386// virtual
1387S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
1388{
1389	S32 format_count = 1;
1390	switch(data.type())
1391	{
1392	case LLSD::TypeMap:
1393	{
1394		ostr.put('{');
1395		U32 size_nbo = htonl(data.size());
1396		ostr.write((const char*)(&size_nbo), sizeof(U32));
1397		LLSD::map_const_iterator iter = data.beginMap();
1398		LLSD::map_const_iterator end = data.endMap();
1399		for(; iter != end; ++iter)
1400		{
1401			ostr.put('k');
1402			formatString((*iter).first, ostr);
1403			format_count += format((*iter).second, ostr);
1404		}
1405		ostr.put('}');
1406		break;
1407	}
1408
1409	case LLSD::TypeArray:
1410	{
1411		ostr.put('[');
1412		U32 size_nbo = htonl(data.size());
1413		ostr.write((const char*)(&size_nbo), sizeof(U32));
1414		LLSD::array_const_iterator iter = data.beginArray();
1415		LLSD::array_const_iterator end = data.endArray();
1416		for(; iter != end; ++iter)
1417		{
1418			format_count += format(*iter, ostr);
1419		}
1420		ostr.put(']');
1421		break;
1422	}
1423
1424	case LLSD::TypeUndefined:
1425		ostr.put('!');
1426		break;
1427
1428	case LLSD::TypeBoolean:
1429		if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
1430		else ostr.put(BINARY_FALSE_SERIAL);
1431		break;
1432
1433	case LLSD::TypeInteger:
1434	{
1435		ostr.put('i');
1436		U32 value_nbo = htonl(data.asInteger());
1437		ostr.write((const char*)(&value_nbo), sizeof(U32));
1438		break;
1439	}
1440
1441	case LLSD::TypeReal:
1442	{
1443		ostr.put('r');
1444		F64 value_nbo = ll_htond(data.asReal());
1445		ostr.write((const char*)(&value_nbo), sizeof(F64));
1446		break;
1447	}
1448
1449	case LLSD::TypeUUID:
1450		ostr.put('u');
1451		ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES);
1452		break;
1453
1454	case LLSD::TypeString:
1455		ostr.put('s');
1456		formatString(data.asString(), ostr);
1457		break;
1458
1459	case LLSD::TypeDate:
1460	{
1461		ostr.put('d');
1462		F64 value = data.asReal();
1463		ostr.write((const char*)(&value), sizeof(F64));
1464		break;
1465	}
1466
1467	case LLSD::TypeURI:
1468		ostr.put('l');
1469		formatString(data.asString(), ostr);
1470		break;
1471
1472	case LLSD::TypeBinary:
1473	{
1474		// *FIX: memory inefficient.
1475		ostr.put('b');
1476		std::vector<U8> buffer = data.asBinary();
1477		U32 size_nbo = htonl(buffer.size());
1478		ostr.write((const char*)(&size_nbo), sizeof(U32));
1479		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
1480		break;
1481	}
1482
1483	default:
1484		// *NOTE: This should never happen.
1485		ostr.put('!');
1486		break;
1487	}
1488	return format_count;
1489}
1490
1491void LLSDBinaryFormatter::formatString(
1492	const std::string& string,
1493	std::ostream& ostr) const
1494{
1495	U32 size_nbo = htonl(string.size());
1496	ostr.write((const char*)(&size_nbo), sizeof(U32));
1497	ostr.write(string.c_str(), string.size());
1498}
1499
1500/**
1501 * local functions
1502 */
1503int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
1504{
1505	int c = istr.get();
1506	if(istr.fail())
1507	{
1508		// No data in stream, bail out but mention the character we
1509		// grabbed.
1510		return LLSDParser::PARSE_FAILURE;
1511	}
1512
1513	int rv = LLSDParser::PARSE_FAILURE;
1514	switch(c)
1515	{
1516	case '\'':
1517	case '"':
1518		rv = deserialize_string_delim(istr, value, c);
1519		break;
1520	case 's':
1521		// technically, less than max_bytes, but this is just meant to
1522		// catch egregious protocol errors. parse errors will be
1523		// caught in the case of incorrect counts.
1524		rv = deserialize_string_raw(istr, value, max_bytes);
1525		break;
1526	default:
1527		break;
1528	}
1529	if(LLSDParser::PARSE_FAILURE == rv) return rv;
1530	return rv + 1; // account for the character grabbed at the top.
1531}
1532
1533int deserialize_string_delim(
1534	std::istream& istr,
1535	std::string& value,
1536	char delim)
1537{
1538	std::ostringstream write_buffer;
1539	bool found_escape = false;
1540	bool found_hex = false;
1541	bool found_digit = false;
1542	U8 byte = 0;
1543	int count = 0;
1544
1545	while (true)
1546	{
1547		int next_byte = istr.get();
1548		++count;
1549
1550		if(istr.fail())
1551		{
1552			// If our stream is empty, break out
1553			value = write_buffer.str();
1554			return LLSDParser::PARSE_FAILURE;
1555		}
1556
1557		char next_char = (char)next_byte; // Now that we know it's not EOF
1558		
1559		if(found_escape)
1560		{
1561			// next character(s) is a special sequence.
1562			if(found_hex)
1563			{
1564				if(found_digit)
1565				{
1566					found_digit = false;
1567					found_hex = false;
1568					found_escape = false;
1569					byte = byte << 4;
1570					byte |= hex_as_nybble(next_char);
1571					write_buffer << byte;
1572					byte = 0;
1573				}
1574				else
1575				{
1576					// next character is the first nybble of
1577					//
1578					found_digit = true;
1579					byte = hex_as_nybble(next_char);
1580				}
1581			}
1582			else if(next_char == 'x')
1583			{
1584				found_hex = true;
1585			}
1586			else
1587			{
1588				switch(next_char)
1589				{
1590				case 'a':
1591					write_buffer << '\a';
1592					break;
1593				case 'b':
1594					write_buffer << '\b';
1595					break;
1596				case 'f':
1597					write_buffer << '\f';
1598					break;
1599				case 'n':
1600					write_buffer << '\n';
1601					break;
1602				case 'r':
1603					write_buffer << '\r';
1604					break;
1605				case 't':
1606					write_buffer << '\t';
1607					break;
1608				case 'v':
1609					write_buffer << '\v';
1610					break;
1611				default:
1612					write_buffer << next_char;
1613					break;
1614				}
1615				found_escape = false;
1616			}
1617		}
1618		else if(next_char == '\\')
1619		{
1620			found_escape = true;
1621		}
1622		else if(next_char == delim)
1623		{
1624			break;
1625		}
1626		else
1627		{
1628			write_buffer << next_char;
1629		}
1630	}
1631
1632	value = write_buffer.str();
1633	return count;
1634}
1635
1636int deserialize_string_raw(
1637	std::istream& istr,
1638	std::string& value,
1639	S32 max_bytes)
1640{
1641	int count = 0;
1642	const S32 BUF_LEN = 20;
1643	char buf[BUF_LEN];		/* Flawfinder: ignore */
1644	istr.get(buf, BUF_LEN - 1, ')');
1645	count += istr.gcount();
1646	int c = istr.get();
1647	c = istr.get();
1648	count += 2;
1649	if(((c == '"') || (c == '\'')) && (buf[0] == '('))
1650	{
1651		// We probably have a valid raw string. determine
1652		// the size, and read it.
1653		// *FIX: This is memory inefficient.
1654		S32 len = strtol(buf + 1, NULL, 0);
1655		if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
1656		std::vector<char> buf;
1657		if(len)
1658		{
1659			buf.resize(len);
1660			count += fullread(istr, (char *)&buf[0], len);
1661			value.assign(buf.begin(), buf.end());
1662		}
1663		c = istr.get();
1664		++count;
1665		if(!((c == '"') || (c == '\'')))
1666		{
1667			return LLSDParser::PARSE_FAILURE;
1668		}
1669	}
1670	else
1671	{
1672		return LLSDParser::PARSE_FAILURE;
1673	}
1674	return count;
1675}
1676
1677static const char* NOTATION_STRING_CHARACTERS[256] =
1678{
1679	"\\x00",	// 0
1680	"\\x01",	// 1
1681	"\\x02",	// 2
1682	"\\x03",	// 3
1683	"\\x04",	// 4
1684	"\\x05",	// 5
1685	"\\x06",	// 6
1686	"\\a",		// 7
1687	"\\b",		// 8
1688	"\\t",		// 9
1689	"\\n",		// 10
1690	"\\v",		// 11
1691	"\\f",		// 12
1692	"\\r",		// 13
1693	"\\x0e",	// 14
1694	"\\x0f",	// 15
1695	"\\x10",	// 16
1696	"\\x11",	// 17
1697	"\\x12",	// 18
1698	"\\x13",	// 19
1699	"\\x14",	// 20
1700	"\\x15",	// 21
1701	"\\x16",	// 22
1702	"\\x17",	// 23
1703	"\\x18",	// 24
1704	"\\x19",	// 25
1705	"\\x1a",	// 26
1706	"\\x1b",	// 27
1707	"\\x1c",	// 28
1708	"\\x1d",	// 29
1709	"\\x1e",	// 30
1710	"\\x1f",	// 31
1711	" ",		// 32
1712	"!",		// 33
1713	"\"",		// 34
1714	"#",		// 35
1715	"$",		// 36
1716	"%",		// 37
1717	"&",		// 38
1718	"\\'",		// 39
1719	"(",		// 40
1720	")",		// 41
1721	"*",		// 42
1722	"+",		// 43
1723	",",		// 44
1724	"-",		// 45
1725	".",		// 46
1726	"/",		// 47
1727	"0",		// 48
1728	"1",		// 49
1729	"2",		// 50
1730	"3",		// 51
1731	"4",		// 52
1732	"5",		// 53
1733	"6",		// 54
1734	"7",		// 55
1735	"8",		// 56
1736	"9",		// 57
1737	":",		// 58
1738	";",		// 59
1739	"<",		// 60
1740	"=",		// 61
1741	">",		// 62
1742	"?",		// 63
1743	"@",		// 64
1744	"A",		// 65
1745	"B",		// 66
1746	"C",		// 67
1747	"D",		// 68
1748	"E",		// 69
1749	"F",		// 70
1750	"G",		// 71
1751	"H",		// 72
1752	"I",		// 73
1753	"J",		// 74
1754	"K",		// 75
1755	"L",		// 76
1756	"M",		// 77
1757	"N",		// 78
1758	"O",		// 79
1759	"P",		// 80
1760	"Q",		// 81
1761	"R",		// 82
1762	"S",		// 83
1763	"T",		// 84
1764	"U",		// 85
1765	"V",		// 86
1766	"W",		// 87
1767	"X",		// 88
1768	"Y",		// 89
1769	"Z",		// 90
1770	"[",		// 91
1771	"\\\\",		// 92
1772	"]",		// 93
1773	"^",		// 94
1774	"_",		// 95
1775	"`",		// 96
1776	"a",		// 97
1777	"b",		// 98
1778	"c",		// 99
1779	"d",		// 100
1780	"e",		// 101
1781	"f",		// 102
1782	"g",		// 103
1783	"h",		// 104
1784	"i",		// 105
1785	"j",		// 106
1786	"k",		// 107
1787	"l",		// 108
1788	"m",		// 109
1789	"n",		// 110
1790	"o",		// 111
1791	"p",		// 112
1792	"q",		// 113
1793	"r",		// 114
1794	"s",		// 115
1795	"t",		// 116
1796	"u",		// 117
1797	"v",		// 118
1798	"w",		// 119
1799	"x",		// 120
1800	"y",		// 121
1801	"z",		// 122
1802	"{",		// 123
1803	"|",		// 124
1804	"}",		// 125
1805	"~",		// 126
1806	"\\x7f",	// 127
1807	"\\x80",	// 128
1808	"\\x81",	// 129
1809	"\\x82",	// 130
1810	"\\x83",	// 131
1811	"\\x84",	// 132
1812	"\\x85",	// 133
1813	"\\x86",	// 134
1814	"\\x87",	// 135
1815	"\\x88",	// 136
1816	"\\x89",	// 137
1817	"\\x8a",	// 138
1818	"\\x8b",	// 139
1819	"\\x8c",	// 140
1820	"\\x8d",	// 141
1821	"\\x8e",	// 142
1822	"\\x8f",	// 143
1823	"\\x90",	// 144
1824	"\\x91",	// 145
1825	"\\x92",	// 146
1826	"\\x93",	// 147
1827	"\\x94",	// 148
1828	"\\x95",	// 149
1829	"\\x96",	// 150
1830	"\\x97",	// 151
1831	"\\x98",	// 152
1832	"\\x99",	// 153
1833	"\\x9a",	// 154
1834	"\\x9b",	// 155
1835	"\\x9c",	// 156
1836	"\\x9d",	// 157
1837	"\\x9e",	// 158
1838	"\\x9f",	// 159
1839	"\\xa0",	// 160
1840	"\\xa1",	// 161
1841	"\\xa2",	// 162
1842	"\\xa3",	// 163
1843	"\\xa4",	// 164
1844	"\\xa5",	// 165
1845	"\\xa6",	// 166
1846	"\\xa7",	// 167
1847	"\\xa8",	// 168
1848	"\\xa9",	// 169
1849	"\\xaa",	// 170
1850	"\\xab",	// 171
1851	"\\xac",	// 172
1852	"\\xad",	// 173
1853	"\\xae",	// 174
1854	"\\xaf",	// 175
1855	"\\xb0",	// 176
1856	"\\xb1",	// 177
1857	"\\xb2",	// 178
1858	"\\xb3",	// 179
1859	"\\xb4",	// 180
1860	"\\xb5",	// 181
1861	"\\xb6",	// 182
1862	"\\xb7",	// 183
1863	"\\xb8",	// 184
1864	"\\xb9",	// 185
1865	"\\xba",	// 186
1866	"\\xbb",	// 187
1867	"\\xbc",	// 188
1868	"\\xbd",	// 189
1869	"\\xbe",	// 190
1870	"\\xbf",	// 191
1871	"\\xc0",	// 192
1872	"\\xc1",	// 193
1873	"\\xc2",	// 194
1874	"\\xc3",	// 195
1875	"\\xc4",	// 196
1876	"\\xc5",	// 197
1877	"\\xc6",	// 198
1878	"\\xc7",	// 199
1879	"\\xc8",	// 200
1880	"\\xc9",	// 201
1881	"\\xca",	// 202
1882	"\\xcb",	// 203
1883	"\\xcc",	// 204
1884	"\\xcd",	// 205
1885	"\\xce",	// 206
1886	"\\xcf",	// 207
1887	"\\xd0",	// 208
1888	"\\xd1",	// 209
1889	"\\xd2",	// 210
1890	"\\xd3",	// 211
1891	"\\xd4",	// 212
1892	"\\xd5",	// 213
1893	"\\xd6",	// 214
1894	"\\xd7",	// 215
1895	"\\xd8",	// 216
1896	"\\xd9",	// 217
1897	"\\xda",	// 218
1898	"\\xdb",	// 219
1899	"\\xdc",	// 220
1900	"\\xdd",	// 221
1901	"\\xde",	// 222
1902	"\\xdf",	// 223
1903	"\\xe0",	// 224
1904	"\\xe1",	// 225
1905	"\\xe2",	// 226
1906	"\\xe3",	// 227
1907	"\\xe4",	// 228
1908	"\\xe5",	// 229
1909	"\\xe6",	// 230
1910	"\\xe7",	// 231
1911	"\\xe8",	// 232
1912	"\\xe9",	// 233
1913	"\\xea",	// 234
1914	"\\xeb",	// 235
1915	"\\xec",	// 236
1916	"\\xed",	// 237
1917	"\\xee",	// 238
1918	"\\xef",	// 239
1919	"\\xf0",	// 240
1920	"\\xf1",	// 241
1921	"\\xf2",	// 242
1922	"\\xf3",	// 243
1923	"\\xf4",	// 244
1924	"\\xf5",	// 245
1925	"\\xf6",	// 246
1926	"\\xf7",	// 247
1927	"\\xf8",	// 248
1928	"\\xf9",	// 249
1929	"\\xfa",	// 250
1930	"\\xfb",	// 251
1931	"\\xfc",	// 252
1932	"\\xfd",	// 253
1933	"\\xfe",	// 254
1934	"\\xff"		// 255
1935};
1936
1937void serialize_string(const std::string& value, std::ostream& str)
1938{
1939	std::string::const_iterator it = value.begin();
1940	std::string::const_iterator end = value.end();
1941	U8 c;
1942	for(; it != end; ++it)
1943	{
1944		c = (U8)(*it);
1945		str << NOTATION_STRING_CHARACTERS[c];
1946	}
1947}
1948
1949int deserialize_boolean(
1950	std::istream& istr,
1951	LLSD& data,
1952	const std::string& compare,
1953	bool value)
1954{
1955	//
1956	// this method is a little goofy, because it gets the stream at
1957	// the point where the t or f has already been
1958	// consumed. Basically, parse for a patch to the string passed in
1959	// starting at index 1. If it's a match:
1960	//  * assign data to value
1961	//  * return the number of bytes read
1962	// otherwise:
1963	//  * set data to LLSD::null
1964	//  * return LLSDParser::PARSE_FAILURE (-1)
1965	//
1966	int bytes_read = 0;
1967	std::string::size_type ii = 0;
1968	char c = istr.peek();
1969	while((++ii < compare.size())
1970		  && (tolower(c) == (int)compare[ii])
1971		  && istr.good())
1972	{
1973		istr.ignore();
1974		++bytes_read;
1975		c = istr.peek();
1976	}
1977	if(compare.size() != ii)
1978	{
1979		data.clear();
1980		return LLSDParser::PARSE_FAILURE;
1981	}
1982	data = value;
1983	return bytes_read;
1984}
1985
1986std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
1987{
1988	s << LLSDNotationStreamer(llsd);
1989	return s;
1990}
1991
1992
1993//dirty little zippers -- yell at davep if these are horrid
1994
1995//return a string containing gzipped bytes of binary serialized LLSD
1996// VERY inefficient -- creates several copies of LLSD block in memory
1997std::string zip_llsd(LLSD& data)
1998{ 
1999	std::stringstream llsd_strm;
2000
2001	LLSDSerialize::toBinary(data, llsd_strm);
2002
2003	const U32 CHUNK = 65536;
2004
2005	z_stream strm;
2006	strm.zalloc = Z_NULL;
2007	strm.zfree = Z_NULL;
2008	strm.opaque = Z_NULL;
2009
2010	S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
2011	if (ret != Z_OK)
2012	{
2013		llwarns << "Failed to compress LLSD block." << llendl;
2014		return std::string();
2015	}
2016
2017	std::string source = llsd_strm.str();
2018
2019	U8 out[CHUNK];
2020
2021	strm.avail_in = source.size();
2022	strm.next_in = (U8*) source.data();
2023	U8* output = NULL;
2024
2025	U32 cur_size = 0;
2026
2027	U32 have = 0;
2028
2029	do
2030	{
2031		strm.avail_out = CHUNK;
2032		strm.next_out = out;
2033
2034		ret = deflate(&strm, Z_FINISH);
2035		if (ret == Z_OK || ret == Z_STREAM_END)
2036		{ //copy result into output
2037			if (strm.avail_out >= CHUNK)
2038			{
2039				free(output);
2040				llwarns << "Failed to compress LLSD block." << llendl;
2041				return std::string();
2042			}
2043
2044			have = CHUNK-strm.avail_out;
2045			output = (U8*) realloc(output, cur_size+have);
2046			memcpy(output+cur_size, out, have);
2047			cur_size += have;
2048		}
2049		else 
2050		{
2051			free(output);
2052			llwarns << "Failed to compress LLSD block." << llendl;
2053			return std::string();
2054		}
2055	}
2056	while (ret == Z_OK);
2057
2058	std::string::size_type size = cur_size;
2059
2060	std::string result((char*) output, size);
2061	deflateEnd(&strm);
2062	free(output);
2063
2064#if 0 //verify results work with unzip_llsd
2065	std::istringstream test(result);
2066	LLSD test_sd;
2067	if (!unzip_llsd(test_sd, test, result.size()))
2068	{
2069		llerrs << "Invalid compression result!" << llendl;
2070	}
2071#endif
2072
2073	return result;
2074}
2075
2076//decompress a block of LLSD from provided istream
2077// not very efficient -- creats a copy of decompressed LLSD block in memory
2078// and deserializes from that copy using LLSDSerialize
2079bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
2080{
2081	U8* result = NULL;
2082	U32 cur_size = 0;
2083	z_stream strm;
2084		
2085	const U32 CHUNK = 65536;
2086
2087	U8 *in = new U8[size];
2088	is.read((char*) in, size); 
2089
2090	U8 out[CHUNK];
2091		
2092	strm.zalloc = Z_NULL;
2093	strm.zfree = Z_NULL;
2094	strm.opaque = Z_NULL;
2095	strm.avail_in = size;
2096	strm.next_in = in;
2097
2098	S32 ret = inflateInit(&strm);
2099
2100	do
2101	{
2102		strm.avail_out = CHUNK;
2103		strm.next_out = out;
2104		ret = inflate(&strm, Z_NO_FLUSH);
2105		if (ret == Z_STREAM_ERROR)
2106		{
2107			inflateEnd(&strm);
2108			free(result);
2109			delete [] in;
2110			return false;
2111		}
2112		
2113		switch (ret)
2114		{
2115		case Z_NEED_DICT:
2116			ret = Z_DATA_ERROR;
2117		case Z_DATA_ERROR:
2118		case Z_MEM_ERROR:
2119			inflateEnd(&strm);
2120			free(result);
2121			delete [] in;
2122			return false;
2123			break;
2124		}
2125
2126		U32 have = CHUNK-strm.avail_out;
2127
2128		result = (U8*) realloc(result, cur_size + have);
2129		memcpy(result+cur_size, out, have);
2130		cur_size += have;
2131
2132	} while (ret == Z_OK);
2133
2134	inflateEnd(&strm);
2135	delete [] in;
2136
2137	if (ret != Z_STREAM_END)
2138	{
2139		free(result);
2140		return false;
2141	}
2142
2143	//result now points to the decompressed LLSD block
2144	{
2145		std::string res_str((char*) result, cur_size);
2146
2147		std::string deprecated_header("<? LLSD/Binary ?>");
2148
2149		if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
2150		{
2151			res_str = res_str.substr(deprecated_header.size()+1, cur_size);
2152		}
2153		cur_size = res_str.size();
2154
2155		std::istringstream istr(res_str);
2156		
2157		if (!LLSDSerialize::fromBinary(data, istr, cur_size))
2158		{
2159			llwarns << "Failed to unzip LLSD block" << llendl;
2160			free(result);
2161			return false;
2162		}
2163	}
2164
2165	free(result);
2166	return true;
2167}
2168
2169
2170