diff options
| author | Josh Bell <josh@lindenlab.com> | 2008-02-07 17:15:18 +0000 | 
|---|---|---|
| committer | Josh Bell <josh@lindenlab.com> | 2008-02-07 17:15:18 +0000 | 
| commit | 8bd6a0b3217ea5614d2a29195e528aa8314f6342 (patch) | |
| tree | be5cee5be0678bb03c7174bab9296cfc530d0102 | |
| parent | 3314f78a3673c1250e47722848c60d017dafac97 (diff) | |
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
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  { @@ -52,6 +52,14 @@ protected:  public:  	/**  +	 * @brief Anonymous enum to indicate parsing failure. +	 */ +	enum +	{ +		PARSE_FAILURE = -1 +	}; + +	/**   	 * @brief Constructor  	 */  	LLSDParser(); @@ -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 @@ -411,6 +411,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  	 *  	 * You should prefer iterating over segments is possible since 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); | 
