From 8bd6a0b3217ea5614d2a29195e528aa8314f6342 Mon Sep 17 00:00:00 2001
From: Josh Bell <josh@lindenlab.com>
Date: Thu, 7 Feb 2008 17:15:18 +0000
Subject: svn merge -r 79445:79449
 svn+ssh://svn.lindenlab.com/svn/linden/qa/maintenance-5-merge-79386

QAR-242 merge of maintenance-5 (QAR-203)
* DEV-6548 Copy To Inventory fail to execute without any output feedback when Notecard has changes but not saved
* DEV-7600 Deleting someone else's object in god mode crashes sim
* DEV-5329 LLSD parsers should determine and set maximum parse sizes
* DEV-7473 Resolve instant message crash report
* DEV-2904 Presence Issues not (apparently) caused by scripted attachments
* DEV-7083 Investigate Null Folder IDs Bug that caused 470K inventory items with Null Folder IDS on the Grid
* DEV-2865 Textures/Snapshots in a notecard are opened again when you click copy to inventory.
* DEV-6612 VWR-3290: Linux scons build script doesn't work with distcc
* DEV-8002 c++ llsd notation parser accepts malformed data
* DEV-8001 c++ xml parse returns wrong number of elements parsed
* DEV-8089 Double delete in statc structured data parse functions
* DEV-5326 Any viewer can request presence information for any agent
* DEV-2378 python service builder does not sort query string
* DEV-7872 Block teleport off teen grid sub-estates like Schome Park / Open University
* DEV-4465 Add a "logfile" command line option to the sim to create log files
---
 doc/contributions.txt                 |   1 +
 indra/lib/python/indra/ipc/russ.py    |  10 +-
 indra/llcommon/llapp.cpp              |  11 +-
 indra/llcommon/llapr.cpp              |   8 +-
 indra/llcommon/llfile.cpp             |  27 ++
 indra/llcommon/llfile.h               |   9 +
 indra/llcommon/llsdserialize.cpp      | 761 ++++++++++++++++++++++++----------
 indra/llcommon/llsdserialize.h        | 232 ++++++++---
 indra/llcommon/llsdserialize_xml.cpp  |  23 +-
 indra/llcommon/llstreamtools.cpp      |  27 +-
 indra/llcommon/llstreamtools.h        |   7 +-
 indra/llcrashlogger/llcrashlogger.cpp |   6 +-
 indra/llmessage/llbuffer.h            |  12 +
 indra/llmessage/llfiltersd2xmlrpc.cpp |   4 +-
 indra/llmessage/llhttpclient.cpp      |  12 +-
 indra/llmessage/llhttpclient.h        |  17 +-
 indra/llmessage/lliohttpserver.cpp    |   6 +-
 indra/llmessage/llsdrpcclient.cpp     |   2 +-
 indra/llmessage/llsdrpcserver.cpp     |   5 +-
 indra/llmessage/llservicebuilder.cpp  |  58 +--
 indra/newview/llappviewer.cpp         |  27 --
 indra/newview/llfloatersnapshot.cpp   |   2 +-
 indra/newview/llpreview.cpp           |   1 +
 indra/newview/llstartup.cpp           |  18 +-
 indra/newview/llviewermessage.cpp     |   4 +-
 indra/newview/llviewertexteditor.cpp  |  58 ++-
 indra/newview/llviewertexteditor.h    |   5 +-
 indra/test/io.cpp                     |  30 +-
 28 files changed, 982 insertions(+), 401 deletions(-)

diff --git a/doc/contributions.txt b/doc/contributions.txt
index 4dea768d28..9b2719b3b7 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -33,6 +33,7 @@ Alissa Sabre
 	VWR-1410
 	VWR-2116
 	VWR-2826
+	VWR-3290
 	VWR-4010
 Angus Boyd
 	VWR-592
