summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorJosh Bell <josh@lindenlab.com>2008-02-07 17:15:18 +0000
committerJosh Bell <josh@lindenlab.com>2008-02-07 17:15:18 +0000
commit8bd6a0b3217ea5614d2a29195e528aa8314f6342 (patch)
treebe5cee5be0678bb03c7174bab9296cfc530d0102 /indra
parent3314f78a3673c1250e47722848c60d017dafac97 (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
Diffstat (limited to 'indra')
-rw-r--r--indra/lib/python/indra/ipc/russ.py10
-rw-r--r--indra/llcommon/llapp.cpp11
-rw-r--r--indra/llcommon/llapr.cpp8
-rw-r--r--indra/llcommon/llfile.cpp27
-rw-r--r--indra/llcommon/llfile.h9
-rw-r--r--indra/llcommon/llsdserialize.cpp761
-rw-r--r--indra/llcommon/llsdserialize.h232
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp23
-rw-r--r--indra/llcommon/llstreamtools.cpp27
-rw-r--r--indra/llcommon/llstreamtools.h7
-rwxr-xr-xindra/llcrashlogger/llcrashlogger.cpp6
-rw-r--r--indra/llmessage/llbuffer.h12
-rw-r--r--indra/llmessage/llfiltersd2xmlrpc.cpp4
-rw-r--r--indra/llmessage/llhttpclient.cpp12
-rw-r--r--indra/llmessage/llhttpclient.h17
-rw-r--r--indra/llmessage/lliohttpserver.cpp6
-rw-r--r--indra/llmessage/llsdrpcclient.cpp2
-rw-r--r--indra/llmessage/llsdrpcserver.cpp5
-rw-r--r--indra/llmessage/llservicebuilder.cpp58
-rw-r--r--indra/newview/llappviewer.cpp27
-rw-r--r--indra/newview/llfloatersnapshot.cpp2
-rw-r--r--indra/newview/llpreview.cpp1
-rw-r--r--indra/newview/llstartup.cpp18
-rw-r--r--indra/newview/llviewermessage.cpp4
-rw-r--r--indra/newview/llviewertexteditor.cpp58
-rw-r--r--indra/newview/llviewertexteditor.h5
-rw-r--r--indra/test/io.cpp30
27 files changed, 981 insertions, 401 deletions
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);