summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKartic Krishnamurthy <drunkensufi@lindenlab.com>2008-09-16 18:12:32 +0000
committerKartic Krishnamurthy <drunkensufi@lindenlab.com>2008-09-16 18:12:32 +0000
commit80f61963272cc2311c5410671045e34212476134 (patch)
tree2d913b7bc78c60a4e0755b0667d86a32b42fe467
parent96869c0de45c20949ede6deeb4e8f954b7b209ca (diff)
QAR-751 : Merge Agent Inventory Services - Fetch Inventory and Fetch Inventory Descendents - to Release
Related Jiras: 1. DEV-17797 New Top Causes of Inventory Loss is Attachments with null folder_id 2. DEV-17937 null asset id not handled correctly in ais inventory fetch 3. OPSRT-1097 Update python-indra package on the system images 4. DEV-20505 QAR-751: Banning Cap "FetchLibDescendents" results in error in viewer log. 5. DEV-20328 QAR-751 Excessive log spam when using ais viewer against ais sim 6. DEV-20335 QAR-751 AIS bans are missing from message.xml svn merge -r95983:96590 svn+ssh://svn/svn/linden/branches/ais-for-merge-qar-751 . Miscellaneous commit: 1. Fixed silly bug in llsd-rest that broke connects to https on a non-standard port
-rw-r--r--indra/lib/python/indra/base/llsd.py142
-rw-r--r--indra/lib/python/indra/util/fastest_elementtree.py29
-rw-r--r--indra/llcommon/indra_constants.h1
-rw-r--r--indra/llinventory/llinventory.cpp43
-rw-r--r--indra/llinventory/llsaleinfo.cpp11
-rw-r--r--indra/llmessage/llpumpio.cpp18
-rw-r--r--indra/llmessage/llpumpio.h9
-rw-r--r--indra/llmessage/llurlrequest.cpp23
-rw-r--r--indra/newview/llinventorymodel.cpp393
-rw-r--r--indra/newview/llinventorymodel.h18
-rw-r--r--indra/newview/llstartup.cpp3
-rw-r--r--indra/newview/llviewerinventory.cpp41
-rw-r--r--indra/newview/llviewerregion.cpp5
13 files changed, 562 insertions, 174 deletions
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index c841cdaf63..521b79c65a 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -4,7 +4,7 @@
$LicenseInfo:firstyear=2006&license=mit$
-Copyright (c) 2006-2007, Linden Research, Inc.
+Copyright (c) 2006-2008, Linden Research, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -33,19 +33,26 @@ import time
import types
import re
-from indra.util.fastest_elementtree import fromstring
+from indra.util.fastest_elementtree import ElementTreeError, fromstring
from indra.base import lluuid
-int_regex = re.compile("[-+]?\d+")
-real_regex = re.compile("[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?")
-alpha_regex = re.compile("[a-zA-Z]+")
-date_regex = re.compile("(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})(?P<second_float>\.\d{2})?Z")
+try:
+ import cllsd
+except ImportError:
+ cllsd = None
+
+int_regex = re.compile(r"[-+]?\d+")
+real_regex = re.compile(r"[-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?")
+alpha_regex = re.compile(r"[a-zA-Z]+")
+date_regex = re.compile(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T"
+ r"(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})"
+ r"(?P<second_float>(\.\d+)?)Z")
#date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
class LLSDParseError(Exception):
pass
-class LLSDSerializationError(Exception):
+class LLSDSerializationError(TypeError):
pass
@@ -64,7 +71,7 @@ def format_datestr(v):
""" Formats a datetime object into the string format shared by xml and notation serializations."""
second_str = ""
if v.microsecond > 0:
- seconds = v.second + float(v.microsecond) / 1000000
+ seconds = v.second + float(v.microsecond) / 1e6
second_str = "%05.2f" % seconds
else:
second_str = "%02d" % v.second
@@ -89,7 +96,7 @@ def parse_datestr(datestr):
seconds_float = match.group('second_float')
microsecond = 0
if seconds_float:
- microsecond = int(seconds_float[1:]) * 10000
+ microsecond = int(float('0' + seconds_float) * 1e6)
return datetime.datetime(year, month, day, hour, minute, second, microsecond)
@@ -116,7 +123,7 @@ def uuid_to_python(node):
return lluuid.UUID(node.text)
def str_to_python(node):
- return unicode(node.text or '').encode('utf8', 'replace')
+ return node.text or ''
def bin_to_python(node):
return binary(base64.decodestring(node.text or ''))
@@ -189,9 +196,13 @@ class LLSDXMLFormatter(object):
if(contents is None or contents is ''):
return "<%s />" % (name,)
else:
+ if type(contents) is unicode:
+ contents = contents.encode('utf-8')
return "<%s>%s</%s>" % (name, contents, name)
def xml_esc(self, v):
+ if type(v) is unicode:
+ v = v.encode('utf-8')
return v.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
def LLSD(self, v):
@@ -237,9 +248,14 @@ class LLSDXMLFormatter(object):
raise LLSDSerializationError("Cannot serialize unknown type: %s (%s)" % (
t, something))
- def format(self, something):
+ def _format(self, something):
return '<?xml version="1.0" ?>' + self.elt("llsd", self.generate(something))
+ def format(self, something):
+ if cllsd:
+ return cllsd.llsd_to_xml(something)
+ return self._format(something)
+
_g_xml_formatter = None
def format_xml(something):
global _g_xml_formatter
@@ -356,8 +372,10 @@ class LLSDNotationFormatter(object):
def UUID(self, v):
return "u%s" % v
def BINARY(self, v):
- raise LLSDSerializationError("binary notation not yet supported")
+ return 'b64"' + base64.encodestring(v) + '"'
def STRING(self, v):
+ if isinstance(v, unicode):
+ v = v.encode('utf-8')
return "'%s'" % v.replace("\\", "\\\\").replace("'", "\\'")
def URI(self, v):
return 'l"%s"' % str(v).replace("\\", "\\\\").replace('"', '\\"')
@@ -366,16 +384,24 @@ class LLSDNotationFormatter(object):
def ARRAY(self, v):
return "[%s]" % ','.join([self.generate(item) for item in v])
def MAP(self, v):
- return "{%s}" % ','.join(["'%s':%s" % (key.replace("\\", "\\\\").replace("'", "\\'"), self.generate(value))
+ def fix(key):
+ if isinstance(key, unicode):
+ return key.encode('utf-8')
+ return key
+ return "{%s}" % ','.join(["'%s':%s" % (fix(key).replace("\\", "\\\\").replace("'", "\\'"), self.generate(value))
for key, value in v.items()])
def generate(self, something):
t = type(something)
- if self.type_map.has_key(t):
- return self.type_map[t](something)
+ handler = self.type_map.get(t)
+ if handler:
+ return handler(something)
else:
- raise LLSDSerializationError("Cannot serialize unknown type: %s (%s)" % (
- t, something))
+ try:
+ return self.ARRAY(iter(something))
+ except TypeError:
+ raise LLSDSerializationError(
+ "Cannot serialize unknown type: %s (%s)" % (t, something))
def format(self, something):
return self.generate(something)
@@ -479,7 +505,6 @@ class LLSDBinaryParser(object):
raise LLSDParseError("invalid map key at byte %d." % (
self._index - 1,))
value = self._parse()
- #print "kv:",key,value
rv[key] = value
count += 1
cc = self._buffer[self._index]
@@ -636,11 +661,23 @@ class LLSDNotationParser(object):
# 'd' = date in seconds since epoch
return self._parse_date()
elif cc == 'b':
- raise LLSDParseError("binary notation not yet supported")
+ return self._parse_binary()
else:
raise LLSDParseError("invalid token at index %d: %d" % (
self._index - 1, ord(cc)))
+ def _parse_binary(self):
+ i = self._index
+ if self._buffer[i:i+2] == '64':
+ q = self._buffer[i+2]
+ e = self._buffer.find(q, i+3)
+ try:
+ return base64.decodestring(self._buffer[i+3:e])
+ finally:
+ self._index = e + 1
+ else:
+ raise LLSDParseError('random horrible binary format not supported')
+
def _parse_map(self):
""" map: { string:object, string:object } """
rv = {}
@@ -653,30 +690,23 @@ class LLSDNotationParser(object):
if cc in ("'", '"', 's'):
key = self._parse_string(cc)
found_key = True
- #print "key:",key
elif cc.isspace() or cc == ',':
cc = self._buffer[self._index]
self._index += 1
else:
raise LLSDParseError("invalid map key at byte %d." % (
self._index - 1,))
+ elif cc.isspace() or cc == ':':
+ cc = self._buffer[self._index]
+ self._index += 1
+ continue
else:
- if cc.isspace() or cc == ':':
- #print "skipping whitespace '%s'" % cc
- cc = self._buffer[self._index]
- self._index += 1
- continue
self._index += 1
value = self._parse()
- #print "kv:",key,value
rv[key] = value
found_key = False
cc = self._buffer[self._index]
self._index += 1
- #if cc == '}':
- # break
- #cc = self._buffer[self._index]
- #self._index += 1
return rv
@@ -840,6 +870,14 @@ def format_binary(something):
return '<?llsd/binary?>\n' + _format_binary_recurse(something)
def _format_binary_recurse(something):
+ def _format_list(something):
+ array_builder = []
+ array_builder.append('[' + struct.pack('!i', len(something)))
+ for item in something:
+ array_builder.append(_format_binary_recurse(item))
+ array_builder.append(']')
+ return ''.join(array_builder)
+
if something is None:
return '!'
elif isinstance(something, LLSD):
@@ -857,7 +895,10 @@ def _format_binary_recurse(something):
return 'u' + something._bits
elif isinstance(something, binary):
return 'b' + struct.pack('!i', len(something)) + something
- elif isinstance(something, (str, unicode)):
+ elif isinstance(something, str):
+ return 's' + struct.pack('!i', len(something)) + something
+ elif isinstance(something, unicode):
+ something = something.encode('utf-8')
return 's' + struct.pack('!i', len(something)) + something
elif isinstance(something, uri):
return 'l' + struct.pack('!i', len(something)) + something
@@ -865,35 +906,50 @@ def _format_binary_recurse(something):
seconds_since_epoch = time.mktime(something.timetuple())
return 'd' + struct.pack('!d', seconds_since_epoch)
elif isinstance(something, (list, tuple)):
- array_builder = []
- array_builder.append('[' + struct.pack('!i', len(something)))
- for item in something:
- array_builder.append(_format_binary_recurse(item))
- array_builder.append(']')
- return ''.join(array_builder)
+ return _format_list(something)
elif isinstance(something, dict):
map_builder = []
map_builder.append('{' + struct.pack('!i', len(something)))
for key, value in something.items():
+ if isinstance(key, unicode):
+ key = key.encode('utf-8')
map_builder.append('k' + struct.pack('!i', len(key)) + key)
map_builder.append(_format_binary_recurse(value))
map_builder.append('}')
return ''.join(map_builder)
else:
- raise LLSDSerializationError("Cannot serialize unknown type: %s (%s)" % (
- type(something), something))
+ try:
+ return _format_list(list(something))
+ except TypeError:
+ raise LLSDSerializationError(
+ "Cannot serialize unknown type: %s (%s)" %
+ (type(something), something))
+
+
+def parse_binary(something):
+ header = '<?llsd/binary?>\n'
+ if not something.startswith(header):
+ raise LLSDParseError('LLSD binary encoding header not found')
+ return LLSDBinaryParser().parse(something[len(header):])
+
+def parse_xml(something):
+ try:
+ return to_python(fromstring(something)[0])
+ except ElementTreeError, err:
+ raise LLSDParseError(*err.args)
+def parse_notation(something):
+ return LLSDNotationParser().parse(something)
def parse(something):
try:
if something.startswith('<?llsd/binary?>'):
- just_binary = something.split('\n', 1)[1]
- return LLSDBinaryParser().parse(just_binary)
+ return parse_binary(something)
# This should be better.
elif something.startswith('<'):
- return to_python(fromstring(something)[0])
+ return parse_xml(something)
else:
- return LLSDNotationParser().parse(something)
+ return parse_notation(something)
except KeyError, e:
raise Exception('LLSD could not be parsed: %s' % (e,))
diff --git a/indra/lib/python/indra/util/fastest_elementtree.py b/indra/lib/python/indra/util/fastest_elementtree.py
index 228be49ed3..24701438f0 100644
--- a/indra/lib/python/indra/util/fastest_elementtree.py
+++ b/indra/lib/python/indra/util/fastest_elementtree.py
@@ -2,9 +2,9 @@
@file fastest_elementtree.py
@brief Concealing some gnarly import logic in here. This should export the interface of elementtree.
-$LicenseInfo:firstyear=2006&license=mit$
+$LicenseInfo:firstyear=2008&license=mit$
-Copyright (c) 2006-2007, Linden Research, Inc.
+Copyright (c) 2008, Linden Research, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -26,25 +26,40 @@ THE SOFTWARE.
$/LicenseInfo$
"""
-# Using celementree might cause some unforeseen problems so here's a
+# The parsing exception raised by the underlying library depends
+# on the ElementTree implementation we're using, so we provide an
+# alias here.
+#
+# Use ElementTreeError as the exception type for catching parsing
+# errors.
+
+
+# Using cElementTree might cause some unforeseen problems, so here's a
# convenient off switch.
+
use_celementree = True
try:
if not use_celementree:
raise ImportError()
- from cElementTree import * ## This does not work under Windows
+ # Python 2.3 and 2.4.
+ from cElementTree import *
+ ElementTreeError = SyntaxError
except ImportError:
try:
if not use_celementree:
raise ImportError()
- ## This is the name of cElementTree under python 2.5
+ # Python 2.5 and above.
from xml.etree.cElementTree import *
+ ElementTreeError = SyntaxError
except ImportError:
+ # Pure Python code.
try:
- ## This is the old name of elementtree, for use with 2.3
+ # Python 2.3 and 2.4.
from elementtree.ElementTree import *
except ImportError:
- ## This is the name of elementtree under python 2.5
+ # Python 2.5 and above.
from xml.etree.ElementTree import *
+ # The pure Python ElementTree module uses Expat for parsing.
+ from xml.parsers.expat import ExpatError as ElementTreeError
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index e83da12beb..a3e3aec360 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -251,6 +251,7 @@ const U8 GOD_NOT = 0;
const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb");
// Governor Linden's agent id.
+const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f");
const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
// Maintenance's group id.
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 0cdc445069..a126ae4fbf 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -60,6 +60,9 @@ static const std::string INV_SALE_INFO_LABEL("sale_info");
static const std::string INV_FLAGS_LABEL("flags");
static const std::string INV_CREATION_DATE_LABEL("created_at");
+// key used by agent-inventory-service
+static const std::string INV_ASSET_TYPE_LABEL_WS("type_default");
+static const std::string INV_FOLDER_ID_LABEL_WS("category_id");
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
@@ -949,11 +952,13 @@ LLSD LLInventoryItem::asLLSD() const
sd[INV_SHADOW_ID_LABEL] = shadow_id;
}
sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
+ sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
if(inv_type_str)
{
sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
}
+ //sd[INV_FLAGS_LABEL] = (S32)mFlags;
sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags);
sd[INV_SALE_INFO_LABEL] = mSaleInfo;
sd[INV_NAME_LABEL] = mName;
@@ -1026,17 +1031,40 @@ bool LLInventoryItem::fromLLSD(LLSD& sd)
w = INV_ASSET_TYPE_LABEL;
if (sd.has(w))
{
- mType = LLAssetType::lookup(sd[w].asString());
+ if (sd[w].isString())
+ {
+ mType = LLAssetType::lookup(sd[w].asString().c_str());
+ }
+ else if (sd[w].isInteger())
+ {
+ S8 type = (U8)sd[w].asInteger();
+ mType = static_cast<LLAssetType::EType>(type);
+ }
}
w = INV_INVENTORY_TYPE_LABEL;
if (sd.has(w))
{
- mInventoryType = LLInventoryType::lookup(sd[w].asString());
+ if (sd[w].isString())
+ {
+ mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str());
+ }
+ else if (sd[w].isInteger())
+ {
+ S8 type = (U8)sd[w].asInteger();
+ mInventoryType = static_cast<LLInventoryType::EType>(type);
+ }
}
w = INV_FLAGS_LABEL;
if (sd.has(w))
{
- mFlags = ll_U32_from_sd(sd[w]);
+ if (sd[w].isBinary())
+ {
+ mFlags = ll_U32_from_sd(sd[w]);
+ }
+ else if(sd[w].isInteger())
+ {
+ mFlags = sd[w].asInteger();
+ }
}
w = INV_NAME_LABEL;
if (sd.has(w))
@@ -1394,7 +1422,7 @@ bool LLInventoryCategory::fromLLSD(LLSD& sd)
{
std::string w;
- w = INV_ITEM_ID_LABEL;
+ w = INV_FOLDER_ID_LABEL_WS;
if (sd.has(w))
{
mUUID = sd[w];
@@ -1410,6 +1438,13 @@ bool LLInventoryCategory::fromLLSD(LLSD& sd)
S8 type = (U8)sd[w].asInteger();
mPreferredType = static_cast<LLAssetType::EType>(type);
}
+ w = INV_ASSET_TYPE_LABEL_WS;
+ if (sd.has(w))
+ {
+ S8 type = (U8)sd[w].asInteger();
+ mPreferredType = static_cast<LLAssetType::EType>(type);
+ }
+
w = INV_NAME_LABEL;
if (sd.has(w))
{
diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp
index 111167ae27..9c36f0b7a0 100644
--- a/indra/llinventory/llsaleinfo.cpp
+++ b/indra/llinventory/llsaleinfo.cpp
@@ -114,7 +114,16 @@ bool LLSaleInfo::fromLLSD(LLSD& sd, BOOL& has_perm_mask, U32& perm_mask)
{
const char *w;
- mSaleType = lookup(sd["sale_type"].asString().c_str());
+ if (sd["sale_type"].isString())
+ {
+ mSaleType = lookup(sd["sale_type"].asString().c_str());
+ }
+ else if(sd["sale_type"].isInteger())
+ {
+ S8 type = (U8)sd["sale_type"].asInteger();
+ mSaleType = static_cast<LLSaleInfo::EForSale>(type);
+ }
+
mSalePrice = llclamp(sd["sale_price"].asInteger(), 0, S32_MAX);
w = "perm_mask";
if (sd.has(w))
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 503ca947df..284a7141d0 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -269,6 +269,13 @@ bool LLPumpIO::setTimeoutSeconds(F32 timeout)
return true;
}
+void LLPumpIO::adjustTimeoutSeconds(F32 delta)
+{
+ // If no chain is running, bail
+ if(current_chain_t() == mCurrentChain) return;
+ (*mCurrentChain).adjustTimeoutSeconds(delta);
+}
+
static std::string events_2_string(apr_int16_t events)
{
std::ostringstream ostr;
@@ -1161,3 +1168,14 @@ void LLPumpIO::LLChainInfo::setTimeoutSeconds(F32 timeout)
mTimer.stop();
}
}
+
+void LLPumpIO::LLChainInfo::adjustTimeoutSeconds(F32 delta)
+{
+ LLMemType m1(LLMemType::MTYPE_IO_PUMP);
+ if(mTimer.getStarted())
+ {
+ F64 expiry = mTimer.expiresAt();
+ expiry += delta;
+ mTimer.setExpiryAt(expiry);
+ }
+}
diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h
index fe7012ad6c..2a02bad89e 100644
--- a/indra/llmessage/llpumpio.h
+++ b/indra/llmessage/llpumpio.h
@@ -166,6 +166,14 @@ public:
bool setTimeoutSeconds(F32 timeout);
/**
+ * @brief Adjust the timeout of the running chain.
+ *
+ * This method has no effect if there is no timeout on the chain.
+ * @param delta The number of seconds to add to/remove from the timeout.
+ */
+ void adjustTimeoutSeconds(F32 delta);
+
+ /**
* @brief Set up file descriptors for for the running chain.
* @see rebuildPollset()
*
@@ -349,6 +357,7 @@ protected:
// methods
LLChainInfo();
void setTimeoutSeconds(F32 timeout);
+ void adjustTimeoutSeconds(F32 delta);
// basic member data
bool mInit;
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 6e5fa6def8..ff6ec9f077 100644
--- a/indra/llmessage/llurlrequest.cpp
+++ b/indra/llmessage/llurlrequest.cpp
@@ -68,6 +68,7 @@ public:
LLChannelDescriptors mChannels;
U8* mLastRead;
U32 mBodyLimit;
+ S32 mByteAccumulator;
bool mIsBodyLimitSet;
};
@@ -76,8 +77,8 @@ LLURLRequestDetail::LLURLRequestDetail() :
mResponseBuffer(NULL),
mLastRead(NULL),
mBodyLimit(0),
+ mByteAccumulator(0),
mIsBodyLimitSet(false)
-
{
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
mCurlRequest = new LLCurlEasyRequest();
@@ -264,8 +265,25 @@ LLIOPipe::EStatus LLURLRequest::process_impl(
{
CURLcode result;
bool newmsg = mDetail->mCurlRequest->getResult(&result);
- if (!newmsg)
+ if(!newmsg)
{
+ // we're still waiting or prcessing, check how many
+ // bytes we have accumulated.
+ const S32 MIN_ACCUMULATION = 100000;
+ if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION))
+ {
+ // This is a pretty sloppy calculation, but this
+ // tries to make the gross assumption that if data
+ // is coming in at 56kb/s, then this transfer will
+ // probably succeed. So, if we're accumlated
+ // 100,000 bytes (MIN_ACCUMULATION) then let's
+ // give this client another 2s to complete.
+ const F32 TIMEOUT_ADJUSTMENT = 2.0f;
+ mDetail->mByteAccumulator = 0;
+ pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT);
+ }
+
+ // keep processing
break;
}
@@ -434,6 +452,7 @@ size_t LLURLRequest::downCallback(
req->mDetail->mChannels.out(),
(U8*)data,
bytes);
+ req->mDetail->mByteAccumulator += bytes;
return bytes;
}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 9ee3840f7f..b56629b60a 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -84,7 +84,7 @@ static std::deque<LLUUID> sFetchQueue;
//BOOL decompress_file(const char* src_filename, const char* dst_filename);
const F32 MAX_TIME_FOR_SINGLE_FETCH = 10.f;
-const S32 MAX_FETCH_RETRIES = 5;
+const S32 MAX_FETCH_RETRIES = 10;
const char CACHE_FORMAT_STRING[] = "%s.inv";
const char* NEW_CATEGORY_NAME = "New Folder";
const char* NEW_CATEGORY_NAMES[LLAssetType::AT_COUNT] =
@@ -989,13 +989,24 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer)
// Call this method when it's time to update everyone on a new state,
// by default, the inventory model will not update observers
// automatically.
-void LLInventoryModel::notifyObservers()
+// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
+void LLInventoryModel::notifyObservers(const std::string service_name)
{
for (observer_list_t::iterator iter = mObservers.begin();
iter != mObservers.end(); )
{
LLInventoryObserver* observer = *iter;
- observer->changed(mModifyMask);
+
+ if (service_name.empty())
+ {
+ observer->changed(mModifyMask);
+ }
+ else
+ {
+ observer->mMessageName = service_name;
+ observer->changed(mModifyMask);
+ }
+
// safe way to incrament since changed may delete entries! (@!##%@!@&*!)
iter = mObservers.upper_bound(observer);
}
@@ -1037,6 +1048,79 @@ void LLInventoryModel::mock(const LLUUID& root_id)
}
*/
+//If we get back a normal response, handle it here
+void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
+{
+ start_new_inventory_observer();
+
+ /*LLUUID agent_id;
+ agent_id = content["agent_id"].asUUID();
+ if(agent_id != gAgent.getID())
+ {
+ llwarns << "Got a inventory update for the wrong agent: " << agent_id
+ << llendl;
+ return;
+ }*/
+ item_array_t items;
+ update_map_t update;
+ S32 count = content["items"].size();
+ bool all_one_folder = true;
+ LLUUID folder_id;
+ // Does this loop ever execute more than once? -Gigs
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+ titem->unpackMessage(content["items"][i]);
+
+ lldebugs << "LLInventoryModel::messageUpdateCore() item id:"
+ << titem->getUUID() << llendl;
+ items.push_back(titem);
+ // examine update for changes.
+ LLViewerInventoryItem* itemp = gInventory.getItem(titem->getUUID());
+ if(itemp)
+ {
+ if(titem->getParentUUID() == itemp->getParentUUID())
+ {
+ update[titem->getParentUUID()];
+ }
+ else
+ {
+ ++update[titem->getParentUUID()];
+ --update[itemp->getParentUUID()];
+ }
+ }
+ else
+ {
+ ++update[titem->getParentUUID()];
+ }
+ if (folder_id.isNull())
+ {
+ folder_id = titem->getParentUUID();
+ }
+ else
+ {
+ all_one_folder = false;
+ }
+ }
+
+ U32 changes = 0x0;
+ //as above, this loop never seems to loop more than once per call
+ for (item_array_t::iterator it = items.begin(); it != items.end(); ++it)
+ {
+ changes |= gInventory.updateItem(*it);
+ }
+ gInventory.notifyObservers("fetchinventory");
+ gViewerWindow->getWindow()->decBusyCount();
+}
+
+//If we get back an error (not found, etc...), handle it here
+void LLInventoryModel::fetchInventoryResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "fetchInventory::error "
+ << status << ": " << reason << llendl;
+ gInventory.notifyObservers("fetchinventory");
+}
+
void LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
{
LLViewerInventoryCategory* cat = getCategory(folder_id);
@@ -1085,9 +1169,10 @@ class fetchDescendentsResponder: public LLHTTPClient::Responder
//If we get back a normal response, handle it here
void fetchDescendentsResponder::result(const LLSD& content)
-{
+{
if (content.has("folders"))
{
+
for(LLSD::array_const_iterator folder_it = content["folders"].beginArray();
folder_it != content["folders"].endArray();
++folder_it)
@@ -1095,21 +1180,49 @@ void fetchDescendentsResponder::result(const LLSD& content)
LLSD folder_sd = *folder_it;
- LLUUID agent_id = folder_sd["agent-id"];
+ //LLUUID agent_id = folder_sd["agent_id"];
- if(agent_id != gAgent.getID()) //This should never happen.
- {
- llwarns << "Got a UpdateInventoryItem for the wrong agent."
- << llendl;
- continue;
- }
- LLUUID parent_id = folder_sd["folder-id"];
- LLUUID owner_id = folder_sd["owner-id"];
+ //if(agent_id != gAgent.getID()) //This should never happen.
+ //{
+ // llwarns << "Got a UpdateInventoryItem for the wrong agent."
+ // << llendl;
+ // break;
+ //}
+
+ LLUUID parent_id = folder_sd["folder_id"];
+ LLUUID owner_id = folder_sd["owner_id"];
S32 version = (S32)folder_sd["version"].asInteger();
S32 descendents = (S32)folder_sd["descendents"].asInteger();
LLPointer<LLViewerInventoryCategory> tcategory = new LLViewerInventoryCategory(owner_id);
- LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id);
+ if (parent_id.isNull())
+ {
+ LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+ for(LLSD::array_const_iterator item_it = folder_sd["items"].beginArray();
+ item_it != folder_sd["items"].endArray();
+ ++item_it)
+ {
+ LLUUID lost_uuid = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ if (lost_uuid.notNull())
+ {
+ LLSD item = *item_it;
+ titem->unpackMessage(item);
+
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate new_folder(lost_uuid, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ titem->setParent(lost_uuid);
+ titem->updateParentOnServer(FALSE);
+ gInventory.updateItem(titem);
+ gInventory.notifyObservers("fetchDescendents");
+
+ }
+ }
+ }
+
+ LLViewerInventoryCategory* pcat = gInventory.getCategory(parent_id);
if (!pcat)
{
continue;
@@ -1154,16 +1267,16 @@ void fetchDescendentsResponder::result(const LLSD& content)
}
}
- if (content.has("bad-folders"))
+ if (content.has("bad_folders"))
{
- for(LLSD::array_const_iterator folder_it = content["bad-folders"].beginArray();
- folder_it != content["bad-folders"].endArray();
+ for(LLSD::array_const_iterator folder_it = content["bad_folders"].beginArray();
+ folder_it != content["bad_folders"].endArray();
++folder_it)
{
LLSD folder_sd = *folder_it;
//These folders failed on the dataserver. We probably don't want to retry them.
- llinfos << "Folder " << folder_sd["folder-id"].asString()
+ llinfos << "Folder " << folder_sd["folder_id"].asString()
<< "Error: " << folder_sd["error"].asString() << llendl;
}
}
@@ -1180,7 +1293,7 @@ void fetchDescendentsResponder::result(const LLSD& content)
LLInventoryModel::stopBackgroundFetch();
}
- gInventory.notifyObservers();
+ gInventory.notifyObservers("fetchDescendents");
}
//If we get back an error (not found, etc...), handle it here
@@ -1198,7 +1311,7 @@ void fetchDescendentsResponder::error(U32 status, const std::string& reason)
++folder_it)
{
LLSD folder_sd = *folder_it;
- LLUUID folder_id = folder_sd["folder-id"];
+ LLUUID folder_id = folder_sd["folder_id"];
sFetchQueue.push_front(folder_id);
}
}
@@ -1213,7 +1326,7 @@ void fetchDescendentsResponder::error(U32 status, const std::string& reason)
LLInventoryModel::stopBackgroundFetch();
}
}
- gInventory.notifyObservers();
+ gInventory.notifyObservers("fetchDescendents");
}
//static Bundle up a bunch of requests to send all at once.
@@ -1241,49 +1354,75 @@ void LLInventoryModel::bulkFetch(std::string url)
U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
LLSD body;
-
+ LLSD body_lib;
while( !(sFetchQueue.empty() ) && (folder_count < max_batch_size) )
{
- LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
-
- if (cat)
- {
- if ( LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
- {
- LLSD folder_sd;
- folder_sd["folder-id"] = cat->getUUID();
- folder_sd["owner-id"] = cat->getOwnerID();
- folder_sd["sort-order"] = (LLSD::Integer)sort_order;
- folder_sd["fetch-folders"] = (LLSD::Boolean)sFullFetchStarted;
- folder_sd["fetch-items"] = (LLSD::Boolean)TRUE;
- body["folders"].append(folder_sd);
-
- folder_count++;
- }
- else if (sFullFetchStarted)
- { //Already have this folder but append child folders to list.
- // add all children to queue
- parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
- if (cat_it != gInventory.mParentChildCategoryTree.end())
- {
- cat_array_t* child_categories = cat_it->second;
-
- for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
- {
- sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
- }
- }
+ if (sFetchQueue.front().isNull()) //DEV-17797
+ {
+ LLSD folder_sd;
+ folder_sd["folder_id"] = LLUUID::null.asString();
+ folder_sd["owner_id"] = gAgent.getID();
+ folder_sd["sort_order"] = (LLSD::Integer)sort_order;
+ folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE;
+ folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
+ body["folders"].append(folder_sd);
+ folder_count++;
+ }
+ else
+ {
+
- }
- }
+ LLViewerInventoryCategory* cat = gInventory.getCategory(sFetchQueue.front());
+
+ if (cat)
+ {
+ if ( LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
+ {
+ LLSD folder_sd;
+ folder_sd["folder_id"] = cat->getUUID();
+ folder_sd["owner_id"] = cat->getOwnerID();
+ folder_sd["sort_order"] = (LLSD::Integer)sort_order;
+ folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
+ folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
+
+ if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
+ body_lib["folders"].append(folder_sd);
+ else
+ body["folders"].append(folder_sd);
+ folder_count++;
+ }
+ if (sFullFetchStarted)
+ { //Already have this folder but append child folders to list.
+ // add all children to queue
+ parent_cat_map_t::iterator cat_it = gInventory.mParentChildCategoryTree.find(cat->getUUID());
+ if (cat_it != gInventory.mParentChildCategoryTree.end())
+ {
+ cat_array_t* child_categories = cat_it->second;
+
+ for (S32 child_num = 0; child_num < child_categories->count(); child_num++)
+ {
+ sFetchQueue.push_back(child_categories->get(child_num)->getUUID());
+ }
+ }
+
+ }
+ }
+ }
sFetchQueue.pop_front();
}
if (folder_count > 0)
{
sBulkFetchCount++;
-
- LLHTTPClient::post(url, body, new fetchDescendentsResponder(body));
+ if (body["folders"].size())
+ {
+ LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0);
+ }
+ if (body_lib["folders"].size())
+ {
+ std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
+ LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0);
+ }
sFetchTimer.reset();
}
else if (isBulkFetchProcessingComplete())
@@ -1337,6 +1476,14 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
}
//static
+void LLInventoryModel::findLostItems()
+{
+ sBackgroundFetchActive = TRUE;
+ sFetchQueue.push_back(LLUUID::null);
+ gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
+}
+
+//static
void LLInventoryModel::stopBackgroundFetch()
{
if (sBackgroundFetchActive)
@@ -1355,7 +1502,7 @@ void LLInventoryModel::backgroundFetch(void*)
if (sBackgroundFetchActive)
{
//If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
- std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents");
+ std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
if (!url.empty())
{
bulkFetch(url);
@@ -3312,12 +3459,72 @@ bool LLInventoryFetchObserver::isEverythingComplete() const
return mIncomplete.empty();
}
+void fetch_items_from_llsd(const LLSD& items_llsd)
+{
+ if (!items_llsd.size()) return;
+ LLSD body;
+ body[0]["cap_name"] = "FetchInventory";
+ body[1]["cap_name"] = "FetchLib";
+ for (S32 i=0; i<items_llsd.size();i++)
+ {
+ if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
+ {
+ body[0]["items"].append(items_llsd[i]);
+ continue;
+ }
+ if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
+ {
+ body[1]["items"].append(items_llsd[i]);
+ continue;
+ }
+ }
+
+ for (S32 i=0; i<body.size(); i++)
+ {
+ if (0 >= body[i].size()) continue;
+ std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
+
+ if (!url.empty())
+ {
+ body[i]["agent_id"] = gAgent.getID();
+ LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
+ break;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ BOOL start_new_message = TRUE;
+ for (S32 j=0; j<body[i]["items"].size(); j++)
+ {
+ LLSD item_entry = body[i]["items"][j];
+ if(start_new_message)
+ {
+ start_new_message = FALSE;
+ msg->newMessageFast(_PREHASH_FetchInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
+ msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
+ if(msg->isSendFull(NULL))
+ {
+ start_new_message = TRUE;
+ gAgent.sendReliableMessage();
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ }
+ }
+}
+
void LLInventoryFetchObserver::fetchItems(
const LLInventoryFetchObserver::item_ref_t& ids)
{
- LLMessageSystem* msg = gMessageSystem;
- BOOL start_new_message = TRUE;
LLUUID owner_id;
+ LLSD items_llsd;
for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
{
LLViewerInventoryItem* item = gInventory.getItem(*it);
@@ -3339,31 +3546,18 @@ void LLInventoryFetchObserver::fetchItems(
// assume it's agent inventory.
owner_id = gAgent.getID();
}
-
+
// It's incomplete, so put it on the incomplete container, and
// pack this on the message.
mIncomplete.push_back(*it);
- if(start_new_message)
- {
- start_new_message = FALSE;
- msg->newMessageFast(_PREHASH_FetchInventory);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_OwnerID, owner_id);
- msg->addUUIDFast(_PREHASH_ItemID, (*it));
- if(msg->isSendFull(NULL))
- {
- start_new_message = TRUE;
- gAgent.sendReliableMessage();
- }
- }
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
+
+ // Prepare the data to fetch
+ LLSD item_entry;
+ item_entry["owner_id"] = owner_id;
+ item_entry["item_id"] = (*it);
+ items_llsd.append(item_entry);
}
+ fetch_items_from_llsd(items_llsd);
}
// virtual
@@ -3518,9 +3712,8 @@ void LLInventoryFetchComboObserver::fetch(
// descendent of an incomplete folder because the item will show
// up in an inventory descendents message soon enough so we do not
// have to fetch it individually.
+ LLSD items_llsd;
LLUUID owner_id;
- LLMessageSystem* msg = gMessageSystem;
- bool start_new_message = true;
for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
{
LLViewerInventoryItem* item = gInventory.getItem(*iit);
@@ -3543,33 +3736,17 @@ void LLInventoryFetchComboObserver::fetch(
}
if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
{
- lldebugs << "fetching item " << *iit << llendl;
- if(start_new_message)
- {
- start_new_message = false;
- msg->newMessageFast(_PREHASH_FetchInventory);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_OwnerID, owner_id);
- msg->addUUIDFast(_PREHASH_ItemID, (*iit));
- if(msg->isSendFullFast(_PREHASH_InventoryData))
- {
- start_new_message = true;
- gAgent.sendReliableMessage();
- }
+ LLSD item_entry;
+ item_entry["owner_id"] = owner_id;
+ item_entry["item_id"] = (*iit);
+ items_llsd.append(item_entry);
}
else
{
lldebugs << "not worrying about " << *iit << llendl;
}
}
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
- }
+ fetch_items_from_llsd(items_llsd);
}
void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
@@ -3615,7 +3792,17 @@ void LLInventoryAddedObserver::changed(U32 mask)
// the network, figure out which item was updated.
// Code from Gigs Taggert, sin allowed by JC.
LLMessageSystem* msg = gMessageSystem;
- std::string msg_name = msg->getMessageName();
+
+ std::string msg_name;
+ if (mMessageName.empty())
+ {
+ msg_name = msg->getMessageName();
+ }
+ else
+ {
+ msg_name = mMessageName;
+ }
+
if (msg_name.empty())
{
return;
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 40dd55dda2..064ace52f2 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -69,6 +69,7 @@ public:
};
virtual ~LLInventoryObserver() {};
virtual void changed(U32 mask) = 0;
+ std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328]
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -110,7 +111,18 @@ public:
LLInventoryModel();
~LLInventoryModel();
-
+ class fetchInventoryResponder: public LLHTTPClient::Responder
+ {
+ public:
+ fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {};
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+
+ public:
+ typedef std::vector<LLViewerInventoryCategory*> folder_ref_t;
+ protected:
+ LLSD mRequestSD;
+ };
//
// Accessors
@@ -254,7 +266,8 @@ public:
// Call this method when it's time to update everyone on a new
// state, by default, the inventory model will not update
// observers automatically.
- void notifyObservers();
+ // The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
+ void notifyObservers(const std::string service_name="");
// This allows outsiders to tell the inventory if something has
// been changed 'under the hood', but outside the control of the
@@ -356,6 +369,7 @@ public:
// start and stop background breadth-first fetching of inventory contents
// this gets triggered when performing a filter-search
static void startBackgroundFetch(const LLUUID& cat_id = LLUUID::null); // start fetch process
+ static void findLostItems();
static BOOL backgroundFetchActive();
static bool isEverythingFetched();
static void backgroundFetch(void*); // background fetch idle function
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 793944f7fa..eaf1b90be3 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2244,6 +2244,9 @@ bool idle_startup()
}
}
+ //DEV-17797. get null folder. Any items found here moved to Lost and Found
+ LLInventoryModel::findLostItems();
+
LLStartUp::setStartupState( STATE_PRECACHE );
timeout.reset();
return FALSE;
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 7fe076553b..c28ed7c435 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -196,15 +196,34 @@ void LLViewerInventoryItem::fetchFromServer(void) const
{
if(!mIsComplete)
{
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("FetchInventory");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID("SessionID", gAgent.getSessionID());
- msg->nextBlock("InventoryData");
- msg->addUUID("OwnerID", mPermissions.getOwner());
- msg->addUUID("ItemID", mUUID);
- gAgent.sendReliableMessage();
+ std::string url;
+
+ if( ALEXANDRIA_LINDEN_ID.getString() == mPermissions.getOwner().getString())
+ url = gAgent.getRegion()->getCapability("FetchLib");
+ else
+ url = gAgent.getRegion()->getCapability("FetchInventory");
+
+ if (!url.empty())
+ {
+ LLSD body;
+ body["agent_id"] = gAgent.getID();
+ body["items"][0]["owner_id"] = mPermissions.getOwner();
+ body["items"][0]["item_id"] = mUUID;
+
+ LLHTTPClient::post(url, body, new LLInventoryModel::fetchInventoryResponder(body));
+ }
+ else
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("FetchInventory");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("InventoryData");
+ msg->addUUID("OwnerID", mPermissions.getOwner());
+ msg->addUUID("ItemID", mUUID);
+ gAgent.sendReliableMessage();
+ }
}
else
{
@@ -441,7 +460,7 @@ bool LLViewerInventoryCategory::fetchDescendents()
// This comes from LLInventoryFilter from llfolderview.h
U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
- std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents");
+ std::string url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
if (!url.empty()) //Capability found. Build up LLSD and use it.
{
@@ -449,7 +468,7 @@ bool LLViewerInventoryCategory::fetchDescendents()
}
else
{ //Deprecated, but if we don't have a capability, use the old system.
- llinfos << "FetchInventoryDescendents capability not found. Using deprecated UDP message." << llendl;
+ llinfos << "WebFetchInventoryDescendents capability not found. Using deprecated UDP message." << llendl;
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("FetchInventoryDescendents");
msg->nextBlock("AgentData");
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index f8c7b317f0..fe6ce6faa0 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1387,7 +1387,10 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("DispatchRegionInfo");
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
- capabilityNames.append("FetchInventoryDescendents");
+ capabilityNames.append("FetchInventory");
+ capabilityNames.append("WebFetchInventoryDescendents");
+ capabilityNames.append("FetchLib");
+ capabilityNames.append("FetchLibDescendents");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("HomeLocation");
capabilityNames.append("MapLayer");