summaryrefslogtreecommitdiff
path: root/indra/llcommon/llsd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llsd.cpp')
-rw-r--r--indra/llcommon/llsd.cpp201
1 files changed, 197 insertions, 4 deletions
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 663ceac22b..b36ff7d263 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -30,6 +30,7 @@
#include "linden_common.h"
#include "llsd.h"
+#include "llbase64.h"
#include "llerror.h"
#include "../llmath/llmath.h"
#include "llformat.h"
@@ -142,6 +143,8 @@ public:
virtual const String& asStringRef() const { static const std::string empty; return empty; }
+ virtual String asXMLRPCValue() const { return "<nil/>"; }
+
virtual bool has(const String&) const { return false; }
virtual LLSD get(const String&) const { return LLSD(); }
virtual LLSD getKeys() const { return LLSD::emptyArray(); }
@@ -222,6 +225,8 @@ namespace
virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; }
virtual LLSD::Real asReal() const { return mValue ? 1 : 0; }
virtual LLSD::String asString() const;
+
+ virtual LLSD::String asXMLRPCValue() const { return mValue ? "<boolean>1</boolean>" : "<boolean>0</boolean>"; }
};
LLSD::String ImplBoolean::asString() const
@@ -243,6 +248,8 @@ namespace
virtual LLSD::Integer asInteger() const { return mValue; }
virtual LLSD::Real asReal() const { return mValue; }
virtual LLSD::String asString() const;
+
+ virtual LLSD::String asXMLRPCValue() const { return "<int>" + std::to_string(mValue) + "</int>"; }
};
LLSD::String ImplInteger::asString() const
@@ -259,6 +266,8 @@ namespace
virtual LLSD::Integer asInteger() const;
virtual LLSD::Real asReal() const { return mValue; }
virtual LLSD::String asString() const;
+
+ virtual LLSD::String asXMLRPCValue() const { return "<double>" + std::to_string(mValue) + "</double>"; }
};
LLSD::Boolean ImplReal::asBoolean() const
@@ -286,9 +295,11 @@ namespace
virtual LLSD::URI asURI() const { return LLURI(mValue); }
virtual size_t size() const { return mValue.size(); }
virtual const LLSD::String& asStringRef() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<string>" + LLStringFn::xml_encode(mValue) + "</string>"; }
};
- LLSD::Integer ImplString::asInteger() const
+ LLSD::Integer ImplString::asInteger() const
{
// This must treat "1.23" not as an error, but as a number, which is
// then truncated down to an integer. Hence, this code doesn't call
@@ -298,7 +309,7 @@ namespace
return (int)asReal();
}
- LLSD::Real ImplString::asReal() const
+ LLSD::Real ImplString::asReal() const
{
F64 v = 0.0;
std::istringstream i_stream(mValue);
@@ -323,6 +334,8 @@ namespace
virtual LLSD::String asString() const{ return mValue.asString(); }
virtual LLSD::UUID asUUID() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<string>" + mValue.asString() + "</string>"; }
};
@@ -344,6 +357,8 @@ namespace
}
virtual LLSD::String asString() const{ return mValue.asString(); }
virtual LLSD::Date asDate() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<dateTime.iso8601>" + mValue.toHTTPDateString("%FT%T") + "</dateTime.iso8601>"; }
};
@@ -355,6 +370,8 @@ namespace
virtual LLSD::String asString() const{ return mValue.asString(); }
virtual LLSD::URI asURI() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<string>" + LLStringFn::xml_encode(mValue.asString()) + "</string>"; }
};
@@ -365,13 +382,15 @@ namespace
ImplBinary(const LLSD::Binary& v) : Base(v) { }
virtual const LLSD::Binary& asBinary() const{ return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<base64>" + LLBase64::encode(mValue.data(), mValue.size()) + "</base64>"; }
};
class ImplMap : public LLSD::Impl
{
private:
- typedef std::map<LLSD::String, LLSD> DataMap;
+ typedef std::map<LLSD::String, LLSD> DataMap;
DataMap mData;
@@ -387,6 +406,19 @@ namespace
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
+ virtual LLSD::String asXMLRPCValue() const
+ {
+ std::ostringstream os;
+ os << "<struct>";
+ for (const auto& it : mData)
+ {
+ os << "<member><name>" << LLStringFn::xml_encode(it.first) << "</name>"
+ << it.second.asXMLRPCValue() << "</member>";
+ }
+ os << "</struct>";
+ return os.str();
+ }
+
virtual bool has(const LLSD::String&) const;
using LLSD::Impl::get; // Unhiding get(size_t)
@@ -511,7 +543,7 @@ namespace
class ImplArray : public LLSD::Impl
{
private:
- typedef std::vector<LLSD> DataVector;
+ typedef std::vector<LLSD> DataVector;
DataVector mData;
@@ -527,6 +559,18 @@ namespace
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
+ virtual LLSD::String asXMLRPCValue() const
+ {
+ std::ostringstream os;
+ os << "<array><data>";
+ for (const auto& it : mData)
+ {
+ os << it.asXMLRPCValue();
+ }
+ os << "</data></array>";
+ return os.str();
+ }
+
using LLSD::Impl::get; // Unhiding get(LLSD::String)
using LLSD::Impl::erase; // Unhiding erase(LLSD::String)
using LLSD::Impl::ref; // Unhiding ref(LLSD::String)
@@ -872,6 +916,155 @@ const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); }
const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); }
+LLSD::String LLSD::asXMLRPCValue() const { return "<value>" + safe(impl).asXMLRPCValue() + "</value>"; }
+
+static bool inline check(bool condition, const char* warning_message)
+{
+ if (!condition)
+ {
+ LL_WARNS() << warning_message << LL_ENDL;
+ }
+
+ return condition;
+}
+
+static bool parseXMLRPCArrayValue(LLSD& target, LLSD::TreeNode* node)
+{
+ LLSD::TreeNode* data = node->getFirstChild();
+ if (!check(data, "No array inner XML element (<data> expected)") ||
+ !check(data->hasName("data"), "Invalid array inner XML element (<data> expected)") ||
+ !check(!data->getNextSibling(), "Multiple array inner XML elements (single <data> expected)"))
+ return false;
+
+ for (LLSD::TreeNode* item = data->getFirstChild(); item; item = item->getNextSibling())
+ {
+ LLSD value;
+ if (!value.fromXMLRPCValue(item))
+ return false;
+
+ target.append(value);
+ }
+
+ return true;
+}
+
+static bool parseXMLRPCStructValue(LLSD& target, LLSD::TreeNode* node)
+{
+ for (LLSD::TreeNode* item = node->getFirstChild(); item; item = item->getNextSibling())
+ {
+ if (!check(item->hasName("member"), "Invalid struct inner XML element (<member> expected)"))
+ return false;
+
+ std::string name;
+ LLSD value;
+ for (LLSD::TreeNode* subitem = item->getFirstChild(); subitem; subitem = subitem->getNextSibling())
+ {
+ if (subitem->hasName("name"))
+ {
+ name = LLStringFn::xml_decode(subitem->getTextContents());
+ }
+ else if (!value.fromXMLRPCValue(subitem))
+ {
+ return false;
+ }
+ }
+ if (!check(!name.empty(), "Empty struct member name"))
+ return false;
+
+ target.insert(name, value);
+ }
+
+ return true;
+}
+
+bool LLSD::fromXMLRPCValue(TreeNode* node)
+{
+ clear();
+
+ llassert(node);
+ if (!node)
+ return false;
+
+ if (!check(node->hasName("value"), "Invalid XML element (<value> expected)"))
+ return false;
+
+ TreeNode* inner = node->getFirstChild();
+ if (!inner)
+ {
+ check(false, "No inner XML element (value type expected)");
+ // Value with no type qualifier is treated as string
+ assign(LLStringFn::xml_decode(node->getTextContents()));
+ return true;
+ }
+
+ if (!check(!inner->getNextSibling(), "Multiple inner XML elements (single expected)"))
+ return false;
+
+ if (inner->hasName("string"))
+ {
+ assign(LLStringFn::xml_decode(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("int") || inner->hasName("i4"))
+ {
+ assign(std::stoi(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("double"))
+ {
+ assign(std::stod(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("boolean"))
+ {
+ assign(!!std::stoi(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("dateTime.iso8601"))
+ {
+ assign(Date(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("base64"))
+ {
+ std::string decoded = LLBase64::decodeAsString(inner->getTextContents());
+ Binary binary(decoded.size());
+ memcpy(binary.data(), decoded.data(), decoded.size());
+ assign(binary);
+ return true;
+ }
+
+ if (inner->hasName("array"))
+ {
+ if (!parseXMLRPCArrayValue(*this, inner))
+ {
+ clear();
+ return false;
+ }
+ return true;
+ }
+
+ if (inner->hasName("struct"))
+ {
+ if (!parseXMLRPCStructValue(*this, inner))
+ {
+ clear();
+ return false;
+ }
+ return true;
+ }
+
+ check(false, "Unknown inner XML element (known value type expected)");
+ // Value with unknown type qualifier is treated as string
+ assign(LLStringFn::xml_decode(inner->getTextContents()));
+ return true;
+}
+
// const char * helpers
LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
void LLSD::assign(const char* v)