From cd17687f01420952712a500107e0f93e7ab8d5f8 Mon Sep 17 00:00:00 2001
From: Jacek Antonelli
Date: Fri, 15 Aug 2008 23:45:34 -0500
Subject: Second Life viewer sources 1.19.1.0
---
linden/indra/llcommon/indra_constants.h | 4 +
linden/indra/llcommon/linden_common.h | 7 +
linden/indra/llcommon/llapp.cpp | 11 +-
linden/indra/llcommon/llapr.cpp | 8 +-
linden/indra/llcommon/llclickaction.h | 2 +
linden/indra/llcommon/llcommon_vc8.vcproj | 1618 ++++++++++++++-------------
linden/indra/llcommon/llcommon_vc9.vcproj | 1616 +++++++++++++-------------
linden/indra/llcommon/llfasttimer.h | 7 +-
linden/indra/llcommon/llfile.cpp | 28 +
linden/indra/llcommon/llfile.h | 9 +
linden/indra/llcommon/llkeythrottle.h | 5 +-
linden/indra/llcommon/lllog.cpp | 3 +-
linden/indra/llcommon/llmemory.h | 50 +-
linden/indra/llcommon/llpreprocessor.h | 27 -
linden/indra/llcommon/llsdserialize.cpp | 763 +++++++++----
linden/indra/llcommon/llsdserialize.h | 232 +++-
linden/indra/llcommon/llsdserialize_xml.cpp | 23 +-
linden/indra/llcommon/llstreamtools.cpp | 27 +-
linden/indra/llcommon/llstreamtools.h | 7 +-
linden/indra/llcommon/llsys.cpp | 3 +-
linden/indra/llcommon/llthread.cpp | 7 +
linden/indra/llcommon/llthread.h | 10 +-
linden/indra/llcommon/llversionserver.h | 6 +-
linden/indra/llcommon/llversionviewer.h | 4 +-
24 files changed, 2509 insertions(+), 1968 deletions(-)
(limited to 'linden/indra/llcommon')
diff --git a/linden/indra/llcommon/indra_constants.h b/linden/indra/llcommon/indra_constants.h
index 16e471d..eceb576 100644
--- a/linden/indra/llcommon/indra_constants.h
+++ b/linden/indra/llcommon/indra_constants.h
@@ -323,6 +323,10 @@ const U32 PARCEL_MEDIA_COMMAND_TIME = 6;
const U32 PARCEL_MEDIA_COMMAND_AGENT = 7;
const U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8;
const U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
+const U32 PARCEL_MEDIA_COMMAND_TYPE = 10;
+const U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
+const U32 PARCEL_MEDIA_COMMAND_DESC = 12;
+const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
// map item types
const U32 MAP_ITEM_TELEHUB = 0x01;
diff --git a/linden/indra/llcommon/linden_common.h b/linden/indra/llcommon/linden_common.h
index 01540c1..547cceb 100644
--- a/linden/indra/llcommon/linden_common.h
+++ b/linden/indra/llcommon/linden_common.h
@@ -58,6 +58,13 @@
#ifdef LL_WINDOWS
#pragma warning (3 : 4702) // we like level 3, not 4
+// level 4 warnings that we need to disable:
+#pragma warning (disable : 4100) // unreferenced formal parameter
+#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
+#pragma warning (disable : 4244) // possible loss of data on conversions
+#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
+#pragma warning (disable : 4512) // assignment operator could not be generated
+#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
#endif // LL_WINDOWS
// Linden only libs in alpha-order other than stdtypes.h
diff --git a/linden/indra/llcommon/llapp.cpp b/linden/indra/llcommon/llapp.cpp
index 5ae0727..a10436a 100644
--- a/linden/indra/llcommon/llapp.cpp
+++ b/linden/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/linden/indra/llcommon/llapr.cpp b/linden/indra/llcommon/llapr.cpp
index 2a81e5e..770cd3f 100644
--- a/linden/indra/llcommon/llapr.cpp
+++ b/linden/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;
ll_apr_warn_status(s);
return false;
}
@@ -306,7 +306,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;
ll_apr_warn_status(s);
return false;
}
@@ -363,7 +363,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;
ll_apr_warn_status(s);
return false;
}
@@ -377,7 +377,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;
ll_apr_warn_status(s);
return false;
}
diff --git a/linden/indra/llcommon/llclickaction.h b/linden/indra/llcommon/llclickaction.h
index 20bfbfd..b69ca15 100644
--- a/linden/indra/llcommon/llclickaction.h
+++ b/linden/indra/llcommon/llclickaction.h
@@ -39,5 +39,7 @@ const U8 CLICK_ACTION_SIT = 1;
const U8 CLICK_ACTION_BUY = 2;
const U8 CLICK_ACTION_PAY = 3;
const U8 CLICK_ACTION_OPEN = 4;
+const U8 CLICK_ACTION_PLAY = 5;
+const U8 CLICK_ACTION_OPEN_MEDIA = 6;
#endif
diff --git a/linden/indra/llcommon/llcommon_vc8.vcproj b/linden/indra/llcommon/llcommon_vc8.vcproj
index fc3060a..5578075 100644
--- a/linden/indra/llcommon/llcommon_vc8.vcproj
+++ b/linden/indra/llcommon/llcommon_vc8.vcproj
@@ -1,807 +1,811 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linden/indra/llcommon/llcommon_vc9.vcproj b/linden/indra/llcommon/llcommon_vc9.vcproj
index 752d13f..0bb2d11 100644
--- a/linden/indra/llcommon/llcommon_vc9.vcproj
+++ b/linden/indra/llcommon/llcommon_vc9.vcproj
@@ -1,808 +1,808 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/linden/indra/llcommon/llfasttimer.h b/linden/indra/llcommon/llfasttimer.h
index 3ecf176..8ad2667 100644
--- a/linden/indra/llcommon/llfasttimer.h
+++ b/linden/indra/llcommon/llfasttimer.h
@@ -62,6 +62,7 @@ public:
FTM_SIMULATE_PARTICLES,
FTM_UPDATE_SKY,
FTM_UPDATE_TEXTURES,
+ FTM_UPDATE_WLPARAM,
FTM_UPDATE_WATER,
FTM_UPDATE_CLOUDS,
FTM_UPDATE_GRASS,
@@ -86,8 +87,12 @@ public:
FTM_RENDER_HUD,
FTM_RENDER_PARTICLES,
FTM_RENDER_WATER,
+ FTM_RENDER_WL_SKY,
+ FTM_RENDER_FAKE_VBO_UPDATE,
FTM_RENDER_TIMER,
FTM_RENDER_UI,
+ FTM_RENDER_BLOOM,
+ FTM_RENDER_BLOOM_FBO,
FTM_RENDER_FONTS,
// newview specific
@@ -124,6 +129,7 @@ public:
FTM_GEO_RESERVE,
FTM_GEO_LIGHT,
FTM_GEO_SHADOW,
+ FTM_GEO_SKY,
FTM_GEN_VOLUME,
FTM_GEN_TRIANGLES,
FTM_GEN_FLEX,
@@ -150,7 +156,6 @@ public:
FTM_PIPELINE,
FTM_VFILE_WAIT,
FTM_FLEXIBLE_UPDATE,
- FTM_OCCLUSION,
FTM_OCCLUSION_READBACK,
FTM_HUD_EFFECTS,
FTM_HUD_UPDATE,
diff --git a/linden/indra/llcommon/llfile.cpp b/linden/indra/llcommon/llfile.cpp
index 38157df..6ccf6ac 100644
--- a/linden/indra/llcommon/llfile.cpp
+++ b/linden/indra/llcommon/llfile.cpp
@@ -286,8 +286,36 @@ llofstream::llofstream(const char *_Filename,
llofstream::~llofstream()
{ // destroy the object
+ close();
delete _Filebuffer;
}
#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/linden/indra/llcommon/llfile.h b/linden/indra/llcommon/llfile.h
index 062b183..2650775 100644
--- a/linden/indra/llcommon/llfile.h
+++ b/linden/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/linden/indra/llcommon/llkeythrottle.h b/linden/indra/llcommon/llkeythrottle.h
index c2dc9d2..8314269 100644
--- a/linden/indra/llcommon/llkeythrottle.h
+++ b/linden/indra/llcommon/llkeythrottle.h
@@ -192,10 +192,7 @@ public:
{
noteAction(id);
typename LLKeyThrottleImpl::Entry& curr = (*m.currMap)[id];
- if (curr.count < m.countLimit)
- {
- curr.count = m.countLimit;
- }
+ curr.count = llmax(m.countLimit, curr.count);
curr.blocked = TRUE;
}
diff --git a/linden/indra/llcommon/lllog.cpp b/linden/indra/llcommon/lllog.cpp
index 147b2d3..10f7c00 100644
--- a/linden/indra/llcommon/lllog.cpp
+++ b/linden/indra/llcommon/lllog.cpp
@@ -69,7 +69,8 @@ void LLLogImpl::log(const std::string message, LLSD& info)
}
}
}
- llinfos << "LLLOGMESSAGE (" << (sequence++) << ") " << message << " " << LLSDNotationStreamer(info) << llendl;
+ llinfos << "LLLOGMESSAGE (" << (sequence++) << ") " << message
+ << " " << LLSDNotationStreamer(info) << llendl;
}
//@brief Function to check if specified legacy log message should be sent.
diff --git a/linden/indra/llcommon/llmemory.h b/linden/indra/llcommon/llmemory.h
index 8a3ca0b..e1af7ba 100644
--- a/linden/indra/llcommon/llmemory.h
+++ b/linden/indra/llcommon/llmemory.h
@@ -243,25 +243,25 @@ protected:
// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
// This is useful in instances where operations on NULL pointers are semantically safe and/or
// when error checking occurs at a different granularity or in a different part of the code
-// than when referencing an object via a LLHandle.
+// than when referencing an object via a LLSafeHandle.
//
template
-class LLHandle
+class LLSafeHandle
{
public:
- LLHandle() :
+ LLSafeHandle() :
mPointer(NULL)
{
}
- LLHandle(Type* ptr) :
+ LLSafeHandle(Type* ptr) :
mPointer(NULL)
{
assign(ptr);
}
- LLHandle(const LLHandle& ptr) :
+ LLSafeHandle(const LLSafeHandle& ptr) :
mPointer(NULL)
{
assign(ptr.mPointer);
@@ -269,13 +269,13 @@ public:
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template
- LLHandle(const LLHandle& ptr) :
+ LLSafeHandle(const LLSafeHandle& ptr) :
mPointer(NULL)
{
assign(ptr.get());
}
- ~LLHandle()
+ ~LLSafeHandle()
{
unref();
}
@@ -300,17 +300,17 @@ public:
operator const Type*() const { return mPointer; }
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
- bool operator ==(const LLHandle& ptr) const { return (mPointer == ptr.mPointer); }
- bool operator < (const LLHandle& ptr) const { return (mPointer < ptr.mPointer); }
- bool operator > (const LLHandle& ptr) const { return (mPointer > ptr.mPointer); }
+ bool operator ==(const LLSafeHandle& ptr) const { return (mPointer == ptr.mPointer); }
+ bool operator < (const LLSafeHandle& ptr) const { return (mPointer < ptr.mPointer); }
+ bool operator > (const LLSafeHandle& ptr) const { return (mPointer > ptr.mPointer); }
- LLHandle& operator =(Type* ptr)
+ LLSafeHandle& operator =(Type* ptr)
{
assign(ptr);
return *this;
}
- LLHandle& operator =(const LLHandle& ptr)
+ LLSafeHandle& operator =(const LLSafeHandle& ptr)
{
assign(ptr.mPointer);
return *this;
@@ -318,7 +318,7 @@ public:
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template
- LLHandle& operator =(const LLHandle& ptr)
+ LLSafeHandle& operator =(const LLSafeHandle& ptr)
{
assign(ptr.get());
return *this;
@@ -399,11 +399,25 @@ protected:
//----------------------------------------------------------------------------
-// LLSingleton implements the getInstance() method part of the Singleton pattern. It can't make
-// the derived class constructors protected, though, so you have to do that yourself.
-// The proper way to use LLSingleton is to inherit from it while using the typename that you'd
-// like to be static as the template parameter, like so:
-// class FooBar: public LLSingleton
+// LLSingleton implements the getInstance() method part of the Singleton
+// pattern. It can't make the derived class constructors protected, though, so
+// you have to do that yourself.
+//
+// There are two ways to use LLSingleton. The first way is to inherit from it
+// while using the typename that you'd like to be static as the template
+// parameter, like so:
+//
+// class Foo: public LLSingleton{};
+//
+// Foo* instance = Foo::getInstance();
+//
+// The second way is to define a seperate class that exposes the singleton
+// interface:
+//
+// class FooSingleton: public LLSingleton{};
+//
+// Foo* instance = FooSingleton::getInstance();
+//
// As currently written, it is not thread-safe.
template
class LLSingleton
diff --git a/linden/indra/llcommon/llpreprocessor.h b/linden/indra/llcommon/llpreprocessor.h
index 8bcad34..8d38904 100644
--- a/linden/indra/llcommon/llpreprocessor.h
+++ b/linden/indra/llcommon/llpreprocessor.h
@@ -52,33 +52,6 @@
#define LL_FORCE_INLINE __forceinline
#endif
-// Per-OS feature switches.
-
-#if LL_DARWIN
- #define LL_QUICKTIME_ENABLED 1
- #define LL_LIBXUL_ENABLED 1
-#elif LL_WINDOWS
- #define LL_QUICKTIME_ENABLED 1
- #define LL_LIBXUL_ENABLED 1
-#elif LL_LINUX
- #define LL_QUICKTIME_ENABLED 0
- #ifndef LL_LIBXUL_ENABLED
- #define LL_LIBXUL_ENABLED 1
- #endif // def LL_LIBXUL_ENABLED
-#elif LL_SOLARIS
- #define LL_QUICKTIME_ENABLED 0
- #ifndef LL_LIBXUL_ENABLED
- #define LL_LIBXUL_ENABLED 0
- #endif // def LL_LIBXUL_ENABLED
-#endif
-
-#if LL_LIBXUL_ENABLED && !defined(MOZILLA_INTERNAL_API)
- // Without this, nsTAString.h errors out with:
- // "Cannot use internal string classes without MOZILLA_INTERNAL_API defined. Use the frozen header nsStringAPI.h instead."
- // It might be worth our while to figure out if we can use the frozen apis at some point...
- #define MOZILLA_INTERNAL_API 1
-#endif
-
// Figure out differences between compilers
#if defined(__GNUC__)
#define GCC_VERSION (__GNUC__ * 10000 \
diff --git a/linden/indra/llcommon/llsdserialize.cpp b/linden/indra/llcommon/llsdserialize.cpp
index 7813cf0..a556d5d 100644
--- a/linden/indra/llcommon/llsdserialize.cpp
+++ b/linden/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[] = "";
+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 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,71 @@ 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. Passing in
+ * a negative value will skip this check.
+ * @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. Passing in
+ * a negative value will skip this check.
+ * @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 +296,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 +403,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 +415,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 +558,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 +705,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 +762,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(mCheckLimits && (len > mMaxBytesLeft)) return false;
std::vector 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 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 +810,14 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
U8 byte_buffer[BINARY_BUFFER_SIZE];
U8* write;
std::vector 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 +832,9 @@ void LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
}
else
{
- data.clear();
+ return false;
}
+ return true;
}
@@ -666,7 +851,7 @@ LLSDBinaryParser::~LLSDBinaryParser()
}
// virtual
-S32 LLSDBinaryParser::parse(std::istream& istr, LLSD& data) const
+S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
{
/**
* Undefined: '!'
@@ -685,7 +870,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 +879,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 +931,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 +943,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 +955,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 +968,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 +1009,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 +1028,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 +1042,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 value;
- if(size)
+ if(mCheckLimits && (size > mMaxBytesLeft))
{
- value.resize(size);
- istr.read((char*)&value[0], size); /*Flawfinder: ignore*/
+ parse_count = PARSE_FAILURE;
+ }
+ else
+ {
+ std::vector 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 +1138,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 +1150,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 +1163,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(mCheckLimits && (size > mMaxBytesLeft)) return false;
std::vector 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 +1487,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 +1527,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 +1615,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((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
std::vector 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 +1931,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/linden/indra/llcommon/llsdserialize.h b/linden/indra/llcommon/llsdserialize.h
index e1e81d5..41e0aa5 100644
--- a/linden/indra/llcommon/llsdserialize.h
+++ b/linden/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 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 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 p = new LLSDNotationParser;
+ return p->parse(str, sd, max_bytes);
+ }
+ static LLSD fromNotation(std::istream& str, S32 max_bytes)
{
LLPointer 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 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 p = new LLSDXMLParser;
- return p->parse(str, sd);
+ return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED);
}
/*
@@ -602,14 +734,18 @@ public:
LLPointer 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 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 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/linden/indra/llcommon/llsdserialize_xml.cpp b/linden/indra/llcommon/llsdserialize_xml.cpp
index b8adcf1..7de0c35 100644
--- a/linden/indra/llcommon/llsdserialize_xml.cpp
+++ b/linden/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/linden/indra/llcommon/llstreamtools.cpp b/linden/indra/llcommon/llstreamtools.cpp
index 5419b24..669bdd0 100644
--- a/linden/indra/llcommon/llstreamtools.cpp
+++ b/linden/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/linden/indra/llcommon/llstreamtools.h b/linden/indra/llcommon/llstreamtools.h
index 0114e4c..9db90c8 100644
--- a/linden/indra/llcommon/llstreamtools.h
+++ b/linden/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/linden/indra/llcommon/llsys.cpp b/linden/indra/llcommon/llsys.cpp
index 2a6e466..ccdcd00 100644
--- a/linden/indra/llcommon/llsys.cpp
+++ b/linden/indra/llcommon/llsys.cpp
@@ -679,7 +679,8 @@ BOOL gunzip_file(const char *srcfile, const char *dstfile)
size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
if (nwrit < (size_t) bytes)
{
- llerrs << "Short write on " << tmpfile << llendl;
+ llwarns << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << llendl;
+ goto err;
}
} while(gzeof(src) == 0);
fclose(dst);
diff --git a/linden/indra/llcommon/llthread.cpp b/linden/indra/llcommon/llthread.cpp
index c0e92ca..48ebc4b 100644
--- a/linden/indra/llcommon/llthread.cpp
+++ b/linden/indra/llcommon/llthread.cpp
@@ -31,6 +31,8 @@
#include "linden_common.h"
#include "llapr.h"
+#include "apr-1/apr_portable.h"
+
#include "llthread.h"
#include "lltimer.h"
@@ -225,6 +227,11 @@ void LLThread::setQuitting()
wake();
}
+// static
+U32 LLThread::currentID()
+{
+ return (U32)apr_os_thread_current();
+}
// static
void LLThread::yield()
diff --git a/linden/indra/llcommon/llthread.h b/linden/indra/llcommon/llthread.h
index 5c71c34..608b218 100644
--- a/linden/indra/llcommon/llthread.h
+++ b/linden/indra/llcommon/llthread.h
@@ -56,14 +56,14 @@ public:
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
virtual void shutdown(); // stops the thread
- static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
-
-
bool isQuitting() const { return (QUITTING == mStatus); }
bool isStopped() const { return (STOPPED == mStatus); }
- // PAUSE / RESUME functionality. See source code for important usage notes.
+ static U32 currentID(); // Return ID of current thread
+ static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
+
public:
+ // PAUSE / RESUME functionality. See source code for important usage notes.
// Called from MAIN THREAD.
void pause();
void unpause();
@@ -127,7 +127,7 @@ protected:
class LLMutex
{
public:
- LLMutex(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
+ LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
~LLMutex();
void lock(); // blocks
diff --git a/linden/indra/llcommon/llversionserver.h b/linden/indra/llcommon/llversionserver.h
index 079fa85..922e4ac 100644
--- a/linden/indra/llcommon/llversionserver.h
+++ b/linden/indra/llcommon/llversionserver.h
@@ -33,9 +33,9 @@
#define LL_LLVERSIONSERVER_H
const S32 LL_VERSION_MAJOR = 1;
-const S32 LL_VERSION_MINOR = 18;
-const S32 LL_VERSION_PATCH = 6;
-const S32 LL_VERSION_BUILD = 76747;
+const S32 LL_VERSION_MINOR = 19;
+const S32 LL_VERSION_PATCH = 1;
+const S32 LL_VERSION_BUILD = 80913;
const char * const LL_CHANNEL = "Second Life Server";
diff --git a/linden/indra/llcommon/llversionviewer.h b/linden/indra/llcommon/llversionviewer.h
index c14efe8..c1e6778 100644
--- a/linden/indra/llcommon/llversionviewer.h
+++ b/linden/indra/llcommon/llversionviewer.h
@@ -34,8 +34,8 @@
const S32 LL_VERSION_MAJOR = 1;
const S32 LL_VERSION_MINOR = 19;
-const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 5;
+const S32 LL_VERSION_PATCH = 1;
+const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Release";
--
cgit v1.1