diff --git a/indra/lib/python/indra/ipc/russ.py b/indra/lib/python/indra/ipc/russ.py
index 1ef5562a52..bd50569d3a 100644
--- a/indra/lib/python/indra/ipc/russ.py
+++ b/indra/lib/python/indra/ipc/russ.py
@@ -136,7 +136,15 @@ def _build_query_string(query_dict):
     @returns Returns an urlencoded query string including leading '?'.
     """
     if query_dict:
-        return '?' + urllib.urlencode(query_dict)
+        keys = query_dict.keys()
+        keys.sort()
+        def stringize(value):
+            if type(value) in (str,unicode):
+                return value
+            else:
+                return str(value)
+        query_list = [urllib.quote(str(key)) + '=' + urllib.quote(stringize(query_dict[key])) for key in keys]
+        return '?' + '&'.join(query_list)
     else:
         return ''
 
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 2347ac9cd9..6591bbc070 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -166,7 +166,16 @@ bool LLApp::parseCommandOptions(int argc, char** argv)
 			// we found another option after this one or we have
 			// reached the end. simply record that this option was
 			// found and continue.
-			commands[name] = true;
+			int flag = name.compare("logfile");
+			if (0 == flag)
+			{
+				commands[name] = "log";
+			}
+			else
+			{
+				commands[name] = true;
+			}
+			
 			continue;
 		}
 		++ii;
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index be3a52da0d..861cf814e2 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -292,7 +292,7 @@ bool ll_apr_file_remove(const LLString& filename, apr_pool_t* pool)
 	s = apr_file_remove(filename.c_str(), pool);
 	if (s != APR_SUCCESS)
 	{
-		llwarns << "ll_apr_file_remove failed on file: " << filename << llendl;
+		lldebugs << "ll_apr_file_remove failed on file: " << filename << llendl;
 		return false;
 	}
 	return true;
@@ -305,7 +305,7 @@ bool ll_apr_file_rename(const LLString& filename, const LLString& newname, apr_p
 	s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
 	if (s != APR_SUCCESS)
 	{
-		llwarns << "ll_apr_file_rename failed on file: " << filename << llendl;
+		lldebugs << "ll_apr_file_rename failed on file: " << filename << llendl;
 		return false;
 	}
 	return true;
@@ -361,7 +361,7 @@ bool ll_apr_dir_make(const LLString& dirname, apr_pool_t* pool)
 	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
 	if (s != APR_SUCCESS)
 	{
-		llwarns << "ll_apr_file_remove failed on file: " << dirname << llendl;
+		lldebugs << "ll_apr_dir_make failed on file: " << dirname << llendl;
 		return false;
 	}
 	return true;
@@ -374,7 +374,7 @@ bool ll_apr_dir_remove(const LLString& dirname, apr_pool_t* pool)
 	s = apr_file_remove(dirname.c_str(), pool);
 	if (s != APR_SUCCESS)
 	{
-		llwarns << "ll_apr_file_remove failed on file: " << dirname << llendl;
+		lldebugs << "ll_apr_dir_remove failed on file: " << dirname << llendl;
 		return false;
 	}
 	return true;
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index eb76b20d23..241b13f84f 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -291,3 +291,30 @@ llofstream::~llofstream()
 
 #endif // #if USE_LLFILESTREAMS
 
+/************** helper functions ********************************/
+
+std::streamsize llifstream_size(llifstream& ifstr)
+{
+	if(!ifstr.is_open()) return 0;
+	std::streampos pos_old = ifstr.tellg();
+	ifstr.seekg(0, ios_base::beg);
+	std::streampos pos_beg = ifstr.tellg();
+	ifstr.seekg(0, ios_base::end);
+	std::streampos pos_end = ifstr.tellg();
+	ifstr.seekg(pos_old, ios_base::beg);
+	return pos_end - pos_beg;
+}
+
+std::streamsize llofstream_size(llofstream& ofstr)
+{
+	if(!ofstr.is_open()) return 0;
+	std::streampos pos_old = ofstr.tellp();
+	ofstr.seekp(0, ios_base::beg);
+	std::streampos pos_beg = ofstr.tellp();
+	ofstr.seekp(0, ios_base::end);
+	std::streampos pos_end = ofstr.tellp();
+	ofstr.seekp(pos_old, ios_base::beg);
+	return pos_end - pos_beg;
+}
+
+
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index f51cea9219..7a1542a6fa 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -168,5 +168,14 @@ private:
 
 #endif
 
+/**
+ * @breif filesize helpers.
+ *
+ * The file size helpers are not considered particularly efficient,
+ * and should only be used for config files and the like -- not in a
+ * loop.
+ */
+std::streamsize llifstream_size(llifstream& fstr);
+std::streamsize llofstream_size(llofstream& fstr);
 
 #endif // not LL_LLFILE_H
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 5ab94715c5..02152cfe79 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -45,26 +45,18 @@
 
 #include "lldate.h"
 #include "llsd.h"
+#include "llstring.h"
 #include "lluri.h"
 
 // File constants
 static const int MAX_HDR_LEN = 20;
 static const char LEGACY_NON_HEADER[] = "<llsd>";
+const std::string LLSD_BINARY_HEADER("LLSD/Binary");
+const std::string LLSD_XML_HEADER("LLSD/XML");
 
-//static
-const char* LLSDSerialize::LLSDBinaryHeader = "LLSD/Binary";
-
-//static
-const char* LLSDSerialize::LLSDXMLHeader =    "LLSD/XML";
-
-// virtual
-LLSDParser::~LLSDParser()
-{ }
-
-// virtual
-LLSDNotationParser::~LLSDNotationParser()
-{ }
-
+/**
+ * LLSDSerialize
+ */
 
 // static
 void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
@@ -74,12 +66,12 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
 	switch (type)
 	{
 	case LLSD_BINARY:
-		str << "<? " << LLSDBinaryHeader << " ?>\n";
+		str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
 		f = new LLSDBinaryFormatter;
 		break;
 
 	case LLSD_XML:
-		str << "<? " << LLSDXMLHeader << " ?>\n";
+		str << "<? " << LLSD_XML_HEADER << " ?>\n";
 		f = new LLSDXMLFormatter;
 		break;
 
@@ -94,7 +86,7 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
 }
 
 // static
-bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
+bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
 {
 	LLPointer<LLSDParser> p = NULL;
 	char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
@@ -102,8 +94,8 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
 	int inbuf = 0;
 	bool legacy_no_header = false;
 	bool fail_if_not_legacy = false;
-	std::string header = "";
-	
+	std::string header;
+
 	/*
 	 * Get the first line before anything.
 	 */
@@ -155,15 +147,15 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
 	 */
 	if (legacy_no_header)
 	{
-		LLSDXMLParser *x = new LLSDXMLParser;
+		LLSDXMLParser* x = new LLSDXMLParser;
 		x->parsePart(hdr_buf, inbuf);
 		p = x;
 	}
-	else if (header == LLSDBinaryHeader)
+	else if (header == LLSD_BINARY_HEADER)
 	{
 		p = new LLSDBinaryParser;
 	}
-	else if (header == LLSDXMLHeader)
+	else if (header == LLSD_XML_HEADER)
 	{
 		p = new LLSDXMLParser;
 	}
@@ -174,7 +166,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str)
 
 	if (p.notNull())
 	{
-		p->parse(str, sd);
+		p->parse(str, sd, max_bytes);
 		return true;
 	}
 
@@ -230,11 +222,69 @@ F64 ll_ntohd(F64 netdouble)
 /**
  * Local functions.
  */
-bool deserialize_string(std::istream& str, std::string& value);
-bool deserialize_string_delim(std::istream& str, std::string& value, char d);
-bool deserialize_string_raw(std::istream& str, std::string& value);
+/**
+ * @brief Figure out what kind of string it is (raw or delimited) and handoff.
+ *
+ * @param istr The stream to read from.
+ * @param value [out] The string which was found.
+ * @param max_bytes The maximum possible length of the string.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
+
+/**
+ * @brief Parse a delimited string. 
+ *
+ * @param istr The stream to read from, with the delimiter already popped.
+ * @param value [out] The string which was found.
+ * @param d The delimiter to use.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_string_delim(std::istream& istr, std::string& value, char d);
+
+/**
+ * @brief Read a raw string off the stream.
+ *
+ * @param istr The stream to read from, with the (len) parameter
+ * leading the stream.
+ * @param value [out] The string which was found.
+ * @param d The delimiter to use.
+ * @param max_bytes The maximum possible length of the string.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_string_raw(
+	std::istream& istr,
+	std::string& value,
+	S32 max_bytes);
+
+/**
+ * @brief helper method for dealing with the different notation boolean format.
+ *
+ * @param istr The stream to read from with the leading character stripped.
+ * @param data [out] the result of the parse.
+ * @param compare The string to compare the boolean against
+ * @param vale The value to assign to data if the parse succeeds.
+ * @return Returns number of bytes read off of the stream. Returns
+ * PARSE_FAILURE (-1) on failure.
+ */
+int deserialize_boolean(
+	std::istream& istr,
+	LLSD& data,
+	const std::string& compare,
+	bool value);
+
+/**
+ * @brief Do notation escaping of a string to an ostream.
+ *
+ * @param value The string to escape and serialize
+ * @param str The stream to serialize to.
+ */
 void serialize_string(const std::string& value, std::ostream& str);
 
+
 /**
  * Local constants.
  */
@@ -244,20 +294,96 @@ static const std::string NOTATION_FALSE_SERIAL("false");
 static const char BINARY_TRUE_SERIAL = '1';
 static const char BINARY_FALSE_SERIAL = '0';
 
-static const S32 NOTATION_PARSE_FAILURE = -1;
 
 /**
  * LLSDParser
  */
-LLSDParser::LLSDParser()
+LLSDParser::LLSDParser() : mCheckLimits(true), mMaxBytesLeft(0)
+{
+}
+
+// virtual
+LLSDParser::~LLSDParser()
+{ }
+
+S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
+{
+	mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
+	mMaxBytesLeft = max_bytes;
+	return doParse(istr, data);
+}
+
+
+int LLSDParser::get(std::istream& istr) const
+{
+	if(mCheckLimits) --mMaxBytesLeft;
+	return istr.get();
+}
+
+std::istream& LLSDParser::get(
+	std::istream& istr,
+	char* s,
+	std::streamsize n,
+	char delim) const
+{
+	istr.get(s, n, delim);
+	if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
+	return istr;
+}
+
+std::istream& LLSDParser::get(
+		std::istream& istr,
+		std::streambuf& sb,
+		char delim) const		
+{
+	istr.get(sb, delim);
+	if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
+	return istr;
+}
+
+std::istream& LLSDParser::ignore(std::istream& istr) const
 {
+	istr.ignore();
+	if(mCheckLimits) --mMaxBytesLeft;
+	return istr;
 }
 
+std::istream& LLSDParser::putback(std::istream& istr, char c) const
+{
+	istr.putback(c);
+	if(mCheckLimits) ++mMaxBytesLeft;
+	return istr;
+}
+
+std::istream& LLSDParser::read(
+	std::istream& istr,
+	char* s,
+	std::streamsize n) const
+{
+	istr.read(s, n);
+	if(mCheckLimits) mMaxBytesLeft -= istr.gcount();
+	return istr;
+}
+
+void LLSDParser::account(S32 bytes) const
+{
+	if(mCheckLimits) mMaxBytesLeft -= bytes;
+}
+
+
 /**
  * LLSDNotationParser
  */
+LLSDNotationParser::LLSDNotationParser()
+{
+}	
+
+// virtual
+LLSDNotationParser::~LLSDNotationParser()
+{ }
+
 // virtual
-S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
+S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 {
 	// map: { string:object, string:object }
 	// array: [ object, object, object ]
@@ -275,7 +401,7 @@ S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
 	while(isspace(c))
 	{
 		// pop the whitespace.
-		c = istr.get();
+		c = get(istr);
 		c = istr.peek();
 		continue;
 	}
@@ -287,107 +413,142 @@ S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
 	switch(c)
 	{
 	case '{':
-		parse_count += parseMap(istr, data);
-		if(istr.fail())
+	{
+		S32 child_count = parseMap(istr, data);
+		if((child_count == PARSE_FAILURE) || data.isUndefined())
 		{
-			llinfos << "STREAM FAILURE reading map." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
-		if(data.isUndefined())
+		else
 		{
-			parse_count = NOTATION_PARSE_FAILURE;
+			parse_count += child_count;
+		}
+		if(istr.fail())
+		{
+			llinfos << "STREAM FAILURE reading map." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
+	}
 
 	case '[':
-		parse_count += parseArray(istr, data);
-		if(istr.fail())
+	{
+		S32 child_count = parseArray(istr, data);
+		if((child_count == PARSE_FAILURE) || data.isUndefined())
 		{
-			llinfos << "STREAM FAILURE reading array." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
-		if(data.isUndefined())
+		else
 		{
-			parse_count = NOTATION_PARSE_FAILURE;
+			parse_count += child_count;
+		}
+		if(istr.fail())
+		{
+			llinfos << "STREAM FAILURE reading array." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
+	}
 
 	case '!':
-		c = istr.get();
+		c = get(istr);
 		data.clear();
 		break;
 
 	case '0':
-		c = istr.get();
+		c = get(istr);
 		data = false;
 		break;
 
 	case 'F':
 	case 'f':
-		do
+		ignore(istr);
+		c = istr.peek();
+		if(isalpha(c))
 		{
-			istr.ignore();
-			c = istr.peek();
-		} while (isalpha(c));
-		data = false;
+			int cnt = deserialize_boolean(
+				istr,
+				data,
+				NOTATION_FALSE_SERIAL,
+				false);
+			if(PARSE_FAILURE == cnt) parse_count = cnt;
+			else account(cnt);
+		}
+		else
+		{
+			data = false;
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading boolean." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 
 	case '1':
-		c = istr.get();
+		c = get(istr);
 		data = true;
 		break;
 
 	case 'T':
 	case 't':
-		do
+		ignore(istr);
+		c = istr.peek();
+		if(isalpha(c))
 		{
-			istr.ignore();
-			c = istr.peek();
-		} while (isalpha(c));
-		data = true;
+			int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
+			if(PARSE_FAILURE == cnt) parse_count = cnt;
+			else account(cnt);
+		}
+		else
+		{
+			data = true;
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading boolean." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 
 	case 'i':
 	{
-		c = istr.get();
+		c = get(istr);
 		S32 integer = 0;
 		istr >> integer;
 		data = integer;
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading integer." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
 
 	case 'r':
 	{
-		c = istr.get();
+		c = get(istr);
 		F64 real = 0.0;
 		istr >> real;
 		data = real;
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading real." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
 
 	case 'u':
 	{
-		c = istr.get();
+		c = get(istr);
 		LLUUID id;
 		istr >> id;
 		data = id;
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading uuid." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
@@ -395,126 +556,144 @@ S32 LLSDNotationParser::parse(std::istream& istr, LLSD& data) const
 	case '\"':
 	case '\'':
 	case 's':
-		parseString(istr, data);
-		if(istr.fail())
+		if(!parseString(istr, data))
 		{
-			llinfos << "STREAM FAILURE reading string." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
-		if(data.isUndefined())
+		if(istr.fail())
 		{
-			parse_count = NOTATION_PARSE_FAILURE;
+			llinfos << "STREAM FAILURE reading string." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 
 	case 'l':
 	{
-		c = istr.get(); // pop the 'l'
-		c = istr.get(); // pop the delimiter
+		c = get(istr); // pop the 'l'
+		c = get(istr); // pop the delimiter
 		std::string str;
-		deserialize_string_delim(istr, str, c);
-		data = LLURI(str);
+		int cnt = deserialize_string_delim(istr, str, c);
+		if(PARSE_FAILURE == cnt)
+		{
+			parse_count = PARSE_FAILURE;
+		}
+		else
+		{
+			data = LLURI(str);
+			account(cnt);
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading link." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
 
 	case 'd':
 	{
-		c = istr.get(); // pop the 'd'
-		c = istr.get(); // pop the delimiter
+		c = get(istr); // pop the 'd'
+		c = get(istr); // pop the delimiter
 		std::string str;
-		deserialize_string_delim(istr, str, c);
-		data = LLDate(str);
+		int cnt = deserialize_string_delim(istr, str, c);
+		if(PARSE_FAILURE == cnt)
+		{
+			parse_count = PARSE_FAILURE;
+		}
+		else
+		{
+			data = LLDate(str);
+			account(cnt);
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading date." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
 
 	case 'b':
-		parseBinary(istr, data);
-		if(istr.fail())
+		if(!parseBinary(istr, data))
 		{
-			llinfos << "STREAM FAILURE reading data." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
-		if(data.isUndefined())
+		if(istr.fail())
 		{
-			parse_count = NOTATION_PARSE_FAILURE;
+			llinfos << "STREAM FAILURE reading data." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 
 	default:
-		data.clear();
-		parse_count = NOTATION_PARSE_FAILURE;
+		parse_count = PARSE_FAILURE;
 		llinfos << "Unrecognized character while parsing: int(" << (int)c
-				<< ")" << llendl;
+			<< ")" << llendl;
 		break;
 	}
+	if(PARSE_FAILURE == parse_count)
+	{
+		data.clear();
+	}
 	return parse_count;
 }
 
-// static
-LLSD LLSDNotationParser::parse(std::istream& istr)
-{
-	LLSDNotationParser parser;
-	LLSD rv;
-	S32 count = parser.parse(istr, rv);
-	lldebugs << "LLSDNotationParser::parse parsed " << count << " objects."
-		 << llendl;
-	return rv;
-}
-
 S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
 {
 	// map: { string:object, string:object }
 	map = LLSD::emptyMap();
 	S32 parse_count = 0;
-	char c = istr.get();
+	char c = get(istr);
 	if(c == '{')
 	{
 		// eat commas, white
 		bool found_name = false;
 		std::string name;
-		c = istr.get();
+		c = get(istr);
 		while(c != '}' && istr.good())
 		{
 			if(!found_name)
 			{
 				if((c == '\"') || (c == '\'') || (c == 's'))
 				{
-					istr.putback(c);
+					putback(istr, c);
 					found_name = true;
-					deserialize_string(istr, name);
+					int count = deserialize_string(istr, name, mMaxBytesLeft);
+					if(PARSE_FAILURE == count) return PARSE_FAILURE;
+					account(count);
 				}
-				c = istr.get();
+				c = get(istr);
 			}
 			else
 			{
 				if(isspace(c) || (c == ':'))
 				{
-					c = istr.get();
+					c = get(istr);
 					continue;
 				}
-				istr.putback(c);
+				putback(istr, c);
 				LLSD child;
-				S32 count = parse(istr, child);
+				S32 count = doParse(istr, child);
 				if(count > 0)
 				{
+					// There must be a value for every key, thus
+					// child_count must be greater than 0.
 					parse_count += count;
 					map.insert(name, child);
 				}
 				else
 				{
-					map.clear();
-					return NOTATION_PARSE_FAILURE;
+					return PARSE_FAILURE;
 				}
 				found_name = false;
-				c = istr.get();
+				c = get(istr);
 			}
 		}
+		if(c != '}')
+		{
+			map.clear();
+			return PARSE_FAILURE;
+		}
 	}
 	return parse_count;
 }
@@ -524,52 +703,51 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
 	// array: [ object, object, object ]
 	array = LLSD::emptyArray();
 	S32 parse_count = 0;
-	char c = istr.get();
+	char c = get(istr);
 	if(c == '[')
 	{
 		// eat commas, white
-		c = istr.get();
+		c = get(istr);
 		while((c != ']') && istr.good())
 		{
 			LLSD child;
 			if(isspace(c) || (c == ','))
 			{
-				c = istr.get();
+				c = get(istr);
 				continue;
 			}
-			istr.putback(c);
-			S32 count = parse(istr, child);
-			if(count > 0)
+			putback(istr, c);
+			S32 count = doParse(istr, child);
+			if(PARSE_FAILURE == count)
 			{
-				parse_count += count;
-				array.append(child);
+				return PARSE_FAILURE;
 			}
 			else
 			{
-				array.clear();
-				return NOTATION_PARSE_FAILURE;
+				parse_count += count;
+				array.append(child);
 			}
-			c = istr.get();
+			c = get(istr);
+		}
+		if(c != ']')
+		{
+			return PARSE_FAILURE;
 		}
 	}
 	return parse_count;
 }
 
-void LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
+bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
 {
 	std::string value;
-	if(deserialize_string(istr, value))
-	{
-		data = value;
-	}
-	else
-	{
-		// failed to parse.
-		data.clear();
-	}
+	int count = deserialize_string(istr, value, mMaxBytesLeft);
+	if(PARSE_FAILURE == count) return false;
+	account(count);
+	data = value;
+	return true;
 }
 
-void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
+bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
 {
 	// binary: b##"ff3120ab1"
 	// or: b(len)"..."
@@ -582,40 +760,44 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
 
 	// need to read the base out.
 	char buf[BINARY_BUFFER_SIZE];		/* Flawfinder: ignore */
-	istr.get(buf, STREAM_GET_COUNT, '"');
-	char c = istr.get();
-	if((c == '"') && (0 == strncmp("b(", buf, 2)))
+	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.
-		// *FIX: Should we set a maximum size?
 		S32 len = strtol(buf + 2, NULL, 0);
+		if(len > mMaxBytesLeft) return false;
 		std::vector<U8> value;
 		if(len)
 		{
 			value.resize(len);
-			fullread(istr, (char *)&value[0], len);
+			account(fullread(istr, (char *)&value[0], len));
 		}
-		c = istr.get(); // strip off the trailing double-quote
+		c = get(istr); // strip off the trailing double-quote
 		data = value;
 	}
-	else if((c == '"') && (0 == strncmp("b64", buf, 3)))
+	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;
-		istr.get(*(coded_stream.rdbuf()), '\"');
-		c = istr.get();
+		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;
-		value.resize(len);
-		len = apr_base64_decode_binary(&value[0], encoded.c_str());
-		value.resize(len);
+		if(len)
+		{
+			value.resize(len);
+			len = apr_base64_decode_binary(&value[0], encoded.c_str());
+			value.resize(len);
+		}
 		data = value;
 	}
-	else if((c == '"') && (0 == strncmp("b16", buf, 3)))
+	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
@@ -626,14 +808,14 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
 		U8 byte_buffer[BINARY_BUFFER_SIZE];
 		U8* write;
 		std::vector<U8> value;
-		c = istr.get();
+		c = get(istr);
 		while(c != '"')
 		{
-			istr.putback(c);
+			putback(istr, c);
 			read = buf;
 			write = byte_buffer;
-			istr.get(buf, STREAM_GET_COUNT, '"');
-			c = istr.get();
+			get(istr, buf, STREAM_GET_COUNT, '"');
+			c = get(istr);
 			while(*read != '\0')	 /*Flawfinder: ignore*/
 			{
 				byte = hex_as_nybble(*read++);
@@ -648,8 +830,9 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
 	}
 	else
 	{
-		data.clear();
+		return false;
 	}
+	return true;
 }
 
 
@@ -666,7 +849,7 @@ LLSDBinaryParser::~LLSDBinaryParser()
 }
 
 // virtual
-S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
+S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 {
 /**
  * Undefined: '!'<br>
@@ -685,7 +868,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
  *  notation format.
  */
 	char c;
-	c = istr.get();
+	c = get(istr);
 	if(!istr.good())
 	{
 		return 0;
@@ -694,20 +877,42 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	switch(c)
 	{
 	case '{':
-		parse_count += parseMap(istr, data);
+	{
+		S32 child_count = parseMap(istr, data);
+		if((child_count == PARSE_FAILURE) || data.isUndefined())
+		{
+			parse_count = PARSE_FAILURE;
+		}
+		else
+		{
+			parse_count += child_count;
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading binary map." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
+	}
 
 	case '[':
-		parse_count += parseArray(istr, data);
+	{
+		S32 child_count = parseArray(istr, data);
+		if((child_count == PARSE_FAILURE) || data.isUndefined())
+		{
+			parse_count = PARSE_FAILURE;
+		}
+		else
+		{
+			parse_count += child_count;
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading binary array." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
+	}
 
 	case '!':
 		data.clear();
@@ -724,7 +929,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	case 'i':
 	{
 		U32 value_nbo = 0;
-		istr.read((char*)&value_nbo, sizeof(U32));	 /*Flawfinder: ignore*/
+		read(istr, (char*)&value_nbo, sizeof(U32));	 /*Flawfinder: ignore*/
 		data = (S32)ntohl(value_nbo);
 		if(istr.fail())
 		{
@@ -736,7 +941,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	case 'r':
 	{
 		F64 real_nbo = 0.0;
-		istr.read((char*)&real_nbo, sizeof(F64));	 /*Flawfinder: ignore*/
+		read(istr, (char*)&real_nbo, sizeof(F64));	 /*Flawfinder: ignore*/
 		data = ll_ntohd(real_nbo);
 		if(istr.fail())
 		{
@@ -748,7 +953,7 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	case 'u':
 	{
 		LLUUID id;
-		istr.read((char*)(&id.mData), UUID_BYTES);	 /*Flawfinder: ignore*/
+		read(istr, (char*)(&id.mData), UUID_BYTES);	 /*Flawfinder: ignore*/
 		data = id;
 		if(istr.fail())
 		{
@@ -761,19 +966,40 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	case '"':
 	{
 		std::string value;
-		deserialize_string_delim(istr, value, c);
-		data = value;
+		int cnt = deserialize_string_delim(istr, value, c);
+		if(PARSE_FAILURE == cnt)
+		{
+			parse_count = PARSE_FAILURE;
+		}
+		else
+		{
+			data = value;
+			account(cnt);
+		}
+		if(istr.fail())
+		{
+			llinfos << "STREAM FAILURE reading binary (notation-style) string."
+				<< llendl;
+			parse_count = PARSE_FAILURE;
+		}
 		break;
 	}
 
 	case 's':
 	{
 		std::string value;
-		parseString(istr, value);
-		data = value;
+		if(parseString(istr, value))
+		{
+			data = value;
+		}
+		else
+		{
+			parse_count = PARSE_FAILURE;
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading binary string." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
@@ -781,11 +1007,18 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	case 'l':
 	{
 		std::string value;
-		parseString(istr, value);
-		data = LLURI(value);
+		if(parseString(istr, value))
+		{
+			data = LLURI(value);
+		}
+		else
+		{
+			parse_count = PARSE_FAILURE;
+		}
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading binary link." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
@@ -793,11 +1026,12 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	case 'd':
 	{
 		F64 real = 0.0;
-		istr.read((char*)&real, sizeof(F64));	 /*Flawfinder: ignore*/
+		read(istr, (char*)&real, sizeof(F64));	 /*Flawfinder: ignore*/
 		data = LLDate(real);
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading binary date." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
@@ -806,75 +1040,94 @@ S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
 	{
 		// We probably have a valid raw binary stream. determine
 		// the size, and read it.
-		// *FIX: Should we set a maximum size?
 		U32 size_nbo = 0;
-		istr.read((char*)&size_nbo, sizeof(U32));	/*Flawfinder: ignore*/
+		read(istr, (char*)&size_nbo, sizeof(U32));	/*Flawfinder: ignore*/
 		S32 size = (S32)ntohl(size_nbo);
-		std::vector<U8> value;
-		if(size)
+		if(size > mMaxBytesLeft)
 		{
-			value.resize(size);
-			istr.read((char*)&value[0], size);		 /*Flawfinder: ignore*/
+			parse_count = PARSE_FAILURE;
+		}
+		else
+		{
+			std::vector<U8> value;
+			if(size > 0)
+			{
+				value.resize(size);
+				account(fullread(istr, (char*)&value[0], size));
+			}
+			data = value;
 		}
-		data = value;
 		if(istr.fail())
 		{
 			llinfos << "STREAM FAILURE reading binary." << llendl;
+			parse_count = PARSE_FAILURE;
 		}
 		break;
 	}
 
 	default:
-		--parse_count;
+		parse_count = PARSE_FAILURE;
 		llinfos << "Unrecognized character while parsing: int(" << (int)c
-				<< ")" << llendl;
+			<< ")" << llendl;
 		break;
 	}
+	if(PARSE_FAILURE == parse_count)
+	{
+		data.clear();
+	}
 	return parse_count;
 }
 
-// static
-LLSD LLSDBinaryParser::parse(std::istream& istr)
-{
-	LLSDBinaryParser parser;
-	LLSD rv;
-	S32 count = parser.parse(istr, rv);
-	lldebugs << "LLSDBinaryParser::parse parsed " << count << " objects."
-		 << llendl;
-	return rv;
-}
-
 S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
 {
 	map = LLSD::emptyMap();
 	U32 value_nbo = 0;
-	istr.read((char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
+	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
 	S32 size = (S32)ntohl(value_nbo);
 	S32 parse_count = 0;
 	S32 count = 0;
-	char c = istr.get();
+	char c = get(istr);
 	while(c != '}' && (count < size) && istr.good())
 	{
 		std::string name;
 		switch(c)
 		{
 		case 'k':
-			parseString(istr, name);
+			if(!parseString(istr, name))
+			{
+				return PARSE_FAILURE;
+			}
 			break;
 		case '\'':
 		case '"':
-			deserialize_string_delim(istr, name, c);
+		{
+			int cnt = deserialize_string_delim(istr, name, c);
+			if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
+			account(cnt);
 			break;
 		}
+		}
 		LLSD child;
-		S32 child_count = parse(istr, child);
-		if(child_count)
+		S32 child_count = doParse(istr, child);
+		if(child_count > 0)
 		{
+			// There must be a value for every key, thus child_count
+			// must be greater than 0.
 			parse_count += child_count;
 			map.insert(name, child);
 		}
+		else
+		{
+			return PARSE_FAILURE;
+		}
 		++count;
-		c = istr.get();
+		c = get(istr);
+	}
+	if((c != '}') || (count < size))
+	{
+		// Make sure it is correctly terminated and we parsed as many
+		// as were said to be there.
+		return PARSE_FAILURE;
 	}
 	return parse_count;
 }
@@ -883,7 +1136,7 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
 {
 	array = LLSD::emptyArray();
 	U32 value_nbo = 0;
-	istr.read((char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
+	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
 	S32 size = (S32)ntohl(value_nbo);
 
 	// *FIX: This would be a good place to reserve some space in the
@@ -895,7 +1148,11 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
 	while((c != ']') && (count < size) && istr.good())
 	{
 		LLSD child;
-		S32 child_count = parse(istr, child);
+		S32 child_count = doParse(istr, child);
+		if(PARSE_FAILURE == child_count)
+		{
+			return PARSE_FAILURE;
+		}
 		if(child_count)
 		{
 			parse_count += child_count;
@@ -904,22 +1161,33 @@ S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
 		++count;
 		c = istr.peek();
 	}
-	c = istr.get();
+	c = get(istr);
+	if((c != ']') || (count < size))
+	{
+		// Make sure it is correctly terminated and we parsed as many
+		// as were said to be there.
+		return PARSE_FAILURE;
+	}
 	return parse_count;
 }
 
-void LLSDBinaryParser::parseString(
+bool LLSDBinaryParser::parseString(
 	std::istream& istr,
 	std::string& value) const
 {
 	// *FIX: This is memory inefficient.
 	U32 value_nbo = 0;
-	istr.read((char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
+	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
 	S32 size = (S32)ntohl(value_nbo);
+	if(size > mMaxBytesLeft) return false;
 	std::vector<char> buf;
-	buf.resize(size);
-	istr.read(&buf[0], size);		 /*Flawfinder: ignore*/
-	value.assign(buf.begin(), buf.end());
+	if(size)
+	{
+		buf.resize(size);
+		account(fullread(istr, &buf[0], size));
+		value.assign(buf.begin(), buf.end());
+	}
+	return true;
 }
 
 
@@ -1217,33 +1485,38 @@ void LLSDBinaryFormatter::formatString(
 /**
  * local functions
  */
-bool deserialize_string(std::istream& str, std::string& value)
+int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
 {
-	char c = str.get();
-	if (str.fail())
+	char c = istr.get();
+	if(istr.fail())
 	{
-		// No data in stream, bail out
-		return false;
+		// No data in stream, bail out but mention the character we
+		// grabbed.
+		return LLSDParser::PARSE_FAILURE;
 	}
 
-	bool rv = false;
+	int rv = LLSDParser::PARSE_FAILURE;
 	switch(c)
 	{
 	case '\'':
 	case '"':
-		rv = deserialize_string_delim(str, value, c);
+		rv = deserialize_string_delim(istr, value, c);
 		break;
 	case 's':
-		rv = deserialize_string_raw(str, value);
+		// technically, less than max_bytes, but this is just meant to
+		// catch egregious protocol errors. parse errors will be
+		// caught in the case of incorrect counts.
+		rv = deserialize_string_raw(istr, value, max_bytes);
 		break;
 	default:
 		break;
 	}
-	return rv;
+	if(LLSDParser::PARSE_FAILURE == rv) return rv;
+	return rv + 1; // account for the character grabbed at the top.
 }
 
-bool deserialize_string_delim(
-	std::istream& str,
+int deserialize_string_delim(
+	std::istream& istr,
 	std::string& value,
 	char delim)
 {
@@ -1252,16 +1525,18 @@ bool deserialize_string_delim(
 	bool found_hex = false;
 	bool found_digit = false;
 	U8 byte = 0;
-	
+	int count = 0;
+
 	while (true)
 	{
-		char next_char = str.get();
-		
-		if(str.fail())
+		char next_char = istr.get();
+		++count;
+
+		if(istr.fail())
 		{
 			// If our stream is empty, break out
 			value = write_buffer.str();
-			return false;
+			return LLSDParser::PARSE_FAILURE;
 		}
 		
 		if(found_escape)
@@ -1338,35 +1613,48 @@ bool deserialize_string_delim(
 	}
 
 	value = write_buffer.str();
-	return true;
+	return count;
 }
 
-bool deserialize_string_raw(std::istream& str, std::string& value)
+int deserialize_string_raw(
+	std::istream& istr,
+	std::string& value,
+	S32 max_bytes)
 {
-	bool ok = false;
+	int count = 0;
 	const S32 BUF_LEN = 20;
 	char buf[BUF_LEN];		/* Flawfinder: ignore */
-	str.get(buf, BUF_LEN - 1, ')');
-	char c = str.get();
-	c = str.get();
+	istr.get(buf, BUF_LEN - 1, ')');
+	count += istr.gcount();
+	char c = istr.get();
+	c = istr.get();
+	count += 2;
 	if(((c == '"') || (c == '\'')) && (buf[0] == '('))
 	{
 		// We probably have a valid raw string. determine
 		// the size, and read it.
-		// *FIX: Should we set a maximum size?
 		// *FIX: This is memory inefficient.
 		S32 len = strtol(buf + 1, NULL, 0);
+		if(len > max_bytes) return LLSDParser::PARSE_FAILURE;
 		std::vector<char> buf;
-		buf.resize(len);
-		str.read(&buf[0], len);		 /*Flawfinder: ignore*/
-		value.assign(buf.begin(), buf.end());
-		c = str.get();
-		if((c == '"') || (c == '\''))
+		if(len)
+		{
+			buf.resize(len);
+			count += fullread(istr, (char *)&buf[0], len);
+			value.assign(buf.begin(), buf.end());
+		}
+		c = istr.get();
+		++count;
+		if(!((c == '"') || (c == '\'')))
 		{
-			ok = true;
+			return LLSDParser::PARSE_FAILURE;
 		}
 	}
-	return ok;
+	else
+	{
+		return LLSDParser::PARSE_FAILURE;
+	}
+	return count;
 }
 
 static const char* NOTATION_STRING_CHARACTERS[256] =
@@ -1641,6 +1929,43 @@ void serialize_string(const std::string& value, std::ostream& str)
 	}
 }
 
+int deserialize_boolean(
+	std::istream& istr,
+	LLSD& data,
+	const std::string& compare,
+	bool value)
+{
+	//
+	// this method is a little goofy, because it gets the stream at
+	// the point where the t or f has already been
+	// consumed. Basically, parse for a patch to the string passed in
+	// starting at index 1. If it's a match:
+	//  * assign data to value
+	//  * return the number of bytes read
+	// otherwise:
+	//  * set data to LLSD::null
+	//  * return LLSDParser::PARSE_FAILURE (-1)
+	//
+	int bytes_read = 0;
+	std::string::size_type ii = 0;
+	char c = istr.peek();
+	while((++ii < compare.size())
+		  && (tolower(c) == (int)compare[ii])
+		  && istr.good())
+	{
+		istr.ignore();
+		++bytes_read;
+		c = istr.peek();
+	}
+	if(compare.size() != ii)
+	{
+		data.clear();
+		return LLSDParser::PARSE_FAILURE;
+	}
+	data = value;
+	return bytes_read;
+}
+
 std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
 {
 	s << LLSDNotationStreamer(llsd);
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index b4d6683c2e..26ce1dc993 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -40,7 +40,7 @@
 
 /** 
  * @class LLSDParser
- * @brief Abstract base class for simple LLSD parsers.
+ * @brief Abstract base class for LLSD parsers.
  */
 class LLSDParser : public LLRefCount
 {
@@ -51,6 +51,14 @@ protected:
 	virtual ~LLSDParser();
 
 public:
+	/** 
+	 * @brief Anonymous enum to indicate parsing failure.
+	 */
+	enum
+	{
+		PARSE_FAILURE = -1
+	};
+
 	/** 
 	 * @brief Constructor
 	 */
@@ -67,12 +75,122 @@ public:
 	 * caller.
 	 * @param istr The input stream.
 	 * @param data[out] The newly parse structured data.
-	 * @return Returns The number of LLSD objects parsed into data.
+	 * @param max_bytes The maximum number of bytes that will be in
+	 * the stream. Pass in LLSDSerialize::SIZE_UNLIMITED (-1) to set no
+	 * byte limit.
+	 * @return Returns the number of LLSD objects parsed into
+	 * data. Returns PARSE_FAILURE (-1) on parse failure.
+	 */
+	S32 parse(std::istream& istr, LLSD& data, S32 max_bytes);
+
+protected:
+	/** 
+	 * @brief Pure virtual base for doing the parse.
+	 *
+	 * This method parses the istream for a structured data. This
+	 * method assumes that the istream is a complete llsd object --
+	 * for example an opened and closed map with an arbitrary nesting
+	 * of elements. This method will return after reading one data
+	 * object, allowing continued reading from the stream by the
+	 * caller.
+	 * @param istr The input stream.
+	 * @param data[out] The newly parse structured data.
+	 * @return Returns the number of LLSD objects parsed into
+	 * data. Returns PARSE_FAILURE (-1) on parse failure.
+	 */
+	virtual S32 doParse(std::istream& istr, LLSD& data) const = 0;
+
+	/* @name Simple istream helper methods 
+	 *
+	 * These helper methods exist to help correctly use the
+	 * mMaxBytesLeft without really thinking about it for most simple
+	 * operations. Use of the streamtools in llstreamtools.h will
+	 * require custom wrapping.
+	 */
+	//@{
+	/** 
+	 * @brief get a byte off the stream
+	 *
+	 * @param istr The istream to work with.
+	 * @return returns the next character.
+	 */
+	int get(std::istream& istr) const;
+	
+	/** 
+	 * @brief get several bytes off the stream into a buffer.
+	 *
+	 * @param istr The istream to work with.
+	 * @param s The buffer to get into
+	 * @param n Extract maximum of n-1 bytes and null temrinate.
+	 * @param delim Delimiter to get until found.
+	 * @return Returns istr.
+	 */
+	std::istream& get(
+		std::istream& istr,
+		char* s,
+		std::streamsize n,
+		char delim) const;
+
+	/** 
+	 * @brief get several bytes off the stream into a streambuf
+	 *
+	 * @param istr The istream to work with.
+	 * @param sb The streambuf to read into
+	 * @param delim Delimiter to get until found.
+	 * @return Returns istr.
+	 */
+	std::istream& get(
+		std::istream& istr,
+		std::streambuf& sb,
+		char delim) const;
+
+	/** 
+	 * @brief ignore the next byte on the istream
+	 *
+	 * @param istr The istream to work with.
+	 * @return Returns istr.
+	 */
+	std::istream& ignore(std::istream& istr) const;
+
+	/** 
+	 * @brief put the last character retrieved back on the stream
+	 *
+	 * @param istr The istream to work with.
+	 * @param c The character to put back
+	 * @return Returns istr.
+	 */
+	std::istream& putback(std::istream& istr, char c) const;
+
+	/** 
+	 * @brief read a block of n characters into a buffer
+	 *
+	 * @param istr The istream to work with.
+	 * @param s The buffer to read into
+	 * @param n The number of bytes to read.
+	 * @return Returns istr.
+	 */
+	std::istream& read(std::istream& istr, char* s, std::streamsize n) const;
+	//@}
+
+protected:
+	/**
+	 * @brief Accunt for bytes read outside of the istream helpers.
+	 *
+	 * Conceptually const since it only modifies mutable members.
+	 * @param bytes The number of bytes read.
 	 */
-	virtual S32 parse(std::istream& istr, LLSD& data) const = 0;
+	void account(S32 bytes) const;
 
 protected:
+	/**
+	 * @brief boolean to set if byte counts should be checked during parsing.
+	 */
+	bool mCheckLimits;
 
+	/**
+	 * @brief The maximum number of bytes left to be parsed.
+	 */
+	mutable S32 mMaxBytesLeft;
 };
 
 /** 
@@ -91,8 +209,9 @@ public:
 	/** 
 	 * @brief Constructor
 	 */
-	LLSDNotationParser() {}
+	LLSDNotationParser();
 
+protected:
 	/** 
 	 * @brief Call this method to parse a stream for LLSD.
 	 *
@@ -105,21 +224,9 @@ public:
 	 * @param istr The input stream.
 	 * @param data[out] The newly parse structured data. Undefined on failure.
 	 * @return Returns the number of LLSD objects parsed into
-	 * data. Returns -1 on parse failure.
-	 */
-	virtual S32 parse(std::istream& istr, LLSD& data) const;
-
-	/** 
-	 * @brief Simple notation parse.
-	 *
-	 * This simplified parser cannot not distinguish between a failed
-	 * parse and a parse which yields a single undefined LLSD. You can
-	 * use this if error checking will be implicit in the use of the
-	 * results of the parse.
-	 * @param istr The input stream.
-	 * @return Returns the parsed LLSD object.
+	 * data. Returns PARSE_FAILURE (-1) on parse failure.
 	 */
-	static LLSD parse(std::istream& istr);
+	virtual S32 doParse(std::istream& istr, LLSD& data) const;
 
 private:
 	/** 
@@ -145,16 +252,18 @@ private:
 	 *
 	 * @param istr The input stream.
 	 * @param data[out] The data to assign.
+	 * @return Retuns true if a complete string was parsed.
 	 */
-	void parseString(std::istream& istr, LLSD& data) const;
+	bool parseString(std::istream& istr, LLSD& data) const;
 
 	/** 
 	 * @brief Parse binary data from the stream.
 	 *
 	 * @param istr The input stream.
 	 * @param data[out] The data to assign.
+	 * @return Retuns true if a complete blob was parsed.
 	 */
-	void parseBinary(std::istream& istr, LLSD& data) const;
+	bool parseBinary(std::istream& istr, LLSD& data) const;
 };
 
 /** 
@@ -175,6 +284,7 @@ public:
 	 */
 	LLSDXMLParser();
 
+protected:
 	/** 
 	 * @brief Call this method to parse a stream for LLSD.
 	 *
@@ -186,15 +296,16 @@ public:
 	 * caller.
 	 * @param istr The input stream.
 	 * @param data[out] The newly parse structured data.
-	 * @return Returns the number of LLSD objects parsed into data.
+	 * @return Returns the number of LLSD objects parsed into
+	 * data. Returns PARSE_FAILURE (-1) on parse failure.
 	 */
-	virtual S32 parse(std::istream& istr, LLSD& data) const;
+	virtual S32 doParse(std::istream& istr, LLSD& data) const;
 
 private:
 	class Impl;
 	Impl& impl;
 
-	void parsePart(const char *buf, int len);
+	void parsePart(const char* buf, int len);
 	friend class LLSDSerialize;
 };
 
@@ -216,6 +327,7 @@ public:
 	 */
 	LLSDBinaryParser();
 
+protected:
 	/** 
 	 * @brief Call this method to parse a stream for LLSD.
 	 *
@@ -227,21 +339,10 @@ public:
 	 * caller.
 	 * @param istr The input stream.
 	 * @param data[out] The newly parse structured data.
-	 * @return Returns the number of LLSD objects parsed into data.
-	 */
-	virtual S32 parse(std::istream& istr, LLSD& data) const;
-
-	/** 
-	 * @brief Simple notation parse.
-	 *
-	 * This simplified parser cannot not distinguish between a failed
-	 * parse and a parse which yields a single undefined LLSD. You can
-	 * use this if error checking will be implicit in the use of the
-	 * results of the parse.
-	 * @param istr The input stream.
-	 * @return Returns the parsed LLSD object.
+	 * @return Returns the number of LLSD objects parsed into
+	 * data. Returns -1 on parse failure.
 	 */
-	static LLSD parse(std::istream& istr);
+	virtual S32 doParse(std::istream& istr, LLSD& data) const;
 
 private:
 	/** 
@@ -267,8 +368,9 @@ private:
 	 *
 	 * @param istr The input stream.
 	 * @param value[out] The string to assign.
+	 * @return Retuns true if a complete string was parsed.
 	 */
-	void parseString(std::istream& istr, std::string& value) const;
+	bool parseString(std::istream& istr, std::string& value) const;
 };
 
 
@@ -544,7 +646,7 @@ typedef LLSDOStreamer<LLSDXMLFormatter>			LLSDXMLStreamer;
 
 /** 
  * @class LLSDSerialize
- * @Serializer / deserializer for the various LLSD formats
+ * @brief Serializer / deserializer for the various LLSD formats
  */
 class LLSDSerialize
 {
@@ -554,12 +656,32 @@ public:
 		LLSD_BINARY, LLSD_XML
 	};
 
+	/**
+	 * @brief anonymouse enumeration for useful max_bytes constants.
+	 */
+	enum
+	{
+		// Setting an unlimited size is discouraged and should only be
+		// used when reading cin or another stream source which does
+		// not provide access to size.
+		SIZE_UNLIMITED = -1,
+	};
+
 	/*
 	 * Generic in/outs
 	 */
 	static void serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize,
 		U32 options = LLSDFormatter::OPTIONS_NONE);
-	static bool deserialize(LLSD& sd, std::istream& str);
+
+	/**
+	 * @breif Examine a stream, and parse 1 sd object out based on contents.
+	 *
+	 * @param sd [out] The data found on the stream
+	 * @param str The incoming stream
+	 * @param max_bytes the maximum number of bytes to parse
+	 * @return Returns true if the stream appears to contain valid data
+	 */
+	static bool deserialize(LLSD& sd, std::istream& str, S32 max_bytes);
 
 	/*
 	 * Notation Methods
@@ -569,10 +691,17 @@ public:
 		LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter;
 		return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
 	}
-	static S32 fromNotation(LLSD& sd, std::istream& str)
+	static S32 fromNotation(LLSD& sd, std::istream& str, S32 max_bytes)
+	{
+		LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
+		return p->parse(str, sd, max_bytes);
+	}
+	static LLSD fromNotation(std::istream& str, S32 max_bytes)
 	{
 		LLPointer<LLSDNotationParser> p = new LLSDNotationParser;
-		return p->parse(str, sd);
+		LLSD sd;
+		(void)p->parse(str, sd, max_bytes);
+		return sd;
 	}
 	
 	/*
@@ -588,10 +717,13 @@ public:
 		LLPointer<LLSDXMLFormatter> f = new LLSDXMLFormatter;
 		return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);
 	}
+
 	static S32 fromXML(LLSD& sd, std::istream& str)
 	{
+		// no need for max_bytes since xml formatting is not
+		// subvertable by bad sizes.
 		LLPointer<LLSDXMLParser> p = new LLSDXMLParser;
-		return p->parse(str, sd);
+		return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED);
 	}
 
 	/*
@@ -602,14 +734,18 @@ public:
 		LLPointer<LLSDBinaryFormatter> f = new LLSDBinaryFormatter;
 		return f->format(sd, str, LLSDFormatter::OPTIONS_NONE);
 	}
-	static S32 fromBinary(LLSD& sd, std::istream& str)
+	static S32 fromBinary(LLSD& sd, std::istream& str, S32 max_bytes)
 	{
 		LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
-		return p->parse(str, sd);
+		return p->parse(str, sd, max_bytes);
+	}
+	static LLSD fromBinary(std::istream& str, S32 max_bytes)
+	{
+		LLPointer<LLSDBinaryParser> p = new LLSDBinaryParser;
+		LLSD sd;
+		(void)p->parse(str, sd, max_bytes);
+		return sd;
 	}
-private:
-	static const char *LLSDBinaryHeader;
-	static const char *LLSDXMLHeader;
 };
 
 #endif // LL_LLSDSERIALIZE_H
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 6232622298..b3596e8705 100644
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -305,6 +305,7 @@ private:
 	XML_Parser	mParser;
 
 	LLSD mResult;
+	S32 mParseCount;
 	
 	bool mInLLSDElement;
 	bool mGracefullStop;
@@ -411,12 +412,12 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
 		}
 		llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl;
 		data = LLSD();
-		return -1;
+		return LLSDParser::PARSE_FAILURE;
 	}
 
 	clear_eol(input);
 	data = mResult;
-	return 1;
+	return mParseCount;
 }
 
 void LLSDXMLParser::Impl::reset()
@@ -428,6 +429,7 @@ void LLSDXMLParser::Impl::reset()
 	}
 
 	mResult.clear();
+	mParseCount = 0;
 
 	mInLLSDElement = false;
 	mDepth = 0;
@@ -472,7 +474,7 @@ LLSDXMLParser::Impl::findAttribute(const XML_Char* name, const XML_Char** pairs)
 	return NULL;
 }
 
-void LLSDXMLParser::Impl::parsePart(const char *buf, int len)
+void LLSDXMLParser::Impl::parsePart(const char* buf, int len)
 {
 	void * buffer = XML_GetBuffer(mParser, len);
 	if (buffer != NULL && buf != NULL)
@@ -486,7 +488,7 @@ void LLSDXMLParser::Impl::parsePart(const char *buf, int len)
 
 void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Char** attributes)
 {
-	mDepth += 1;
+	++mDepth;
 	if (mSkipping)
 	{
 		return;
@@ -554,6 +556,7 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch
 		return startSkipping();
 	}
 
+	++mParseCount;
 	switch (element)
 	{
 		case ELEMENT_MAP:
@@ -572,7 +575,7 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch
 
 void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
 {
-	mDepth -= 1;
+	--mDepth;
 	if (mSkipping)
 	{
 		if (mDepth < mSkipThrough)
@@ -715,10 +718,10 @@ LLSDXMLParser::Impl::Element LLSDXMLParser::Impl::readElement(const XML_Char* na
 
 
 
-
-
-LLSDXMLParser::LLSDXMLParser()
-	: impl(* new Impl)
+/**
+ * LLSDXMLParser
+ */
+LLSDXMLParser::LLSDXMLParser() : impl(* new Impl)
 {
 }
 
@@ -733,7 +736,7 @@ void LLSDXMLParser::parsePart(const char *buf, int len)
 }
 
 // virtual
-S32 LLSDXMLParser::parse(std::istream& input, LLSD& data) const
+S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data) const
 {
 	return impl.parse(input, data);	
 }
diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp
index bfe1765827..8d4a3ef6b8 100644
--- a/indra/llcommon/llstreamtools.cpp
+++ b/indra/llcommon/llstreamtools.cpp
@@ -538,23 +538,32 @@ void get_keyword_and_value(std::string& keyword,
 	}
 }
 
-std::istream& fullread(std::istream& str, char *buf, std::streamsize requested)
+std::streamsize fullread(
+	std::istream& istr,
+	char* buf,
+	std::streamsize requested)
 {
 	std::streamsize got;
 	std::streamsize total = 0;
 
-	str.read(buf, requested);	 /*Flawfinder: ignore*/
-	got = str.gcount();
+	istr.read(buf, requested);	 /*Flawfinder: ignore*/
+	got = istr.gcount();
 	total += got;
-	while (got && total < requested)
+	while(got && total < requested)
 	{
-		if (str.fail())
-			str.clear();
-		str.read(buf + total, requested - total);	 /*Flawfinder: ignore*/
-		got = str.gcount();
+		if(istr.fail())
+		{
+			// If bad is true, not much we can doo -- it implies loss
+			// of stream integrity. Bail in that case, and otherwise
+			// clear and attempt to continue.
+			if(istr.bad()) return total;
+			istr.clear();
+		}
+		istr.read(buf + total, requested - total);	 /*Flawfinder: ignore*/
+		got = istr.gcount();
 		total += got;
 	}
-	return str;
+	return total;
 }
 
 std::istream& operator>>(std::istream& str, const char *tocheck)
diff --git a/indra/llcommon/llstreamtools.h b/indra/llcommon/llstreamtools.h
index 0708447050..b024112f9f 100644
--- a/indra/llcommon/llstreamtools.h
+++ b/indra/llcommon/llstreamtools.h
@@ -114,7 +114,12 @@ void get_keyword_and_value(std::string& keyword,
 // continue to read from the stream until you really can't
 // read anymore or until we hit the count.  Some istream
 // implimentations have a max that they will read.
-std::istream& fullread(std::istream& str, char *buf, std::streamsize requested);
+// Returns the number of bytes read.
+std::streamsize fullread(
+	std::istream& istr,
+	char* buf,
+	std::streamsize requested);
+
 
 std::istream& operator>>(std::istream& str, const char *tocheck);
 
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index a20247866c..04b7d688e5 100755
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -117,8 +117,10 @@ void LLCrashLogger::gatherFiles()
 	updateApplication("Gathering logs...");
 
 	// Figure out the filename of the debug log
-	LLString db_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"debug_info.log").c_str();
-	std::ifstream debug_log_file(db_file_name.c_str());
+	std::string db_file_name = gDirUtilp->getExpandedFilename(
+		LL_PATH_LOGS,
+		"debug_info.log");
+	llifstream debug_log_file(db_file_name.c_str());
 
 	// Look for it in the debug_info.log file
 	if (debug_log_file.is_open())
diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h
index b251af8b35..52fc769be9 100644
--- a/indra/llmessage/llbuffer.h
+++ b/indra/llmessage/llbuffer.h
@@ -410,6 +410,18 @@ public:
 	 */
 	S32 countAfter(S32 channel, U8* start) const;
 
+	/** 
+	 * @brief Count all bytes on channel.
+	 *
+	 * Helper method which just calls countAfter().
+	 * @param channel The channel to count.
+	 * @return Returns the number of bytes in the channel.
+	 */
+	S32 count(S32 channel) const
+	{
+		return countAfter(channel, NULL);
+	}
+
 	/** 
 	 * @brief Read bytes in the buffer array on the specified channel
 	 *
diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp
index eac7dc11f2..88f7b1cb68 100644
--- a/indra/llmessage/llfiltersd2xmlrpc.cpp
+++ b/indra/llmessage/llfiltersd2xmlrpc.cpp
@@ -336,7 +336,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
 	LLBufferStream stream(channels, buffer.get());
 	stream << XML_HEADER << XMLRPC_METHOD_RESPONSE_HEADER;
 	LLSD sd;
-	LLSDSerialize::fromNotation(sd, stream);
+	LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
 
 	PUMP_DEBUG;
 	LLIOPipe::EStatus rv = STATUS_ERROR;
@@ -408,7 +408,7 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
 	// See if we can parse it
 	LLBufferStream stream(channels, buffer.get());
 	LLSD sd;
-	LLSDSerialize::fromNotation(sd, stream);
+	LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
 	if(stream.fail())
 	{
 		llinfos << "STREAM FAILURE reading structure data." << llendl;
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index bf5fa4073d..9f6115a0e4 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -71,8 +71,11 @@ void LLHTTPClient::Responder::result(const LLSD& content)
 }
 
 // virtual 
-void LLHTTPClient::Responder::completedRaw(U32 status, const std::string& reason, const LLChannelDescriptors& channels,
-								const LLIOPipe::buffer_ptr_t& buffer)
+void LLHTTPClient::Responder::completedRaw(
+	U32 status,
+	const std::string& reason,
+	const LLChannelDescriptors& channels,
+	const LLIOPipe::buffer_ptr_t& buffer)
 {
 	LLBufferStream istr(channels, buffer.get());
 	LLSD content;
@@ -94,7 +97,10 @@ void LLHTTPClient::Responder::completedRaw(U32 status, const std::string& reason
 }
 
 // virtual
-void LLHTTPClient::Responder::completed(U32 status, const std::string& reason, const LLSD& content)
+void LLHTTPClient::Responder::completed(
+	U32 status,
+	const std::string& reason,
+	const LLSD& content)
 {
 	if(isGoodStatus(status))
 	{
diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h
index 6323defb76..983ff46e03 100644
--- a/indra/llmessage/llhttpclient.h
+++ b/indra/llmessage/llhttpclient.h
@@ -72,11 +72,18 @@ public:
 		
 		virtual void result(const LLSD& content);
 		
-		// Override point for clients that may want to use this class when the response is some other format besides LLSD
-		virtual void completedRaw(U32 status, const std::string& reason, const LLChannelDescriptors& channels,
-								const LLIOPipe::buffer_ptr_t& buffer);
-
-		virtual void completed(U32 status, const std::string& reason, const LLSD& content);
+		// Override point for clients that may want to use this class
+		// when the response is some other format besides LLSD
+		virtual void completedRaw(
+			U32 status,
+			const std::string& reason,
+			const LLChannelDescriptors& channels,
+			const LLIOPipe::buffer_ptr_t& buffer);
+
+		virtual void completed(
+			U32 status,
+			const std::string& reason,
+			const LLSD& content);
 			/**< The default implemetnation calls
 				either:
 				* result(), or
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index acc38e153d..625dbb68b9 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -156,7 +156,9 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 			// assume deferred unless mResponse does otherwise
 		mResponse = Response::create(this);
 
-		// TODO: Babbage: Parameterize parser?
+		// *TODO: Babbage: Parameterize parser?
+		// *TODO: We should look at content-type and do the right
+		// thing. Phoenix 2007-12-31
 		LLBufferStream istr(channels, buffer.get());
 
 		static LLTimer timer;
@@ -171,14 +173,12 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
 		{
 			LLSD input;
 			LLSDSerialize::fromXML(input, istr);
-
 			mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
 		}
 		else if(verb == HTTP_VERB_POST)
 		{
 			LLSD input;
 			LLSDSerialize::fromXML(input, istr);
-
 			mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
 		}
 		else if(verb == HTTP_VERB_DELETE)
diff --git a/indra/llmessage/llsdrpcclient.cpp b/indra/llmessage/llsdrpcclient.cpp
index 0a12c478f9..c4738b7083 100644
--- a/indra/llmessage/llsdrpcclient.cpp
+++ b/indra/llmessage/llsdrpcclient.cpp
@@ -221,7 +221,7 @@ LLIOPipe::EStatus LLSDRPCClient::process_impl(
 		//		 << llendl;
 		LLBufferStream resp(channels, buffer.get());
 		LLSD sd;
-		LLSDSerialize::fromNotation(sd, resp);
+		LLSDSerialize::fromNotation(sd, resp, buffer->count(channels.in()));
 		LLSDRPCResponse* response = (LLSDRPCResponse*)mResponse.get();
 		if (!response)
 		{
diff --git a/indra/llmessage/llsdrpcserver.cpp b/indra/llmessage/llsdrpcserver.cpp
index 13ed79110f..ab1b800db8 100644
--- a/indra/llmessage/llsdrpcserver.cpp
+++ b/indra/llmessage/llsdrpcserver.cpp
@@ -182,7 +182,10 @@ LLIOPipe::EStatus LLSDRPCServer::process_impl(
 		PUMP_DEBUG;
 		LLBufferStream istr(channels, buffer.get());
 		mRequest.clear();
-		LLSDSerialize::fromNotation(mRequest, istr);
+		LLSDSerialize::fromNotation(
+			mRequest,
+			istr,
+			buffer->count(channels.in()));
 
 		// { 'method':'...', 'parameter': ... }
 		method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
diff --git a/indra/llmessage/llservicebuilder.cpp b/indra/llmessage/llservicebuilder.cpp
index 22e5c4af43..a3e6ee479b 100644
--- a/indra/llmessage/llservicebuilder.cpp
+++ b/indra/llmessage/llservicebuilder.cpp
@@ -1,33 +1,33 @@
 /** 
-* @file llservicebuilder.cpp
-* @brief Implementation of the LLServiceBuilder class.
-*
-* $LicenseInfo:firstyear=2007&license=viewergpl$
-* 
-* Copyright (c) 2007, Linden Research, Inc.
-* 
-* Second Life Viewer Source Code
-* The source code in this file ("Source Code") is provided by Linden Lab
-* to you under the terms of the GNU General Public License, version 2.0
-* ("GPL"), unless you have obtained a separate licensing agreement
-* ("Other License"), formally executed by you and Linden Lab.  Terms of
-* the GPL can be found in doc/GPL-license.txt in this distribution, or
-* online at http://secondlife.com/developers/opensource/gplv2
-* 
-* There are special exceptions to the terms and conditions of the GPL as
-* it is applied to this Source Code. View the full text of the exception
-* in the file doc/FLOSS-exception.txt in this software distribution, or
-* online at http://secondlife.com/developers/opensource/flossexception
-* 
-* By copying, modifying or distributing this software, you acknowledge
-* that you have read and understood your obligations described above,
-* and agree to abide by those obligations.
-* 
-* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
-* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
-* COMPLETENESS OR PERFORMANCE.
-* $/LicenseInfo$
-*/
+ * @file llservicebuilder.cpp
+ * @brief Implementation of the LLServiceBuilder class.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ * 
+ * Copyright (c) 2007, Linden Research, Inc.
+ * 
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab.  Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ * 
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ * 
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ * 
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
 
 #include "linden_common.h"
 #include "llapp.h"
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 907f957bed..97f652d88d 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -390,7 +390,6 @@ static const char USAGE[] = "\n"
 " -set <variable> <value>              specify the value of a particular\n"
 "                                        configuration variable that\n"
 "                                        overrides all other settings\n"
-" -user <user_server_ip>               specify userserver in dotted quad\n"
 #if !LL_RELEASE_FOR_DOWNLOAD
 " -sim <simulator_ip>                  specify the simulator ip address\n"
 #endif
@@ -658,21 +657,6 @@ int parse_args(int argc, char **argv)
 			gGridChoice = GRID_INFO_YAMI;
 			sprintf(gGridName,"%s", gGridInfo[gGridChoice].mName);
 		}
-		else if (!strcmp(argv[j], "-user") && (++j < argc)) 
-		{
-			if (!strcmp(argv[j], "-"))
-			{
-				gGridChoice = GRID_INFO_LOCAL;
-				snprintf(gGridName, MAX_STRING, "%s", LOOPBACK_ADDRESS_STRING);		// Flawfinder: ignore
-			}
-			else
-			{
-				gGridChoice = GRID_INFO_OTHER;
-				ip_string.assign( argv[j] );
-				LLString::trim(ip_string);
-				snprintf(gGridName, MAX_STRING, "%s", ip_string.c_str());		// Flawfinder: ignore
-			}
-		}
 		else if (!strcmp(argv[j], "-loginpage") && (++j < argc))
 		{
 			LLAppViewer::instance()->setLoginPage(utf8str_trim(argv[j]));
@@ -1927,17 +1911,6 @@ bool LLAppViewer::initEarlyConfiguration()
 		{
 			sprintf(gGridName,"%s", gGridInfo[GRID_INFO_ARUNA].mName);
 		}
-		else if (!strcmp(argv[j], "-user") && (++j < argc))
-		{
-			if (!strcmp(argv[j], "-"))
-			{
-				snprintf(gGridName, MAX_STRING, "%s", LOOPBACK_ADDRESS_STRING);		// Flawfinder: ignore 
-			}
-			else
-			{
-				snprintf(gGridName, MAX_STRING, "%s", argv[j]);		// Flawfinder: ignore 
-			}
-		}
 		else if (!strcmp(argv[j], "-multiple"))
 		{
 			// Hack to detect -multiple so we can disable the marker file check (which will always fail)
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index da298c56c4..31c60d8b2d 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -1126,7 +1126,7 @@ void LLFloaterSnapshot::Impl::onCommitResolution(LLUICtrl* ctrl, void* data)
 	std::string sdstring = combobox->getSelectedValue();
 	LLSD sdres;
 	std::stringstream sstream(sdstring);
-	LLSDSerialize::fromNotation(sdres, sstream);
+	LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
 		
 	S32 width = sdres[0];
 	S32 height = sdres[1];
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 660de69fb0..b0d7aa6d1b 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -468,6 +468,7 @@ void LLPreview::onBtnCopyToInv(void* userdata)
 				cb);
 		}
 	}
+	self->close();
 }
 
 // static
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 20e4eee396..8df34d39c6 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1377,8 +1377,13 @@ BOOL idle_startup()
 			const char* look_at_str = gUserAuthp->getResponse("look_at");
 			if (look_at_str)
 			{
-				LLMemoryStream mstr((U8*)look_at_str, strlen(look_at_str));		/* Flawfinder: ignore */
-				LLSD sd = LLSDNotationParser::parse(mstr);
+#if !LL_WINDOWS && !LL_DARWIN
+				size_t len = strnlen(look_at_str, MAX_STRING);
+#else
+				size_t len = strlen(look_at_str);
+#endif
+				LLMemoryStream mstr((U8*)look_at_str, len);
+				LLSD sd = LLSDSerialize::fromNotation(mstr, len);
 				agent_start_look_at = ll_vector3_from_sd(sd);
 			}
 
@@ -1399,8 +1404,13 @@ BOOL idle_startup()
 			const char* home_location = gUserAuthp->getResponse("home");
 			if(home_location)
 			{
-				LLMemoryStream mstr((U8*)home_location, strlen(home_location));		/* Flawfinder: ignore */
-				LLSD sd = LLSDNotationParser::parse(mstr);
+#if !LL_WINDOWS && !LL_DARWIN
+				size_t len = strnlen(home_location, MAX_STRING);
+#else
+				size_t len = strlen(home_location);
+#endif
+				LLMemoryStream mstr((U8*)home_location, len);
+				LLSD sd = LLSDSerialize::fromNotation(mstr, len);
 				S32 region_x = sd["region_handle"][0].asInteger();
 				S32 region_y = sd["region_handle"][1].asInteger();
 				U64 region_handle = to_region_handle(region_x, region_y);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 9332a909d7..6b18fb46be 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1194,8 +1194,8 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
 	LLString::format_map_t args;
 	args["[OBJECTNAME]"] = info->mDesc;
 	// must protect against a NULL return from lookupHumanReadable()
-	const char* typestr = LLAssetType::lookupHumanReadable(info->mType);
-	if (typestr)
+	std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType));
+	if (!typestr.empty())
 	{
 		args["[OBJECTTYPE]"] = typestr;
 	}
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index bd488577e3..871fc9702e 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -942,7 +942,13 @@ BOOL LLViewerTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
 			S32 dy = y - mMouseDownY;
 			if (-2 < dx && dx < 2 && -2 < dy && dy < 2)
 			{
-				openEmbeddedItem(mDragItem, mDragItemSaved);
+				if(mDragItemSaved)
+				{
+					openEmbeddedItem(mDragItem);
+				}else
+				{
+					showUnsavedAlertDialog(mDragItem);
+				}
 			}
 		}
 		mDragItem = NULL;
@@ -1311,15 +1317,23 @@ BOOL LLViewerTextEditor::openEmbeddedItemAtPos(S32 pos)
 		if( item )
 		{
 			BOOL saved = LLEmbeddedItems::getEmbeddedItemSaved( mWText[pos] );
-			return openEmbeddedItem(item, saved);
+			if (saved)
+			{
+				return openEmbeddedItem(item); 
+			}
+			else
+			{
+				showUnsavedAlertDialog(item);
+			}
 		}
 	}
 	return FALSE;
 }
 
 
-BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item, BOOL saved)
+BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item)
 {
+
 	switch( item->getType() )
 	{
 	case LLAssetType::AT_TEXTURE:
@@ -1329,15 +1343,15 @@ BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item, BOOL saved)
 	case LLAssetType::AT_SOUND:
 		openEmbeddedSound( item );
 		return TRUE;
-	
+
 	case LLAssetType::AT_NOTECARD:
-	    openEmbeddedNotecard( item, saved );
+		openEmbeddedNotecard( item );
 		return TRUE;
 
 	case LLAssetType::AT_LANDMARK:
 		openEmbeddedLandmark( item );
 		return TRUE;
-		
+
 	case LLAssetType::AT_LSL_TEXT:
 	case LLAssetType::AT_CLOTHING:
 	case LLAssetType::AT_OBJECT:
@@ -1345,10 +1359,11 @@ BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item, BOOL saved)
 	case LLAssetType::AT_ANIMATION:
 	case LLAssetType::AT_GESTURE:
 		showCopyToInvDialog( item );
-		return TRUE;	
+		return TRUE;
 	default:
 		return FALSE;
 	}
+
 }
 
 
@@ -1401,23 +1416,30 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item )
 	open_landmark((LLViewerInventoryItem*)item, title, FALSE, item->getUUID(), TRUE);
 }
 
-void LLViewerTextEditor::openEmbeddedNotecard( LLInventoryItem* item, BOOL saved )
+void LLViewerTextEditor::openEmbeddedNotecard( LLInventoryItem* item )
 {
-	if (saved)
-	{
+	//if (saved)
+	//{
 		// An LLInventoryItem needs to be in an inventory to be opened.
 		// This will give the item to the viewer's agent.
 		// The callback will attempt to open it if its not already opened.
-		copyInventory(item, gInventoryCallbacks.registerCB(mInventoryCallback));
-	}
-	else
-	{
-		LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
-		gViewerWindow->alertXml("ConfirmNotecardSave",		
-								LLViewerTextEditor::onNotecardDialog, (void*)info);
-	}
+	copyInventory(item, gInventoryCallbacks.registerCB(mInventoryCallback));
+
+	//}
+	//else
+	//{
+	//	LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
+	//	gViewerWindow->alertXml("ConfirmNotecardSave",		
+	//							LLViewerTextEditor::onNotecardDialog, (void*)info);
+	//}
 }
 
+void LLViewerTextEditor::showUnsavedAlertDialog( LLInventoryItem* item )
+{
+	LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
+	gViewerWindow->alertXml( "ConfirmNotecardSave",
+		LLViewerTextEditor::onNotecardDialog, (void*)info);
+}
 // static
 void LLViewerTextEditor::onNotecardDialog( S32 option, void* userdata )
 {
diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h
index 1ec173a5d1..02d934fc3c 100644
--- a/indra/newview/llviewertexteditor.h
+++ b/indra/newview/llviewertexteditor.h
@@ -107,15 +107,16 @@ protected:
 
 	BOOL			getEmbeddedItemToolTipAtPos(S32 pos, LLWString &wmsg);
 	BOOL			openEmbeddedItemAtPos( S32 pos );
-	BOOL			openEmbeddedItem(LLInventoryItem* item, BOOL saved);
+	BOOL			openEmbeddedItem(LLInventoryItem* item);
 
 	S32				insertEmbeddedItem(S32 pos, LLInventoryItem* item);
 
 	void			openEmbeddedTexture( LLInventoryItem* item );
 	void			openEmbeddedSound( LLInventoryItem* item );
 	void			openEmbeddedLandmark( LLInventoryItem* item );
-	void			openEmbeddedNotecard( LLInventoryItem* item, BOOL saved );
+	void			openEmbeddedNotecard( LLInventoryItem* item);
 	void			showCopyToInvDialog( LLInventoryItem* item );
+	void			showUnsavedAlertDialog( LLInventoryItem* item );
 
 	static void		onCopyToInvDialog( S32 option, void* userdata );
 	static void		onNotecardDialog( S32 option, void* userdata );
diff --git a/indra/test/io.cpp b/indra/test/io.cpp
index 350fc5394b..c322522ce3 100644
--- a/indra/test/io.cpp
+++ b/indra/test/io.cpp
@@ -634,7 +634,7 @@ namespace tut
 		ensure_equals("size of buffer", count, total_size);
 		LLBufferStream istr(ch, &mBuffer);
 		LLSD data;
-		count = LLSDSerialize::fromNotation(data, istr);
+		count = LLSDSerialize::fromNotation(data, istr, total_size);
 		ensure("sd parsed", data.isDefined());
 
 		for(S32 j = 0; j < 3; ++j)
@@ -699,7 +699,7 @@ namespace tut
 		ensure_equals("size of buffer", count, total_size);
 		LLBufferStream istr(ch, &mBuffer);
 		LLSD data;
-		count = LLSDSerialize::fromNotation(data, istr);
+		count = LLSDSerialize::fromNotation(data, istr, total_size);
 		ensure("sd parsed", data.isDefined());
 	}
 
@@ -735,7 +735,10 @@ namespace tut
 		ch = mBuffer.nextChannel();
 		LLBufferStream istr(ch, &mBuffer);
 		LLSD data;
-		S32 count = LLSDSerialize::fromNotation(data, istr);
+		S32 count = LLSDSerialize::fromNotation(
+			data,
+			istr,
+			mBuffer.count(ch.in()));
 		ensure("parsed something", (count > 0));
 		ensure("sd parsed", data.isDefined());
 		ensure_equals("sd type", data.type(), LLSD::TypeMap);
@@ -780,7 +783,7 @@ namespace tut
 		std::istringstream istr;
 		istr.str(val);
 		LLSD sd;
-		S32 count = LLSDSerialize::fromNotation(sd, istr);
+		S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
 		ensure_equals("parser error return value", count, -1);
 		ensure("data undefined", sd.isUndefined());
 	}
@@ -792,7 +795,7 @@ namespace tut
 		std::istringstream istr;
 		istr.str(val);
 		LLSD sd;
-		S32 count = LLSDSerialize::fromNotation(sd, istr);
+		S32 count = LLSDSerialize::fromNotation(sd, istr, val.size());
 		ensure_equals("parser error return value", count, -1);
 		ensure("data undefined", sd.isUndefined());
 	}
@@ -1324,7 +1327,10 @@ namespace tut
 				  << "}]";
 
 		LLSD request;
-		S32 count = LLSDSerialize::fromNotation(request, stream);
+		S32 count = LLSDSerialize::fromNotation(
+			request,
+			stream,
+			stream.str().size());
 		ensure("parsed something", (count > 0));
 
 		pump_loop(request);
@@ -1425,7 +1431,10 @@ namespace tut
 		LLChannelDescriptors read_channel = buffer.nextChannel();
 		LLBufferStream read_stream(read_channel, &buffer);
 		LLSD request;
-		S32 count = LLSDSerialize::fromNotation(request, read_stream);
+		S32 count = LLSDSerialize::fromNotation(
+			request,
+			read_stream,
+			buffer.count(read_channel.in()));
 		ensure("parsed something", (count > 0));
 		ensure("deserialized", request.isDefined());
 
@@ -1487,7 +1496,10 @@ namespace tut
 		str << "{'message':'" << LLSDNotationFormatter::escapeString(message)
 			<< "'}";
 		LLSD request;
-		S32 count = LLSDSerialize::fromNotation(request, str);
+		S32 count = LLSDSerialize::fromNotation(
+			request,
+			str,
+			str.str().size());
 		ensure_equals("parse count", count, 2);
 		ensure_equals("request type", request.type(), LLSD::TypeMap);
 		pump_loop(request);
@@ -1510,7 +1522,7 @@ namespace tut
 		std::istringstream istr;
 		istr.str(val);
 		LLSD sd;
-		LLSDSerialize::fromNotation(sd, istr);
+		LLSDSerialize::fromNotation(sd, istr, val.size());
 		pump_loop(sd);
 		ensure("valid response", mResponse.isDefined());
 		ensure_equals("parsed type", mResponse.type(), LLSD::TypeMap);
-- 
cgit v1.2.3