diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 21:25:21 +0200 |
---|---|---|
committer | Andrey Lihatskiy <alihatskiy@productengine.com> | 2024-05-22 22:40:26 +0300 |
commit | e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 (patch) | |
tree | 1bb897489ce524986f6196201c10ac0d8861aa5f /indra/llinventory/llinventory.cpp | |
parent | 069ea06848f766466f1a281144c82a0f2bd79f3a (diff) |
Fix line endlings
Diffstat (limited to 'indra/llinventory/llinventory.cpp')
-rw-r--r-- | indra/llinventory/llinventory.cpp | 3034 |
1 files changed, 1517 insertions, 1517 deletions
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 55e8294619..082d8b2f9f 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -1,1517 +1,1517 @@ -/**
- * @file llinventory.cpp
- * @brief Implementation of the inventory system.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llinventory.h"
-
-#include "lldbstrings.h"
-#include "llfasttimer.h"
-#include "llinventorydefines.h"
-#include "llxorcipher.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-#include "message.h"
-#include <boost/tokenizer.hpp>
-
-#include "llsdutil.h"
-
-///----------------------------------------------------------------------------
-/// Exported functions
-///----------------------------------------------------------------------------
-// FIXME D567 - what's the point of these, especially if we don't even use them consistently?
-static const std::string INV_ITEM_ID_LABEL("item_id");
-static const std::string INV_FOLDER_ID_LABEL("cat_id");
-static const std::string INV_PARENT_ID_LABEL("parent_id");
-static const std::string INV_THUMBNAIL_LABEL("thumbnail");
-static const std::string INV_THUMBNAIL_ID_LABEL("thumbnail_id");
-static const std::string INV_ASSET_TYPE_LABEL("type");
-static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
-static const std::string INV_INVENTORY_TYPE_LABEL("inv_type");
-static const std::string INV_NAME_LABEL("name");
-static const std::string INV_DESC_LABEL("desc");
-static const std::string INV_PERMISSIONS_LABEL("permissions");
-static const std::string INV_SHADOW_ID_LABEL("shadow_id");
-static const std::string INV_ASSET_ID_LABEL("asset_id");
-static const std::string INV_LINKED_ID_LABEL("linked_id");
-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
-///----------------------------------------------------------------------------
-
-const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730");
-
-///----------------------------------------------------------------------------
-/// Class LLInventoryObject
-///----------------------------------------------------------------------------
-
-LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
- const LLUUID& parent_uuid,
- LLAssetType::EType type,
- const std::string& name)
-: mUUID(uuid),
- mParentUUID(parent_uuid),
- mType(type),
- mName(name),
- mCreationDate(0)
-{
- correctInventoryName(mName);
-}
-
-LLInventoryObject::LLInventoryObject()
-: mType(LLAssetType::AT_NONE),
- mCreationDate(0)
-{
-}
-
-LLInventoryObject::~LLInventoryObject()
-{
-}
-
-void LLInventoryObject::copyObject(const LLInventoryObject* other)
-{
- mUUID = other->mUUID;
- mParentUUID = other->mParentUUID;
- mType = other->mType;
- mName = other->mName;
- mThumbnailUUID = other->mThumbnailUUID;
-}
-
-const LLUUID& LLInventoryObject::getUUID() const
-{
- return mUUID;
-}
-
-const LLUUID& LLInventoryObject::getParentUUID() const
-{
- return mParentUUID;
-}
-
-const LLUUID& LLInventoryObject::getThumbnailUUID() const
-{
- return mThumbnailUUID;
-}
-
-const std::string& LLInventoryObject::getName() const
-{
- return mName;
-}
-
-// To bypass linked items, since llviewerinventory's getType
-// will return the linked-to item's type instead of this object's type.
-LLAssetType::EType LLInventoryObject::getActualType() const
-{
- return mType;
-}
-
-bool LLInventoryObject::getIsLinkType() const
-{
- return LLAssetType::lookupIsLinkType(mType);
-}
-
-// See LLInventoryItem override.
-// virtual
-const LLUUID& LLInventoryObject::getLinkedUUID() const
-{
- return mUUID;
-}
-
-LLAssetType::EType LLInventoryObject::getType() const
-{
- return mType;
-}
-
-void LLInventoryObject::setUUID(const LLUUID& new_uuid)
-{
- mUUID = new_uuid;
-}
-
-void LLInventoryObject::rename(const std::string& n)
-{
- std::string new_name(n);
- correctInventoryName(new_name);
- if( !new_name.empty() && new_name != mName )
- {
- mName = new_name;
- }
-}
-
-void LLInventoryObject::setParent(const LLUUID& new_parent)
-{
- mParentUUID = new_parent;
-}
-
-void LLInventoryObject::setThumbnailUUID(const LLUUID& thumbnail_uuid)
-{
- mThumbnailUUID = thumbnail_uuid;
-}
-
-void LLInventoryObject::setType(LLAssetType::EType type)
-{
- mType = type;
-}
-
-
-// virtual
-bool LLInventoryObject::importLegacyStream(std::istream& input_stream)
-{
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[MAX_STRING]; /* Flawfinder: ignore */
- char keyword[MAX_STRING]; /* Flawfinder: ignore */
- char valuestr[MAX_STRING]; /* Flawfinder: ignore */
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
- while(input_stream.good())
- {
- input_stream.getline(buffer, MAX_STRING);
- sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("obj_id", keyword))
- {
- mUUID.set(valuestr);
- }
- else if(0 == strcmp("parent_id", keyword))
- {
- mParentUUID.set(valuestr);
- }
- else if(0 == strcmp("type", keyword))
- {
- mType = LLAssetType::lookup(valuestr);
- }
- else if (0 == strcmp("metadata", keyword))
- {
- LLSD metadata;
- if (strncmp("<llsd>", valuestr, 6) == 0)
- {
- std::istringstream stream(valuestr);
- LLSDSerialize::fromXML(metadata, stream);
- }
- else
- {
- // next line likely contains metadata, but at the moment is not supported
- // can do something like:
- // LLSDSerialize::fromNotation(metadata, input_stream, -1);
- }
-
- if (metadata.has("thumbnail"))
- {
- const LLSD& thumbnail = metadata["thumbnail"];
- if (thumbnail.has("asset_id"))
- {
- setThumbnailUUID(thumbnail["asset_id"].asUUID());
- }
- else
- {
- setThumbnailUUID(LLUUID::null);
- }
- }
- else
- {
- setThumbnailUUID(LLUUID::null);
- }
- }
- else if(0 == strcmp("name", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254[^|]",
- keyword, valuestr);
- mName.assign(valuestr);
- correctInventoryName(mName);
- }
- else
- {
- LL_WARNS() << "unknown keyword '" << keyword
- << "' in LLInventoryObject::importLegacyStream() for object " << mUUID << LL_ENDL;
- }
- }
- return true;
-}
-
-bool LLInventoryObject::exportLegacyStream(std::ostream& output_stream, bool) const
-{
- std::string uuid_str;
- output_stream << "\tinv_object\t0\n\t{\n";
- mUUID.toString(uuid_str);
- output_stream << "\t\tobj_id\t" << uuid_str << "\n";
- mParentUUID.toString(uuid_str);
- output_stream << "\t\tparent_id\t" << uuid_str << "\n";
- output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
- output_stream << "\t\tname\t" << mName.c_str() << "|\n";
- output_stream << "\t}\n";
- return true;
-}
-
-void LLInventoryObject::updateParentOnServer(bool) const
-{
- // don't do nothin'
- LL_WARNS() << "LLInventoryObject::updateParentOnServer() called. Doesn't do anything." << LL_ENDL;
-}
-
-void LLInventoryObject::updateServer(bool) const
-{
- // don't do nothin'
- LL_WARNS() << "LLInventoryObject::updateServer() called. Doesn't do anything." << LL_ENDL;
-}
-
-// static
-void LLInventoryObject::correctInventoryName(std::string& name)
-{
- LLStringUtil::replaceNonstandardASCII(name, ' ');
- LLStringUtil::replaceChar(name, '|', ' ');
- LLStringUtil::trim(name);
- LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN);
-}
-
-time_t LLInventoryObject::getCreationDate() const
-{
- return mCreationDate;
-}
-
-void LLInventoryObject::setCreationDate(time_t creation_date_utc)
-{
- mCreationDate = creation_date_utc;
-}
-
-
-const std::string& LLInventoryItem::getDescription() const
-{
- return mDescription;
-}
-
-const std::string& LLInventoryItem::getActualDescription() const
-{
- return mDescription;
-}
-
-///----------------------------------------------------------------------------
-/// Class LLInventoryItem
-///----------------------------------------------------------------------------
-
-LLInventoryItem::LLInventoryItem(const LLUUID& uuid,
- const LLUUID& parent_uuid,
- const LLPermissions& permissions,
- const LLUUID& asset_uuid,
- LLAssetType::EType type,
- LLInventoryType::EType inv_type,
- const std::string& name,
- const std::string& desc,
- const LLSaleInfo& sale_info,
- U32 flags,
- S32 creation_date_utc) :
- LLInventoryObject(uuid, parent_uuid, type, name),
- mPermissions(permissions),
- mAssetUUID(asset_uuid),
- mDescription(desc),
- mSaleInfo(sale_info),
- mInventoryType(inv_type),
- mFlags(flags)
-{
- mCreationDate = creation_date_utc;
-
- LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
- LLStringUtil::replaceChar(mDescription, '|', ' ');
-
- mPermissions.initMasks(inv_type);
-}
-
-LLInventoryItem::LLInventoryItem() :
- LLInventoryObject(),
- mPermissions(),
- mAssetUUID(),
- mDescription(),
- mSaleInfo(),
- mInventoryType(LLInventoryType::IT_NONE),
- mFlags(0)
-{
- mCreationDate = 0;
-}
-
-LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) :
- LLInventoryObject()
-{
- copyItem(other);
-}
-
-LLInventoryItem::~LLInventoryItem()
-{
-}
-
-// virtual
-void LLInventoryItem::copyItem(const LLInventoryItem* other)
-{
- copyObject(other);
- mPermissions = other->mPermissions;
- mAssetUUID = other->mAssetUUID;
- mThumbnailUUID = other->mThumbnailUUID;
- mDescription = other->mDescription;
- mSaleInfo = other->mSaleInfo;
- mInventoryType = other->mInventoryType;
- mFlags = other->mFlags;
- mCreationDate = other->mCreationDate;
-}
-
-// If this is a linked item, then the UUID of the base object is
-// this item's assetID.
-// virtual
-const LLUUID& LLInventoryItem::getLinkedUUID() const
-{
- if (LLAssetType::lookupIsLinkType(getActualType()))
- {
- return mAssetUUID;
- }
-
- return LLInventoryObject::getLinkedUUID();
-}
-
-const LLPermissions& LLInventoryItem::getPermissions() const
-{
- return mPermissions;
-}
-
-const LLUUID& LLInventoryItem::getCreatorUUID() const
-{
- return mPermissions.getCreator();
-}
-
-const LLUUID& LLInventoryItem::getAssetUUID() const
-{
- return mAssetUUID;
-}
-
-void LLInventoryItem::setAssetUUID(const LLUUID& asset_id)
-{
- mAssetUUID = asset_id;
-}
-
-
-U32 LLInventoryItem::getCRC32() const
-{
- // *FIX: Not a real crc - more of a checksum.
- // *NOTE: We currently do not validate the name or description,
- // but if they change in transit, it's no big deal.
- U32 crc = mUUID.getCRC32();
- //LL_DEBUGS() << "1 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mParentUUID.getCRC32();
- //LL_DEBUGS() << "2 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mPermissions.getCRC32();
- //LL_DEBUGS() << "3 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mAssetUUID.getCRC32();
- //LL_DEBUGS() << "4 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mType;
- //LL_DEBUGS() << "5 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mInventoryType;
- //LL_DEBUGS() << "6 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mFlags;
- //LL_DEBUGS() << "7 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mSaleInfo.getCRC32();
- //LL_DEBUGS() << "8 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += (U32)mCreationDate;
- //LL_DEBUGS() << "9 crc: " << std::hex << crc << std::dec << LL_ENDL;
- crc += mThumbnailUUID.getCRC32();
- return crc;
-}
-
-// static
-void LLInventoryItem::correctInventoryDescription(std::string& desc)
-{
- LLStringUtil::replaceNonstandardASCII(desc, ' ');
- LLStringUtil::replaceChar(desc, '|', ' ');
-}
-
-void LLInventoryItem::setDescription(const std::string& d)
-{
- std::string new_desc(d);
- LLInventoryItem::correctInventoryDescription(new_desc);
- if( new_desc != mDescription )
- {
- mDescription = new_desc;
- }
-}
-
-void LLInventoryItem::setPermissions(const LLPermissions& perm)
-{
- mPermissions = perm;
-
- // Override permissions to unrestricted if this is a landmark
- mPermissions.initMasks(mInventoryType);
-}
-
-void LLInventoryItem::setInventoryType(LLInventoryType::EType inv_type)
-{
- mInventoryType = inv_type;
-}
-
-void LLInventoryItem::setFlags(U32 flags)
-{
- mFlags = flags;
-}
-
-// Currently only used in the Viewer to handle calling cards
-// where the creator is actually used to store the target.
-void LLInventoryItem::setCreator(const LLUUID& creator)
-{
- mPermissions.setCreator(creator);
-}
-
-void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item)
-{
- // Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags
- // because we now detect when they should be set.
- setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItemFlags::II_FLAGS_PERM_OVERWRITE_MASK)) );
-
- // Enforce the PERM_OVERWRITE flags for any masks that are different
- // but only for AT_OBJECT's since that is the only asset type that can
- // exist in-world (instead of only in-inventory or in-object-contents).
- if (LLAssetType::AT_OBJECT == getType())
- {
- LLPermissions old_permissions = old_item.getPermissions();
- U32 flags_to_be_set = 0;
- if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner())
- {
- flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_PERM;
- }
- if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone())
- {
- flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
- }
- if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup())
- {
- flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
- }
- LLSaleInfo old_sale_info = old_item.getSaleInfo();
- if(old_sale_info != getSaleInfo())
- {
- flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_SALE;
- }
- setFlags(getFlags() | flags_to_be_set);
- }
-}
-
-const LLSaleInfo& LLInventoryItem::getSaleInfo() const
-{
- return mSaleInfo;
-}
-
-void LLInventoryItem::setSaleInfo(const LLSaleInfo& sale_info)
-{
- mSaleInfo = sale_info;
-}
-
-LLInventoryType::EType LLInventoryItem::getInventoryType() const
-{
- return mInventoryType;
-}
-
-U32 LLInventoryItem::getFlags() const
-{
- return mFlags;
-}
-
-time_t LLInventoryItem::getCreationDate() const
-{
- return mCreationDate;
-}
-
-
-// virtual
-void LLInventoryItem::packMessage(LLMessageSystem* msg) const
-{
- msg->addUUIDFast(_PREHASH_ItemID, mUUID);
- msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
- mPermissions.packMessage(msg);
- msg->addUUIDFast(_PREHASH_AssetID, mAssetUUID);
- S8 type = static_cast<S8>(mType);
- msg->addS8Fast(_PREHASH_Type, type);
- type = static_cast<S8>(mInventoryType);
- msg->addS8Fast(_PREHASH_InvType, type);
- msg->addU32Fast(_PREHASH_Flags, mFlags);
- mSaleInfo.packMessage(msg);
- msg->addStringFast(_PREHASH_Name, mName);
- msg->addStringFast(_PREHASH_Description, mDescription);
- msg->addS32Fast(_PREHASH_CreationDate, (S32)mCreationDate);
- U32 crc = getCRC32();
- msg->addU32Fast(_PREHASH_CRC, crc);
-}
-
-// virtual
-bool LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
-{
- msg->getUUIDFast(block, _PREHASH_ItemID, mUUID, block_num);
- msg->getUUIDFast(block, _PREHASH_FolderID, mParentUUID, block_num);
- mPermissions.unpackMessage(msg, block, block_num);
- msg->getUUIDFast(block, _PREHASH_AssetID, mAssetUUID, block_num);
-
- S8 type;
- msg->getS8Fast(block, _PREHASH_Type, type, block_num);
- mType = static_cast<LLAssetType::EType>(type);
- msg->getS8(block, "InvType", type, block_num);
- mInventoryType = static_cast<LLInventoryType::EType>(type);
- mPermissions.initMasks(mInventoryType);
-
- msg->getU32Fast(block, _PREHASH_Flags, mFlags, block_num);
-
- mSaleInfo.unpackMultiMessage(msg, block, block_num);
-
- msg->getStringFast(block, _PREHASH_Name, mName, block_num);
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
-
- msg->getStringFast(block, _PREHASH_Description, mDescription, block_num);
- LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
-
- S32 date;
- msg->getS32(block, "CreationDate", date, block_num);
- mCreationDate = date;
-
- U32 local_crc = getCRC32();
- U32 remote_crc = 0;
- msg->getU32(block, "CRC", remote_crc, block_num);
-//#define CRC_CHECK
-#ifdef CRC_CHECK
- if(local_crc == remote_crc)
- {
- LL_DEBUGS() << "crc matches" << LL_ENDL;
- return true;
- }
- else
- {
- LL_WARNS() << "inventory crc mismatch: local=" << std::hex << local_crc
- << " remote=" << remote_crc << std::dec << LL_ENDL;
- return false;
- }
-#else
- return (local_crc == remote_crc);
-#endif
-}
-
-// virtual
-bool LLInventoryItem::importLegacyStream(std::istream& input_stream)
-{
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[MAX_STRING]; /* Flawfinder: ignore */
- char keyword[MAX_STRING]; /* Flawfinder: ignore */
- char valuestr[MAX_STRING]; /* Flawfinder: ignore */
- char junk[MAX_STRING]; /* Flawfinder: ignore */
- bool success = true;
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
-
- mInventoryType = LLInventoryType::IT_NONE;
- mAssetUUID.setNull();
- while(success && input_stream.good())
- {
- input_stream.getline(buffer, MAX_STRING);
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254s",
- keyword, valuestr);
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("item_id", keyword))
- {
- mUUID.set(valuestr);
- }
- else if(0 == strcmp("parent_id", keyword))
- {
- mParentUUID.set(valuestr);
- }
- else if(0 == strcmp("permissions", keyword))
- {
- success = mPermissions.importLegacyStream(input_stream);
- }
- else if(0 == strcmp("sale_info", keyword))
- {
- // Sale info used to contain next owner perm. It is now in
- // the permissions. Thus, we read that out, and fix legacy
- // objects. It's possible this op would fail, but it
- // should pick up the vast majority of the tasks.
- bool has_perm_mask = false;
- U32 perm_mask = 0;
- success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask);
- if(has_perm_mask)
- {
- if(perm_mask == PERM_NONE)
- {
- perm_mask = mPermissions.getMaskOwner();
- }
- // fair use fix.
- if(!(perm_mask & PERM_COPY))
- {
- perm_mask |= PERM_TRANSFER;
- }
- mPermissions.setMaskNext(perm_mask);
- }
- }
- else if(0 == strcmp("shadow_id", keyword))
- {
- mAssetUUID.set(valuestr);
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
- }
- else if(0 == strcmp("asset_id", keyword))
- {
- mAssetUUID.set(valuestr);
- }
- else if(0 == strcmp("type", keyword))
- {
- mType = LLAssetType::lookup(valuestr);
- }
- else if (0 == strcmp("metadata", keyword))
- {
- LLSD metadata;
- if (strncmp("<llsd>", valuestr, 6) == 0)
- {
- std::istringstream stream(valuestr);
- LLSDSerialize::fromXML(metadata, stream);
- }
- else
- {
- // next line likely contains metadata, but at the moment is not supported
- // can do something like:
- // LLSDSerialize::fromNotation(metadata, input_stream, -1);
- }
-
- if (metadata.has("thumbnail"))
- {
- const LLSD& thumbnail = metadata["thumbnail"];
- if (thumbnail.has("asset_id"))
- {
- setThumbnailUUID(thumbnail["asset_id"].asUUID());
- }
- else
- {
- setThumbnailUUID(LLUUID::null);
- }
- }
- else
- {
- setThumbnailUUID(LLUUID::null);
- }
- }
- else if(0 == strcmp("inv_type", keyword))
- {
- mInventoryType = LLInventoryType::lookup(std::string(valuestr));
- }
- else if(0 == strcmp("flags", keyword))
- {
- sscanf(valuestr, "%x", &mFlags);
- }
- else if(0 == strcmp("name", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s%254[\t]%254[^|]",
- keyword, junk, valuestr);
-
- // IW: sscanf chokes and puts | in valuestr if there's no name
- if (valuestr[0] == '|')
- {
- valuestr[0] = '\000';
- }
-
- mName.assign(valuestr);
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
- else if(0 == strcmp("desc", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s%254[\t]%254[^|]",
- keyword, junk, valuestr);
-
- if (valuestr[0] == '|')
- {
- valuestr[0] = '\000';
- }
-
- mDescription.assign(valuestr);
- LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
- /* TODO -- ask Ian about this code
- const char *donkey = mDescription.c_str();
- if (donkey[0] == '|')
- {
- LL_ERRS() << "Donkey" << LL_ENDL;
- }
- */
- }
- else if(0 == strcmp("creation_date", keyword))
- {
- S32 date;
- sscanf(valuestr, "%d", &date);
- mCreationDate = date;
- }
- else
- {
- LL_WARNS() << "unknown keyword '" << keyword
- << "' in inventory import of item " << mUUID << LL_ENDL;
- }
- }
-
- // Need to convert 1.0 simstate files to a useful inventory type
- // and potentially deal with bad inventory tyes eg, a landmark
- // marked as a texture.
- if((LLInventoryType::IT_NONE == mInventoryType)
- || !inventory_and_asset_types_match(mInventoryType, mType))
- {
- LL_DEBUGS() << "Resetting inventory type for " << mUUID << LL_ENDL;
- mInventoryType = LLInventoryType::defaultForAssetType(mType);
- }
-
- mPermissions.initMasks(mInventoryType);
-
- return success;
-}
-
-bool LLInventoryItem::exportLegacyStream(std::ostream& output_stream, bool include_asset_key) const
-{
- std::string uuid_str;
- output_stream << "\tinv_item\t0\n\t{\n";
- mUUID.toString(uuid_str);
- output_stream << "\t\titem_id\t" << uuid_str << "\n";
- mParentUUID.toString(uuid_str);
- output_stream << "\t\tparent_id\t" << uuid_str << "\n";
- mPermissions.exportLegacyStream(output_stream);
-
- if (mThumbnailUUID.notNull())
- {
- // Max length is 255 chars, will have to export differently if it gets more data
- // Ex: use newline and toNotation (uses {}) for unlimited size
- LLSD metadata;
- metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID);
-
- output_stream << "\t\tmetadata\t";
- LLSDSerialize::toXML(metadata, output_stream);
- output_stream << "|\n";
- }
-
- // Check for permissions to see the asset id, and if so write it
- // out as an asset id. Otherwise, apply our cheesy encryption.
- if(include_asset_key)
- {
- U32 mask = mPermissions.getMaskBase();
- if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- || (mAssetUUID.isNull()))
- {
- mAssetUUID.toString(uuid_str);
- output_stream << "\t\tasset_id\t" << uuid_str << "\n";
- }
- else
- {
- LLUUID shadow_id(mAssetUUID);
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.encrypt(shadow_id.mData, UUID_BYTES);
- shadow_id.toString(uuid_str);
- output_stream << "\t\tshadow_id\t" << uuid_str << "\n";
- }
- }
- else
- {
- LLUUID::null.toString(uuid_str);
- output_stream << "\t\tasset_id\t" << uuid_str << "\n";
- }
- output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
- const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(!inv_type_str.empty())
- output_stream << "\t\tinv_type\t" << inv_type_str << "\n";
- std::string buffer;
- buffer = llformat( "\t\tflags\t%08x\n", mFlags);
- output_stream << buffer;
- mSaleInfo.exportLegacyStream(output_stream);
- output_stream << "\t\tname\t" << mName.c_str() << "|\n";
- output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n";
- output_stream << "\t\tcreation_date\t" << mCreationDate << "\n";
- output_stream << "\t}\n";
- return true;
-}
-
-LLSD LLInventoryItem::asLLSD() const
-{
- LLSD sd = LLSD();
- asLLSD(sd);
- return sd;
-}
-
-void LLInventoryItem::asLLSD( LLSD& sd ) const
-{
- sd[INV_ITEM_ID_LABEL] = mUUID;
- sd[INV_PARENT_ID_LABEL] = mParentUUID;
- sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions);
-
- if (mThumbnailUUID.notNull())
- {
- sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
- }
-
- U32 mask = mPermissions.getMaskBase();
- if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- || (mAssetUUID.isNull()))
- {
- sd[INV_ASSET_ID_LABEL] = mAssetUUID;
- }
- else
- {
- // *TODO: get rid of this. Phoenix 2008-01-30
- LLUUID shadow_id(mAssetUUID);
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.encrypt(shadow_id.mData, UUID_BYTES);
- sd[INV_SHADOW_ID_LABEL] = shadow_id;
- }
- sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
- sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
- const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
- if(!inv_type_str.empty())
- {
- 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;
- sd[INV_DESC_LABEL] = mDescription;
- sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
-}
-
-bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
-{
- LL_PROFILE_ZONE_SCOPED;
- if (is_new)
- {
- // If we're adding LLSD to an existing object, need avoid
- // clobbering these fields.
- mInventoryType = LLInventoryType::IT_NONE;
- mAssetUUID.setNull();
- }
-
- // TODO - figure out if this should be moved into the noclobber fields above
- mThumbnailUUID.setNull();
-
- // iterate as map to avoid making unnecessary temp copies of everything
- LLSD::map_const_iterator i, end;
- end = sd.endMap();
- for (i = sd.beginMap(); i != end; ++i)
- {
- if (i->first == INV_ITEM_ID_LABEL)
- {
- mUUID = i->second;
- continue;
- }
-
- if (i->first == INV_PARENT_ID_LABEL)
- {
- mParentUUID = i->second;
- continue;
- }
-
- if (i->first == INV_THUMBNAIL_LABEL)
- {
- const LLSD &thumbnail_map = i->second;
- const std::string w = INV_ASSET_ID_LABEL;
- if (thumbnail_map.has(w))
- {
- mThumbnailUUID = thumbnail_map[w];
- }
- /* Example:
- <key> asset_id </key>
- <uuid> acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 </uuid>
- <key> perms </key>
- <integer> 8 </integer>
- <key>service</key>
- <integer> 3 </integer>
- <key>version</key>
- <integer> 1 </key>
- */
- continue;
- }
-
- if (i->first == INV_THUMBNAIL_ID_LABEL)
- {
- mThumbnailUUID = i->second.asUUID();
- continue;
- }
-
- if (i->first == INV_PERMISSIONS_LABEL)
- {
- mPermissions = ll_permissions_from_sd(i->second);
- continue;
- }
-
- if (i->first == INV_SALE_INFO_LABEL)
- {
- // Sale info used to contain next owner perm. It is now in
- // the permissions. Thus, we read that out, and fix legacy
- // objects. It's possible this op would fail, but it
- // should pick up the vast majority of the tasks.
- bool has_perm_mask = false;
- U32 perm_mask = 0;
- if (!mSaleInfo.fromLLSD(i->second, has_perm_mask, perm_mask))
- {
- return false;
- }
- if (has_perm_mask)
- {
- if (perm_mask == PERM_NONE)
- {
- perm_mask = mPermissions.getMaskOwner();
- }
- // fair use fix.
- if (!(perm_mask & PERM_COPY))
- {
- perm_mask |= PERM_TRANSFER;
- }
- mPermissions.setMaskNext(perm_mask);
- }
- continue;
- }
-
- if (i->first == INV_SHADOW_ID_LABEL)
- {
- mAssetUUID = i->second;
- LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES);
- cipher.decrypt(mAssetUUID.mData, UUID_BYTES);
- continue;
- }
-
- if (i->first == INV_ASSET_ID_LABEL)
- {
- mAssetUUID = i->second;
- continue;
- }
-
- if (i->first == INV_LINKED_ID_LABEL)
- {
- mAssetUUID = i->second;
- continue;
- }
-
- if (i->first == INV_ASSET_TYPE_LABEL)
- {
- LLSD const &label = i->second;
- if (label.isString())
- {
- mType = LLAssetType::lookup(label.asString().c_str());
- }
- else if (label.isInteger())
- {
- S8 type = (U8) label.asInteger();
- mType = static_cast<LLAssetType::EType>(type);
- }
- continue;
- }
-
- if (i->first == INV_INVENTORY_TYPE_LABEL)
- {
- LLSD const &label = i->second;
- if (label.isString())
- {
- mInventoryType = LLInventoryType::lookup(label.asString().c_str());
- }
- else if (label.isInteger())
- {
- S8 type = (U8) label.asInteger();
- mInventoryType = static_cast<LLInventoryType::EType>(type);
- }
- continue;
- }
-
- if (i->first == INV_FLAGS_LABEL)
- {
- LLSD const &label = i->second;
- if (label.isBinary())
- {
- mFlags = ll_U32_from_sd(label);
- }
- else if (label.isInteger())
- {
- mFlags = label.asInteger();
- }
- continue;
- }
-
- if (i->first == INV_NAME_LABEL)
- {
- mName = i->second.asString();
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- continue;
- }
-
- if (i->first == INV_DESC_LABEL)
- {
- mDescription = i->second.asString();
- LLStringUtil::replaceNonstandardASCII(mDescription, ' ');
- continue;
- }
-
- if (i->first == INV_CREATION_DATE_LABEL)
- {
- mCreationDate = i->second.asInteger();
- continue;
- }
- }
-
- // Need to convert 1.0 simstate files to a useful inventory type
- // and potentially deal with bad inventory tyes eg, a landmark
- // marked as a texture.
- if((LLInventoryType::IT_NONE == mInventoryType)
- || !inventory_and_asset_types_match(mInventoryType, mType))
- {
- LL_DEBUGS() << "Resetting inventory type for " << mUUID << LL_ENDL;
- mInventoryType = LLInventoryType::defaultForAssetType(mType);
- }
-
- mPermissions.initMasks(mInventoryType);
-
- return true;
-}
-
-///----------------------------------------------------------------------------
-/// Class LLInventoryCategory
-///----------------------------------------------------------------------------
-
-LLInventoryCategory::LLInventoryCategory(const LLUUID& uuid,
- const LLUUID& parent_uuid,
- LLFolderType::EType preferred_type,
- const std::string& name) :
- LLInventoryObject(uuid, parent_uuid, LLAssetType::AT_CATEGORY, name),
- mPreferredType(preferred_type)
-{
-}
-
-LLInventoryCategory::LLInventoryCategory() :
- mPreferredType(LLFolderType::FT_NONE)
-{
- mType = LLAssetType::AT_CATEGORY;
-}
-
-LLInventoryCategory::LLInventoryCategory(const LLInventoryCategory* other) :
- LLInventoryObject()
-{
- copyCategory(other);
-}
-
-LLInventoryCategory::~LLInventoryCategory()
-{
-}
-
-// virtual
-void LLInventoryCategory::copyCategory(const LLInventoryCategory* other)
-{
- copyObject(other);
- mPreferredType = other->mPreferredType;
-}
-
-LLFolderType::EType LLInventoryCategory::getPreferredType() const
-{
- return mPreferredType;
-}
-
-void LLInventoryCategory::setPreferredType(LLFolderType::EType type)
-{
- mPreferredType = type;
-}
-
-LLSD LLInventoryCategory::asLLSD() const
-{
- LLSD sd = LLSD();
- sd[INV_ITEM_ID_LABEL] = mUUID;
- sd[INV_PARENT_ID_LABEL] = mParentUUID;
- S8 type = static_cast<S8>(mPreferredType);
- sd[INV_ASSET_TYPE_LABEL] = type;
- sd[INV_NAME_LABEL] = mName;
-
- if (mThumbnailUUID.notNull())
- {
- sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
- }
-
- return sd;
-}
-
-LLSD LLInventoryCategory::asAISCreateCatLLSD() const
-{
- LLSD sd = LLSD();
- sd[INV_FOLDER_ID_LABEL_WS] = mUUID;
- sd[INV_PARENT_ID_LABEL] = mParentUUID;
- S8 type = static_cast<S8>(mPreferredType);
- sd[INV_ASSET_TYPE_LABEL_WS] = type;
- sd[INV_NAME_LABEL] = mName;
- if (mThumbnailUUID.notNull())
- {
- sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
- }
-
- return sd;
-}
-
-
-// virtual
-void LLInventoryCategory::packMessage(LLMessageSystem* msg) const
-{
- msg->addUUIDFast(_PREHASH_FolderID, mUUID);
- msg->addUUIDFast(_PREHASH_ParentID, mParentUUID);
- S8 type = static_cast<S8>(mPreferredType);
- msg->addS8Fast(_PREHASH_Type, type);
- msg->addStringFast(_PREHASH_Name, mName);
-}
-
-bool LLInventoryCategory::fromLLSD(const LLSD& sd)
-{
- std::string w;
-
- w = INV_FOLDER_ID_LABEL_WS;
- if (sd.has(w))
- {
- mUUID = sd[w];
- }
- w = INV_PARENT_ID_LABEL;
- if (sd.has(w))
- {
- mParentUUID = sd[w];
- }
- mThumbnailUUID.setNull();
- w = INV_THUMBNAIL_LABEL;
- if (sd.has(w))
- {
- const LLSD &thumbnail_map = sd[w];
- w = INV_ASSET_ID_LABEL;
- if (thumbnail_map.has(w))
- {
- mThumbnailUUID = thumbnail_map[w];
- }
- }
- else
- {
- w = INV_THUMBNAIL_ID_LABEL;
- if (sd.has(w))
- {
- mThumbnailUUID = sd[w];
- }
- }
- w = INV_ASSET_TYPE_LABEL;
- if (sd.has(w))
- {
- S8 type = (U8)sd[w].asInteger();
- mPreferredType = static_cast<LLFolderType::EType>(type);
- }
- w = INV_ASSET_TYPE_LABEL_WS;
- if (sd.has(w))
- {
- S8 type = (U8)sd[w].asInteger();
- mPreferredType = static_cast<LLFolderType::EType>(type);
- }
-
- w = INV_NAME_LABEL;
- if (sd.has(w))
- {
- mName = sd[w].asString();
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
- return true;
-}
-
-// virtual
-void LLInventoryCategory::unpackMessage(LLMessageSystem* msg,
- const char* block,
- S32 block_num)
-{
- msg->getUUIDFast(block, _PREHASH_FolderID, mUUID, block_num);
- msg->getUUIDFast(block, _PREHASH_ParentID, mParentUUID, block_num);
- S8 type;
- msg->getS8Fast(block, _PREHASH_Type, type, block_num);
- mPreferredType = static_cast<LLFolderType::EType>(type);
- msg->getStringFast(block, _PREHASH_Name, mName, block_num);
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
-}
-
-// virtual
-bool LLInventoryCategory::importLegacyStream(std::istream& input_stream)
-{
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[MAX_STRING]; /* Flawfinder: ignore */
- char keyword[MAX_STRING]; /* Flawfinder: ignore */
- char valuestr[MAX_STRING]; /* Flawfinder: ignore */
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
- while(input_stream.good())
- {
- input_stream.getline(buffer, MAX_STRING);
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254s",
- keyword, valuestr);
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("cat_id", keyword))
- {
- mUUID.set(valuestr);
- }
- else if(0 == strcmp("parent_id", keyword))
- {
- mParentUUID.set(valuestr);
- }
- else if(0 == strcmp("type", keyword))
- {
- mType = LLAssetType::lookup(valuestr);
- }
- else if(0 == strcmp("pref_type", keyword))
- {
- mPreferredType = LLFolderType::lookup(valuestr);
- }
- else if(0 == strcmp("name", keyword))
- {
- //strcpy(valuestr, buffer + strlen(keyword) + 3);
- // *NOTE: Not ANSI C, but widely supported.
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254[^|]",
- keyword, valuestr);
- mName.assign(valuestr);
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
- else if (0 == strcmp("metadata", keyword))
- {
- LLSD metadata;
- if (strncmp("<llsd>", valuestr, 6) == 0)
- {
- std::istringstream stream(valuestr);
- LLSDSerialize::fromXML(metadata, stream);
- }
- else
- {
- // next line likely contains metadata, but at the moment is not supported
- // can do something like:
- // LLSDSerialize::fromNotation(metadata, input_stream, -1);
- }
-
- if (metadata.has("thumbnail"))
- {
- const LLSD& thumbnail = metadata["thumbnail"];
- if (thumbnail.has("asset_id"))
- {
- setThumbnailUUID(thumbnail["asset_id"].asUUID());
- }
- else
- {
- setThumbnailUUID(LLUUID::null);
- }
- }
- else
- {
- setThumbnailUUID(LLUUID::null);
- }
- }
- else
- {
- LL_WARNS() << "unknown keyword '" << keyword
- << "' in inventory import category " << mUUID << LL_ENDL;
- }
- }
- return true;
-}
-
-bool LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, bool) const
-{
- std::string uuid_str;
- output_stream << "\tinv_category\t0\n\t{\n";
- mUUID.toString(uuid_str);
- output_stream << "\t\tcat_id\t" << uuid_str << "\n";
- mParentUUID.toString(uuid_str);
- output_stream << "\t\tparent_id\t" << uuid_str << "\n";
- output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
- output_stream << "\t\tpref_type\t" << LLFolderType::lookup(mPreferredType) << "\n";
- output_stream << "\t\tname\t" << mName.c_str() << "|\n";
- if (mThumbnailUUID.notNull())
- {
- // Only up to 255 chars
- LLSD metadata;
- metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID);
- output_stream << "\t\tmetadata\t";
- LLSDSerialize::toXML(metadata, output_stream);
- output_stream << "|\n";
- }
- output_stream << "\t}\n";
- return true;
-}
-
-LLSD LLInventoryCategory::exportLLSD() const
-{
- LLSD cat_data;
- cat_data[INV_FOLDER_ID_LABEL] = mUUID;
- cat_data[INV_PARENT_ID_LABEL] = mParentUUID;
- cat_data[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
- cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType);
- cat_data[INV_NAME_LABEL] = mName;
-
- if (mThumbnailUUID.notNull())
- {
- cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
- }
-
- return cat_data;
-}
-
-bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
-{
- if (cat_data.has(INV_FOLDER_ID_LABEL))
- {
- setUUID(cat_data[INV_FOLDER_ID_LABEL].asUUID());
- }
- if (cat_data.has(INV_PARENT_ID_LABEL))
- {
- setParent(cat_data[INV_PARENT_ID_LABEL].asUUID());
- }
- if (cat_data.has(INV_ASSET_TYPE_LABEL))
- {
- setType(LLAssetType::lookup(cat_data[INV_ASSET_TYPE_LABEL].asString()));
- }
- if (cat_data.has(INV_PREFERRED_TYPE_LABEL))
- {
- setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
- }
- if (cat_data.has(INV_THUMBNAIL_LABEL))
- {
- LLUUID thumbnail_uuid;
- const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL];
- if (thumbnail_data.has(INV_ASSET_ID_LABEL))
- {
- thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID();
- }
- setThumbnailUUID(thumbnail_uuid);
- }
- if (cat_data.has(INV_NAME_LABEL))
- {
- mName = cat_data[INV_NAME_LABEL].asString();
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
-
- return true;
-}
-///----------------------------------------------------------------------------
-/// Local function definitions
-///----------------------------------------------------------------------------
-
-LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item)
-{
- LLSD rv;
- if(item.isNull()) return rv;
- if (item->getType() == LLAssetType::AT_NONE)
- {
- LL_WARNS() << "ll_create_sd_from_inventory_item() for item with AT_NONE"
- << LL_ENDL;
- return rv;
- }
- rv[INV_ITEM_ID_LABEL] = item->getUUID();
- rv[INV_PARENT_ID_LABEL] = item->getParentUUID();
- rv[INV_NAME_LABEL] = item->getName();
- rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(item->getType());
- rv[INV_ASSET_ID_LABEL] = item->getAssetUUID();
- rv[INV_DESC_LABEL] = item->getDescription();
- rv[INV_SALE_INFO_LABEL] = ll_create_sd_from_sale_info(item->getSaleInfo());
- rv[INV_PERMISSIONS_LABEL] =
- ll_create_sd_from_permissions(item->getPermissions());
- rv[INV_INVENTORY_TYPE_LABEL] =
- LLInventoryType::lookup(item->getInventoryType());
- rv[INV_FLAGS_LABEL] = (S32)item->getFlags();
- rv[INV_CREATION_DATE_LABEL] = (S32)item->getCreationDate();
- return rv;
-}
-
-LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat)
-{
- LLSD rv;
- if(cat.isNull()) return rv;
- if (cat->getType() == LLAssetType::AT_NONE)
- {
- LL_WARNS() << "ll_create_sd_from_inventory_category() for cat with AT_NONE"
- << LL_ENDL;
- return rv;
- }
- rv[INV_FOLDER_ID_LABEL] = cat->getUUID();
- rv[INV_PARENT_ID_LABEL] = cat->getParentUUID();
- rv[INV_NAME_LABEL] = cat->getName();
- rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType());
- if(LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
- {
- rv[INV_PREFERRED_TYPE_LABEL] =
- LLFolderType::lookup(cat->getPreferredType()).c_str();
- }
- return rv;
-}
-
-LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat)
-{
- LLPointer<LLInventoryCategory> rv = new LLInventoryCategory;
- rv->setUUID(sd_cat[INV_FOLDER_ID_LABEL].asUUID());
- rv->setParent(sd_cat[INV_PARENT_ID_LABEL].asUUID());
- rv->rename(sd_cat[INV_NAME_LABEL].asString());
- rv->setType(
- LLAssetType::lookup(sd_cat[INV_ASSET_TYPE_LABEL].asString()));
- rv->setPreferredType(
- LLFolderType::lookup(
- sd_cat[INV_PREFERRED_TYPE_LABEL].asString()));
- return rv;
-}
+/** + * @file llinventory.cpp + * @brief Implementation of the inventory system. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llinventory.h" + +#include "lldbstrings.h" +#include "llfasttimer.h" +#include "llinventorydefines.h" +#include "llxorcipher.h" +#include "llsd.h" +#include "llsdserialize.h" +#include "message.h" +#include <boost/tokenizer.hpp> + +#include "llsdutil.h" + +///---------------------------------------------------------------------------- +/// Exported functions +///---------------------------------------------------------------------------- +// FIXME D567 - what's the point of these, especially if we don't even use them consistently? +static const std::string INV_ITEM_ID_LABEL("item_id"); +static const std::string INV_FOLDER_ID_LABEL("cat_id"); +static const std::string INV_PARENT_ID_LABEL("parent_id"); +static const std::string INV_THUMBNAIL_LABEL("thumbnail"); +static const std::string INV_THUMBNAIL_ID_LABEL("thumbnail_id"); +static const std::string INV_ASSET_TYPE_LABEL("type"); +static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type"); +static const std::string INV_INVENTORY_TYPE_LABEL("inv_type"); +static const std::string INV_NAME_LABEL("name"); +static const std::string INV_DESC_LABEL("desc"); +static const std::string INV_PERMISSIONS_LABEL("permissions"); +static const std::string INV_SHADOW_ID_LABEL("shadow_id"); +static const std::string INV_ASSET_ID_LABEL("asset_id"); +static const std::string INV_LINKED_ID_LABEL("linked_id"); +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 +///---------------------------------------------------------------------------- + +const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730"); + +///---------------------------------------------------------------------------- +/// Class LLInventoryObject +///---------------------------------------------------------------------------- + +LLInventoryObject::LLInventoryObject(const LLUUID& uuid, + const LLUUID& parent_uuid, + LLAssetType::EType type, + const std::string& name) +: mUUID(uuid), + mParentUUID(parent_uuid), + mType(type), + mName(name), + mCreationDate(0) +{ + correctInventoryName(mName); +} + +LLInventoryObject::LLInventoryObject() +: mType(LLAssetType::AT_NONE), + mCreationDate(0) +{ +} + +LLInventoryObject::~LLInventoryObject() +{ +} + +void LLInventoryObject::copyObject(const LLInventoryObject* other) +{ + mUUID = other->mUUID; + mParentUUID = other->mParentUUID; + mType = other->mType; + mName = other->mName; + mThumbnailUUID = other->mThumbnailUUID; +} + +const LLUUID& LLInventoryObject::getUUID() const +{ + return mUUID; +} + +const LLUUID& LLInventoryObject::getParentUUID() const +{ + return mParentUUID; +} + +const LLUUID& LLInventoryObject::getThumbnailUUID() const +{ + return mThumbnailUUID; +} + +const std::string& LLInventoryObject::getName() const +{ + return mName; +} + +// To bypass linked items, since llviewerinventory's getType +// will return the linked-to item's type instead of this object's type. +LLAssetType::EType LLInventoryObject::getActualType() const +{ + return mType; +} + +bool LLInventoryObject::getIsLinkType() const +{ + return LLAssetType::lookupIsLinkType(mType); +} + +// See LLInventoryItem override. +// virtual +const LLUUID& LLInventoryObject::getLinkedUUID() const +{ + return mUUID; +} + +LLAssetType::EType LLInventoryObject::getType() const +{ + return mType; +} + +void LLInventoryObject::setUUID(const LLUUID& new_uuid) +{ + mUUID = new_uuid; +} + +void LLInventoryObject::rename(const std::string& n) +{ + std::string new_name(n); + correctInventoryName(new_name); + if( !new_name.empty() && new_name != mName ) + { + mName = new_name; + } +} + +void LLInventoryObject::setParent(const LLUUID& new_parent) +{ + mParentUUID = new_parent; +} + +void LLInventoryObject::setThumbnailUUID(const LLUUID& thumbnail_uuid) +{ + mThumbnailUUID = thumbnail_uuid; +} + +void LLInventoryObject::setType(LLAssetType::EType type) +{ + mType = type; +} + + +// virtual +bool LLInventoryObject::importLegacyStream(std::istream& input_stream) +{ + // *NOTE: Changing the buffer size will require changing the scanf + // calls below. + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + char keyword[MAX_STRING]; /* Flawfinder: ignore */ + char valuestr[MAX_STRING]; /* Flawfinder: ignore */ + + keyword[0] = '\0'; + valuestr[0] = '\0'; + while(input_stream.good()) + { + input_stream.getline(buffer, MAX_STRING); + sscanf(buffer, " %254s %254s", keyword, valuestr); /* Flawfinder: ignore */ + if(0 == strcmp("{",keyword)) + { + continue; + } + if(0 == strcmp("}", keyword)) + { + break; + } + else if(0 == strcmp("obj_id", keyword)) + { + mUUID.set(valuestr); + } + else if(0 == strcmp("parent_id", keyword)) + { + mParentUUID.set(valuestr); + } + else if(0 == strcmp("type", keyword)) + { + mType = LLAssetType::lookup(valuestr); + } + else if (0 == strcmp("metadata", keyword)) + { + LLSD metadata; + if (strncmp("<llsd>", valuestr, 6) == 0) + { + std::istringstream stream(valuestr); + LLSDSerialize::fromXML(metadata, stream); + } + else + { + // next line likely contains metadata, but at the moment is not supported + // can do something like: + // LLSDSerialize::fromNotation(metadata, input_stream, -1); + } + + if (metadata.has("thumbnail")) + { + const LLSD& thumbnail = metadata["thumbnail"]; + if (thumbnail.has("asset_id")) + { + setThumbnailUUID(thumbnail["asset_id"].asUUID()); + } + else + { + setThumbnailUUID(LLUUID::null); + } + } + else + { + setThumbnailUUID(LLUUID::null); + } + } + else if(0 == strcmp("name", keyword)) + { + //strcpy(valuestr, buffer + strlen(keyword) + 3); + // *NOTE: Not ANSI C, but widely supported. + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s %254[^|]", + keyword, valuestr); + mName.assign(valuestr); + correctInventoryName(mName); + } + else + { + LL_WARNS() << "unknown keyword '" << keyword + << "' in LLInventoryObject::importLegacyStream() for object " << mUUID << LL_ENDL; + } + } + return true; +} + +bool LLInventoryObject::exportLegacyStream(std::ostream& output_stream, bool) const +{ + std::string uuid_str; + output_stream << "\tinv_object\t0\n\t{\n"; + mUUID.toString(uuid_str); + output_stream << "\t\tobj_id\t" << uuid_str << "\n"; + mParentUUID.toString(uuid_str); + output_stream << "\t\tparent_id\t" << uuid_str << "\n"; + output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; + output_stream << "\t\tname\t" << mName.c_str() << "|\n"; + output_stream << "\t}\n"; + return true; +} + +void LLInventoryObject::updateParentOnServer(bool) const +{ + // don't do nothin' + LL_WARNS() << "LLInventoryObject::updateParentOnServer() called. Doesn't do anything." << LL_ENDL; +} + +void LLInventoryObject::updateServer(bool) const +{ + // don't do nothin' + LL_WARNS() << "LLInventoryObject::updateServer() called. Doesn't do anything." << LL_ENDL; +} + +// static +void LLInventoryObject::correctInventoryName(std::string& name) +{ + LLStringUtil::replaceNonstandardASCII(name, ' '); + LLStringUtil::replaceChar(name, '|', ' '); + LLStringUtil::trim(name); + LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN); +} + +time_t LLInventoryObject::getCreationDate() const +{ + return mCreationDate; +} + +void LLInventoryObject::setCreationDate(time_t creation_date_utc) +{ + mCreationDate = creation_date_utc; +} + + +const std::string& LLInventoryItem::getDescription() const +{ + return mDescription; +} + +const std::string& LLInventoryItem::getActualDescription() const +{ + return mDescription; +} + +///---------------------------------------------------------------------------- +/// Class LLInventoryItem +///---------------------------------------------------------------------------- + +LLInventoryItem::LLInventoryItem(const LLUUID& uuid, + const LLUUID& parent_uuid, + const LLPermissions& permissions, + const LLUUID& asset_uuid, + LLAssetType::EType type, + LLInventoryType::EType inv_type, + const std::string& name, + const std::string& desc, + const LLSaleInfo& sale_info, + U32 flags, + S32 creation_date_utc) : + LLInventoryObject(uuid, parent_uuid, type, name), + mPermissions(permissions), + mAssetUUID(asset_uuid), + mDescription(desc), + mSaleInfo(sale_info), + mInventoryType(inv_type), + mFlags(flags) +{ + mCreationDate = creation_date_utc; + + LLStringUtil::replaceNonstandardASCII(mDescription, ' '); + LLStringUtil::replaceChar(mDescription, '|', ' '); + + mPermissions.initMasks(inv_type); +} + +LLInventoryItem::LLInventoryItem() : + LLInventoryObject(), + mPermissions(), + mAssetUUID(), + mDescription(), + mSaleInfo(), + mInventoryType(LLInventoryType::IT_NONE), + mFlags(0) +{ + mCreationDate = 0; +} + +LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) : + LLInventoryObject() +{ + copyItem(other); +} + +LLInventoryItem::~LLInventoryItem() +{ +} + +// virtual +void LLInventoryItem::copyItem(const LLInventoryItem* other) +{ + copyObject(other); + mPermissions = other->mPermissions; + mAssetUUID = other->mAssetUUID; + mThumbnailUUID = other->mThumbnailUUID; + mDescription = other->mDescription; + mSaleInfo = other->mSaleInfo; + mInventoryType = other->mInventoryType; + mFlags = other->mFlags; + mCreationDate = other->mCreationDate; +} + +// If this is a linked item, then the UUID of the base object is +// this item's assetID. +// virtual +const LLUUID& LLInventoryItem::getLinkedUUID() const +{ + if (LLAssetType::lookupIsLinkType(getActualType())) + { + return mAssetUUID; + } + + return LLInventoryObject::getLinkedUUID(); +} + +const LLPermissions& LLInventoryItem::getPermissions() const +{ + return mPermissions; +} + +const LLUUID& LLInventoryItem::getCreatorUUID() const +{ + return mPermissions.getCreator(); +} + +const LLUUID& LLInventoryItem::getAssetUUID() const +{ + return mAssetUUID; +} + +void LLInventoryItem::setAssetUUID(const LLUUID& asset_id) +{ + mAssetUUID = asset_id; +} + + +U32 LLInventoryItem::getCRC32() const +{ + // *FIX: Not a real crc - more of a checksum. + // *NOTE: We currently do not validate the name or description, + // but if they change in transit, it's no big deal. + U32 crc = mUUID.getCRC32(); + //LL_DEBUGS() << "1 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mParentUUID.getCRC32(); + //LL_DEBUGS() << "2 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mPermissions.getCRC32(); + //LL_DEBUGS() << "3 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mAssetUUID.getCRC32(); + //LL_DEBUGS() << "4 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mType; + //LL_DEBUGS() << "5 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mInventoryType; + //LL_DEBUGS() << "6 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mFlags; + //LL_DEBUGS() << "7 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mSaleInfo.getCRC32(); + //LL_DEBUGS() << "8 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += (U32)mCreationDate; + //LL_DEBUGS() << "9 crc: " << std::hex << crc << std::dec << LL_ENDL; + crc += mThumbnailUUID.getCRC32(); + return crc; +} + +// static +void LLInventoryItem::correctInventoryDescription(std::string& desc) +{ + LLStringUtil::replaceNonstandardASCII(desc, ' '); + LLStringUtil::replaceChar(desc, '|', ' '); +} + +void LLInventoryItem::setDescription(const std::string& d) +{ + std::string new_desc(d); + LLInventoryItem::correctInventoryDescription(new_desc); + if( new_desc != mDescription ) + { + mDescription = new_desc; + } +} + +void LLInventoryItem::setPermissions(const LLPermissions& perm) +{ + mPermissions = perm; + + // Override permissions to unrestricted if this is a landmark + mPermissions.initMasks(mInventoryType); +} + +void LLInventoryItem::setInventoryType(LLInventoryType::EType inv_type) +{ + mInventoryType = inv_type; +} + +void LLInventoryItem::setFlags(U32 flags) +{ + mFlags = flags; +} + +// Currently only used in the Viewer to handle calling cards +// where the creator is actually used to store the target. +void LLInventoryItem::setCreator(const LLUUID& creator) +{ + mPermissions.setCreator(creator); +} + +void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item) +{ + // Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags + // because we now detect when they should be set. + setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItemFlags::II_FLAGS_PERM_OVERWRITE_MASK)) ); + + // Enforce the PERM_OVERWRITE flags for any masks that are different + // but only for AT_OBJECT's since that is the only asset type that can + // exist in-world (instead of only in-inventory or in-object-contents). + if (LLAssetType::AT_OBJECT == getType()) + { + LLPermissions old_permissions = old_item.getPermissions(); + U32 flags_to_be_set = 0; + if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner()) + { + flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_PERM; + } + if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone()) + { + flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE; + } + if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup()) + { + flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP; + } + LLSaleInfo old_sale_info = old_item.getSaleInfo(); + if(old_sale_info != getSaleInfo()) + { + flags_to_be_set |= LLInventoryItemFlags::II_FLAGS_OBJECT_SLAM_SALE; + } + setFlags(getFlags() | flags_to_be_set); + } +} + +const LLSaleInfo& LLInventoryItem::getSaleInfo() const +{ + return mSaleInfo; +} + +void LLInventoryItem::setSaleInfo(const LLSaleInfo& sale_info) +{ + mSaleInfo = sale_info; +} + +LLInventoryType::EType LLInventoryItem::getInventoryType() const +{ + return mInventoryType; +} + +U32 LLInventoryItem::getFlags() const +{ + return mFlags; +} + +time_t LLInventoryItem::getCreationDate() const +{ + return mCreationDate; +} + + +// virtual +void LLInventoryItem::packMessage(LLMessageSystem* msg) const +{ + msg->addUUIDFast(_PREHASH_ItemID, mUUID); + msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); + mPermissions.packMessage(msg); + msg->addUUIDFast(_PREHASH_AssetID, mAssetUUID); + S8 type = static_cast<S8>(mType); + msg->addS8Fast(_PREHASH_Type, type); + type = static_cast<S8>(mInventoryType); + msg->addS8Fast(_PREHASH_InvType, type); + msg->addU32Fast(_PREHASH_Flags, mFlags); + mSaleInfo.packMessage(msg); + msg->addStringFast(_PREHASH_Name, mName); + msg->addStringFast(_PREHASH_Description, mDescription); + msg->addS32Fast(_PREHASH_CreationDate, (S32)mCreationDate); + U32 crc = getCRC32(); + msg->addU32Fast(_PREHASH_CRC, crc); +} + +// virtual +bool LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) +{ + msg->getUUIDFast(block, _PREHASH_ItemID, mUUID, block_num); + msg->getUUIDFast(block, _PREHASH_FolderID, mParentUUID, block_num); + mPermissions.unpackMessage(msg, block, block_num); + msg->getUUIDFast(block, _PREHASH_AssetID, mAssetUUID, block_num); + + S8 type; + msg->getS8Fast(block, _PREHASH_Type, type, block_num); + mType = static_cast<LLAssetType::EType>(type); + msg->getS8(block, "InvType", type, block_num); + mInventoryType = static_cast<LLInventoryType::EType>(type); + mPermissions.initMasks(mInventoryType); + + msg->getU32Fast(block, _PREHASH_Flags, mFlags, block_num); + + mSaleInfo.unpackMultiMessage(msg, block, block_num); + + msg->getStringFast(block, _PREHASH_Name, mName, block_num); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + + msg->getStringFast(block, _PREHASH_Description, mDescription, block_num); + LLStringUtil::replaceNonstandardASCII(mDescription, ' '); + + S32 date; + msg->getS32(block, "CreationDate", date, block_num); + mCreationDate = date; + + U32 local_crc = getCRC32(); + U32 remote_crc = 0; + msg->getU32(block, "CRC", remote_crc, block_num); +//#define CRC_CHECK +#ifdef CRC_CHECK + if(local_crc == remote_crc) + { + LL_DEBUGS() << "crc matches" << LL_ENDL; + return true; + } + else + { + LL_WARNS() << "inventory crc mismatch: local=" << std::hex << local_crc + << " remote=" << remote_crc << std::dec << LL_ENDL; + return false; + } +#else + return (local_crc == remote_crc); +#endif +} + +// virtual +bool LLInventoryItem::importLegacyStream(std::istream& input_stream) +{ + // *NOTE: Changing the buffer size will require changing the scanf + // calls below. + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + char keyword[MAX_STRING]; /* Flawfinder: ignore */ + char valuestr[MAX_STRING]; /* Flawfinder: ignore */ + char junk[MAX_STRING]; /* Flawfinder: ignore */ + bool success = true; + + keyword[0] = '\0'; + valuestr[0] = '\0'; + + mInventoryType = LLInventoryType::IT_NONE; + mAssetUUID.setNull(); + while(success && input_stream.good()) + { + input_stream.getline(buffer, MAX_STRING); + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s %254s", + keyword, valuestr); + if(0 == strcmp("{",keyword)) + { + continue; + } + if(0 == strcmp("}", keyword)) + { + break; + } + else if(0 == strcmp("item_id", keyword)) + { + mUUID.set(valuestr); + } + else if(0 == strcmp("parent_id", keyword)) + { + mParentUUID.set(valuestr); + } + else if(0 == strcmp("permissions", keyword)) + { + success = mPermissions.importLegacyStream(input_stream); + } + else if(0 == strcmp("sale_info", keyword)) + { + // Sale info used to contain next owner perm. It is now in + // the permissions. Thus, we read that out, and fix legacy + // objects. It's possible this op would fail, but it + // should pick up the vast majority of the tasks. + bool has_perm_mask = false; + U32 perm_mask = 0; + success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask); + if(has_perm_mask) + { + if(perm_mask == PERM_NONE) + { + perm_mask = mPermissions.getMaskOwner(); + } + // fair use fix. + if(!(perm_mask & PERM_COPY)) + { + perm_mask |= PERM_TRANSFER; + } + mPermissions.setMaskNext(perm_mask); + } + } + else if(0 == strcmp("shadow_id", keyword)) + { + mAssetUUID.set(valuestr); + LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); + cipher.decrypt(mAssetUUID.mData, UUID_BYTES); + } + else if(0 == strcmp("asset_id", keyword)) + { + mAssetUUID.set(valuestr); + } + else if(0 == strcmp("type", keyword)) + { + mType = LLAssetType::lookup(valuestr); + } + else if (0 == strcmp("metadata", keyword)) + { + LLSD metadata; + if (strncmp("<llsd>", valuestr, 6) == 0) + { + std::istringstream stream(valuestr); + LLSDSerialize::fromXML(metadata, stream); + } + else + { + // next line likely contains metadata, but at the moment is not supported + // can do something like: + // LLSDSerialize::fromNotation(metadata, input_stream, -1); + } + + if (metadata.has("thumbnail")) + { + const LLSD& thumbnail = metadata["thumbnail"]; + if (thumbnail.has("asset_id")) + { + setThumbnailUUID(thumbnail["asset_id"].asUUID()); + } + else + { + setThumbnailUUID(LLUUID::null); + } + } + else + { + setThumbnailUUID(LLUUID::null); + } + } + else if(0 == strcmp("inv_type", keyword)) + { + mInventoryType = LLInventoryType::lookup(std::string(valuestr)); + } + else if(0 == strcmp("flags", keyword)) + { + sscanf(valuestr, "%x", &mFlags); + } + else if(0 == strcmp("name", keyword)) + { + //strcpy(valuestr, buffer + strlen(keyword) + 3); + // *NOTE: Not ANSI C, but widely supported. + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s%254[\t]%254[^|]", + keyword, junk, valuestr); + + // IW: sscanf chokes and puts | in valuestr if there's no name + if (valuestr[0] == '|') + { + valuestr[0] = '\000'; + } + + mName.assign(valuestr); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + LLStringUtil::replaceChar(mName, '|', ' '); + } + else if(0 == strcmp("desc", keyword)) + { + //strcpy(valuestr, buffer + strlen(keyword) + 3); + // *NOTE: Not ANSI C, but widely supported. + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s%254[\t]%254[^|]", + keyword, junk, valuestr); + + if (valuestr[0] == '|') + { + valuestr[0] = '\000'; + } + + mDescription.assign(valuestr); + LLStringUtil::replaceNonstandardASCII(mDescription, ' '); + /* TODO -- ask Ian about this code + const char *donkey = mDescription.c_str(); + if (donkey[0] == '|') + { + LL_ERRS() << "Donkey" << LL_ENDL; + } + */ + } + else if(0 == strcmp("creation_date", keyword)) + { + S32 date; + sscanf(valuestr, "%d", &date); + mCreationDate = date; + } + else + { + LL_WARNS() << "unknown keyword '" << keyword + << "' in inventory import of item " << mUUID << LL_ENDL; + } + } + + // Need to convert 1.0 simstate files to a useful inventory type + // and potentially deal with bad inventory tyes eg, a landmark + // marked as a texture. + if((LLInventoryType::IT_NONE == mInventoryType) + || !inventory_and_asset_types_match(mInventoryType, mType)) + { + LL_DEBUGS() << "Resetting inventory type for " << mUUID << LL_ENDL; + mInventoryType = LLInventoryType::defaultForAssetType(mType); + } + + mPermissions.initMasks(mInventoryType); + + return success; +} + +bool LLInventoryItem::exportLegacyStream(std::ostream& output_stream, bool include_asset_key) const +{ + std::string uuid_str; + output_stream << "\tinv_item\t0\n\t{\n"; + mUUID.toString(uuid_str); + output_stream << "\t\titem_id\t" << uuid_str << "\n"; + mParentUUID.toString(uuid_str); + output_stream << "\t\tparent_id\t" << uuid_str << "\n"; + mPermissions.exportLegacyStream(output_stream); + + if (mThumbnailUUID.notNull()) + { + // Max length is 255 chars, will have to export differently if it gets more data + // Ex: use newline and toNotation (uses {}) for unlimited size + LLSD metadata; + metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID); + + output_stream << "\t\tmetadata\t"; + LLSDSerialize::toXML(metadata, output_stream); + output_stream << "|\n"; + } + + // Check for permissions to see the asset id, and if so write it + // out as an asset id. Otherwise, apply our cheesy encryption. + if(include_asset_key) + { + U32 mask = mPermissions.getMaskBase(); + if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) + || (mAssetUUID.isNull())) + { + mAssetUUID.toString(uuid_str); + output_stream << "\t\tasset_id\t" << uuid_str << "\n"; + } + else + { + LLUUID shadow_id(mAssetUUID); + LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); + cipher.encrypt(shadow_id.mData, UUID_BYTES); + shadow_id.toString(uuid_str); + output_stream << "\t\tshadow_id\t" << uuid_str << "\n"; + } + } + else + { + LLUUID::null.toString(uuid_str); + output_stream << "\t\tasset_id\t" << uuid_str << "\n"; + } + output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) + output_stream << "\t\tinv_type\t" << inv_type_str << "\n"; + std::string buffer; + buffer = llformat( "\t\tflags\t%08x\n", mFlags); + output_stream << buffer; + mSaleInfo.exportLegacyStream(output_stream); + output_stream << "\t\tname\t" << mName.c_str() << "|\n"; + output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n"; + output_stream << "\t\tcreation_date\t" << mCreationDate << "\n"; + output_stream << "\t}\n"; + return true; +} + +LLSD LLInventoryItem::asLLSD() const +{ + LLSD sd = LLSD(); + asLLSD(sd); + return sd; +} + +void LLInventoryItem::asLLSD( LLSD& sd ) const +{ + sd[INV_ITEM_ID_LABEL] = mUUID; + sd[INV_PARENT_ID_LABEL] = mParentUUID; + sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions); + + if (mThumbnailUUID.notNull()) + { + sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); + } + + U32 mask = mPermissions.getMaskBase(); + if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) + || (mAssetUUID.isNull())) + { + sd[INV_ASSET_ID_LABEL] = mAssetUUID; + } + else + { + // *TODO: get rid of this. Phoenix 2008-01-30 + LLUUID shadow_id(mAssetUUID); + LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); + cipher.encrypt(shadow_id.mData, UUID_BYTES); + sd[INV_SHADOW_ID_LABEL] = shadow_id; + } + sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType); + sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType; + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) + { + 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; + sd[INV_DESC_LABEL] = mDescription; + sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate; +} + +bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) +{ + LL_PROFILE_ZONE_SCOPED; + if (is_new) + { + // If we're adding LLSD to an existing object, need avoid + // clobbering these fields. + mInventoryType = LLInventoryType::IT_NONE; + mAssetUUID.setNull(); + } + + // TODO - figure out if this should be moved into the noclobber fields above + mThumbnailUUID.setNull(); + + // iterate as map to avoid making unnecessary temp copies of everything + LLSD::map_const_iterator i, end; + end = sd.endMap(); + for (i = sd.beginMap(); i != end; ++i) + { + if (i->first == INV_ITEM_ID_LABEL) + { + mUUID = i->second; + continue; + } + + if (i->first == INV_PARENT_ID_LABEL) + { + mParentUUID = i->second; + continue; + } + + if (i->first == INV_THUMBNAIL_LABEL) + { + const LLSD &thumbnail_map = i->second; + const std::string w = INV_ASSET_ID_LABEL; + if (thumbnail_map.has(w)) + { + mThumbnailUUID = thumbnail_map[w]; + } + /* Example: + <key> asset_id </key> + <uuid> acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 </uuid> + <key> perms </key> + <integer> 8 </integer> + <key>service</key> + <integer> 3 </integer> + <key>version</key> + <integer> 1 </key> + */ + continue; + } + + if (i->first == INV_THUMBNAIL_ID_LABEL) + { + mThumbnailUUID = i->second.asUUID(); + continue; + } + + if (i->first == INV_PERMISSIONS_LABEL) + { + mPermissions = ll_permissions_from_sd(i->second); + continue; + } + + if (i->first == INV_SALE_INFO_LABEL) + { + // Sale info used to contain next owner perm. It is now in + // the permissions. Thus, we read that out, and fix legacy + // objects. It's possible this op would fail, but it + // should pick up the vast majority of the tasks. + bool has_perm_mask = false; + U32 perm_mask = 0; + if (!mSaleInfo.fromLLSD(i->second, has_perm_mask, perm_mask)) + { + return false; + } + if (has_perm_mask) + { + if (perm_mask == PERM_NONE) + { + perm_mask = mPermissions.getMaskOwner(); + } + // fair use fix. + if (!(perm_mask & PERM_COPY)) + { + perm_mask |= PERM_TRANSFER; + } + mPermissions.setMaskNext(perm_mask); + } + continue; + } + + if (i->first == INV_SHADOW_ID_LABEL) + { + mAssetUUID = i->second; + LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); + cipher.decrypt(mAssetUUID.mData, UUID_BYTES); + continue; + } + + if (i->first == INV_ASSET_ID_LABEL) + { + mAssetUUID = i->second; + continue; + } + + if (i->first == INV_LINKED_ID_LABEL) + { + mAssetUUID = i->second; + continue; + } + + if (i->first == INV_ASSET_TYPE_LABEL) + { + LLSD const &label = i->second; + if (label.isString()) + { + mType = LLAssetType::lookup(label.asString().c_str()); + } + else if (label.isInteger()) + { + S8 type = (U8) label.asInteger(); + mType = static_cast<LLAssetType::EType>(type); + } + continue; + } + + if (i->first == INV_INVENTORY_TYPE_LABEL) + { + LLSD const &label = i->second; + if (label.isString()) + { + mInventoryType = LLInventoryType::lookup(label.asString().c_str()); + } + else if (label.isInteger()) + { + S8 type = (U8) label.asInteger(); + mInventoryType = static_cast<LLInventoryType::EType>(type); + } + continue; + } + + if (i->first == INV_FLAGS_LABEL) + { + LLSD const &label = i->second; + if (label.isBinary()) + { + mFlags = ll_U32_from_sd(label); + } + else if (label.isInteger()) + { + mFlags = label.asInteger(); + } + continue; + } + + if (i->first == INV_NAME_LABEL) + { + mName = i->second.asString(); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + LLStringUtil::replaceChar(mName, '|', ' '); + continue; + } + + if (i->first == INV_DESC_LABEL) + { + mDescription = i->second.asString(); + LLStringUtil::replaceNonstandardASCII(mDescription, ' '); + continue; + } + + if (i->first == INV_CREATION_DATE_LABEL) + { + mCreationDate = i->second.asInteger(); + continue; + } + } + + // Need to convert 1.0 simstate files to a useful inventory type + // and potentially deal with bad inventory tyes eg, a landmark + // marked as a texture. + if((LLInventoryType::IT_NONE == mInventoryType) + || !inventory_and_asset_types_match(mInventoryType, mType)) + { + LL_DEBUGS() << "Resetting inventory type for " << mUUID << LL_ENDL; + mInventoryType = LLInventoryType::defaultForAssetType(mType); + } + + mPermissions.initMasks(mInventoryType); + + return true; +} + +///---------------------------------------------------------------------------- +/// Class LLInventoryCategory +///---------------------------------------------------------------------------- + +LLInventoryCategory::LLInventoryCategory(const LLUUID& uuid, + const LLUUID& parent_uuid, + LLFolderType::EType preferred_type, + const std::string& name) : + LLInventoryObject(uuid, parent_uuid, LLAssetType::AT_CATEGORY, name), + mPreferredType(preferred_type) +{ +} + +LLInventoryCategory::LLInventoryCategory() : + mPreferredType(LLFolderType::FT_NONE) +{ + mType = LLAssetType::AT_CATEGORY; +} + +LLInventoryCategory::LLInventoryCategory(const LLInventoryCategory* other) : + LLInventoryObject() +{ + copyCategory(other); +} + +LLInventoryCategory::~LLInventoryCategory() +{ +} + +// virtual +void LLInventoryCategory::copyCategory(const LLInventoryCategory* other) +{ + copyObject(other); + mPreferredType = other->mPreferredType; +} + +LLFolderType::EType LLInventoryCategory::getPreferredType() const +{ + return mPreferredType; +} + +void LLInventoryCategory::setPreferredType(LLFolderType::EType type) +{ + mPreferredType = type; +} + +LLSD LLInventoryCategory::asLLSD() const +{ + LLSD sd = LLSD(); + sd[INV_ITEM_ID_LABEL] = mUUID; + sd[INV_PARENT_ID_LABEL] = mParentUUID; + S8 type = static_cast<S8>(mPreferredType); + sd[INV_ASSET_TYPE_LABEL] = type; + sd[INV_NAME_LABEL] = mName; + + if (mThumbnailUUID.notNull()) + { + sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); + } + + return sd; +} + +LLSD LLInventoryCategory::asAISCreateCatLLSD() const +{ + LLSD sd = LLSD(); + sd[INV_FOLDER_ID_LABEL_WS] = mUUID; + sd[INV_PARENT_ID_LABEL] = mParentUUID; + S8 type = static_cast<S8>(mPreferredType); + sd[INV_ASSET_TYPE_LABEL_WS] = type; + sd[INV_NAME_LABEL] = mName; + if (mThumbnailUUID.notNull()) + { + sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); + } + + return sd; +} + + +// virtual +void LLInventoryCategory::packMessage(LLMessageSystem* msg) const +{ + msg->addUUIDFast(_PREHASH_FolderID, mUUID); + msg->addUUIDFast(_PREHASH_ParentID, mParentUUID); + S8 type = static_cast<S8>(mPreferredType); + msg->addS8Fast(_PREHASH_Type, type); + msg->addStringFast(_PREHASH_Name, mName); +} + +bool LLInventoryCategory::fromLLSD(const LLSD& sd) +{ + std::string w; + + w = INV_FOLDER_ID_LABEL_WS; + if (sd.has(w)) + { + mUUID = sd[w]; + } + w = INV_PARENT_ID_LABEL; + if (sd.has(w)) + { + mParentUUID = sd[w]; + } + mThumbnailUUID.setNull(); + w = INV_THUMBNAIL_LABEL; + if (sd.has(w)) + { + const LLSD &thumbnail_map = sd[w]; + w = INV_ASSET_ID_LABEL; + if (thumbnail_map.has(w)) + { + mThumbnailUUID = thumbnail_map[w]; + } + } + else + { + w = INV_THUMBNAIL_ID_LABEL; + if (sd.has(w)) + { + mThumbnailUUID = sd[w]; + } + } + w = INV_ASSET_TYPE_LABEL; + if (sd.has(w)) + { + S8 type = (U8)sd[w].asInteger(); + mPreferredType = static_cast<LLFolderType::EType>(type); + } + w = INV_ASSET_TYPE_LABEL_WS; + if (sd.has(w)) + { + S8 type = (U8)sd[w].asInteger(); + mPreferredType = static_cast<LLFolderType::EType>(type); + } + + w = INV_NAME_LABEL; + if (sd.has(w)) + { + mName = sd[w].asString(); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + LLStringUtil::replaceChar(mName, '|', ' '); + } + return true; +} + +// virtual +void LLInventoryCategory::unpackMessage(LLMessageSystem* msg, + const char* block, + S32 block_num) +{ + msg->getUUIDFast(block, _PREHASH_FolderID, mUUID, block_num); + msg->getUUIDFast(block, _PREHASH_ParentID, mParentUUID, block_num); + S8 type; + msg->getS8Fast(block, _PREHASH_Type, type, block_num); + mPreferredType = static_cast<LLFolderType::EType>(type); + msg->getStringFast(block, _PREHASH_Name, mName, block_num); + LLStringUtil::replaceNonstandardASCII(mName, ' '); +} + +// virtual +bool LLInventoryCategory::importLegacyStream(std::istream& input_stream) +{ + // *NOTE: Changing the buffer size will require changing the scanf + // calls below. + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + char keyword[MAX_STRING]; /* Flawfinder: ignore */ + char valuestr[MAX_STRING]; /* Flawfinder: ignore */ + + keyword[0] = '\0'; + valuestr[0] = '\0'; + while(input_stream.good()) + { + input_stream.getline(buffer, MAX_STRING); + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s %254s", + keyword, valuestr); + if(0 == strcmp("{",keyword)) + { + continue; + } + if(0 == strcmp("}", keyword)) + { + break; + } + else if(0 == strcmp("cat_id", keyword)) + { + mUUID.set(valuestr); + } + else if(0 == strcmp("parent_id", keyword)) + { + mParentUUID.set(valuestr); + } + else if(0 == strcmp("type", keyword)) + { + mType = LLAssetType::lookup(valuestr); + } + else if(0 == strcmp("pref_type", keyword)) + { + mPreferredType = LLFolderType::lookup(valuestr); + } + else if(0 == strcmp("name", keyword)) + { + //strcpy(valuestr, buffer + strlen(keyword) + 3); + // *NOTE: Not ANSI C, but widely supported. + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s %254[^|]", + keyword, valuestr); + mName.assign(valuestr); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + LLStringUtil::replaceChar(mName, '|', ' '); + } + else if (0 == strcmp("metadata", keyword)) + { + LLSD metadata; + if (strncmp("<llsd>", valuestr, 6) == 0) + { + std::istringstream stream(valuestr); + LLSDSerialize::fromXML(metadata, stream); + } + else + { + // next line likely contains metadata, but at the moment is not supported + // can do something like: + // LLSDSerialize::fromNotation(metadata, input_stream, -1); + } + + if (metadata.has("thumbnail")) + { + const LLSD& thumbnail = metadata["thumbnail"]; + if (thumbnail.has("asset_id")) + { + setThumbnailUUID(thumbnail["asset_id"].asUUID()); + } + else + { + setThumbnailUUID(LLUUID::null); + } + } + else + { + setThumbnailUUID(LLUUID::null); + } + } + else + { + LL_WARNS() << "unknown keyword '" << keyword + << "' in inventory import category " << mUUID << LL_ENDL; + } + } + return true; +} + +bool LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, bool) const +{ + std::string uuid_str; + output_stream << "\tinv_category\t0\n\t{\n"; + mUUID.toString(uuid_str); + output_stream << "\t\tcat_id\t" << uuid_str << "\n"; + mParentUUID.toString(uuid_str); + output_stream << "\t\tparent_id\t" << uuid_str << "\n"; + output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; + output_stream << "\t\tpref_type\t" << LLFolderType::lookup(mPreferredType) << "\n"; + output_stream << "\t\tname\t" << mName.c_str() << "|\n"; + if (mThumbnailUUID.notNull()) + { + // Only up to 255 chars + LLSD metadata; + metadata["thumbnail"] = LLSD().with("asset_id", mThumbnailUUID); + output_stream << "\t\tmetadata\t"; + LLSDSerialize::toXML(metadata, output_stream); + output_stream << "|\n"; + } + output_stream << "\t}\n"; + return true; +} + +LLSD LLInventoryCategory::exportLLSD() const +{ + LLSD cat_data; + cat_data[INV_FOLDER_ID_LABEL] = mUUID; + cat_data[INV_PARENT_ID_LABEL] = mParentUUID; + cat_data[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType); + cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType); + cat_data[INV_NAME_LABEL] = mName; + + if (mThumbnailUUID.notNull()) + { + cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); + } + + return cat_data; +} + +bool LLInventoryCategory::importLLSD(const LLSD& cat_data) +{ + if (cat_data.has(INV_FOLDER_ID_LABEL)) + { + setUUID(cat_data[INV_FOLDER_ID_LABEL].asUUID()); + } + if (cat_data.has(INV_PARENT_ID_LABEL)) + { + setParent(cat_data[INV_PARENT_ID_LABEL].asUUID()); + } + if (cat_data.has(INV_ASSET_TYPE_LABEL)) + { + setType(LLAssetType::lookup(cat_data[INV_ASSET_TYPE_LABEL].asString())); + } + if (cat_data.has(INV_PREFERRED_TYPE_LABEL)) + { + setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString())); + } + if (cat_data.has(INV_THUMBNAIL_LABEL)) + { + LLUUID thumbnail_uuid; + const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL]; + if (thumbnail_data.has(INV_ASSET_ID_LABEL)) + { + thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID(); + } + setThumbnailUUID(thumbnail_uuid); + } + if (cat_data.has(INV_NAME_LABEL)) + { + mName = cat_data[INV_NAME_LABEL].asString(); + LLStringUtil::replaceNonstandardASCII(mName, ' '); + LLStringUtil::replaceChar(mName, '|', ' '); + } + + return true; +} +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- + +LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item) +{ + LLSD rv; + if(item.isNull()) return rv; + if (item->getType() == LLAssetType::AT_NONE) + { + LL_WARNS() << "ll_create_sd_from_inventory_item() for item with AT_NONE" + << LL_ENDL; + return rv; + } + rv[INV_ITEM_ID_LABEL] = item->getUUID(); + rv[INV_PARENT_ID_LABEL] = item->getParentUUID(); + rv[INV_NAME_LABEL] = item->getName(); + rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(item->getType()); + rv[INV_ASSET_ID_LABEL] = item->getAssetUUID(); + rv[INV_DESC_LABEL] = item->getDescription(); + rv[INV_SALE_INFO_LABEL] = ll_create_sd_from_sale_info(item->getSaleInfo()); + rv[INV_PERMISSIONS_LABEL] = + ll_create_sd_from_permissions(item->getPermissions()); + rv[INV_INVENTORY_TYPE_LABEL] = + LLInventoryType::lookup(item->getInventoryType()); + rv[INV_FLAGS_LABEL] = (S32)item->getFlags(); + rv[INV_CREATION_DATE_LABEL] = (S32)item->getCreationDate(); + return rv; +} + +LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat) +{ + LLSD rv; + if(cat.isNull()) return rv; + if (cat->getType() == LLAssetType::AT_NONE) + { + LL_WARNS() << "ll_create_sd_from_inventory_category() for cat with AT_NONE" + << LL_ENDL; + return rv; + } + rv[INV_FOLDER_ID_LABEL] = cat->getUUID(); + rv[INV_PARENT_ID_LABEL] = cat->getParentUUID(); + rv[INV_NAME_LABEL] = cat->getName(); + rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType()); + if(LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + rv[INV_PREFERRED_TYPE_LABEL] = + LLFolderType::lookup(cat->getPreferredType()).c_str(); + } + return rv; +} + +LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat) +{ + LLPointer<LLInventoryCategory> rv = new LLInventoryCategory; + rv->setUUID(sd_cat[INV_FOLDER_ID_LABEL].asUUID()); + rv->setParent(sd_cat[INV_PARENT_ID_LABEL].asUUID()); + rv->rename(sd_cat[INV_NAME_LABEL].asString()); + rv->setType( + LLAssetType::lookup(sd_cat[INV_ASSET_TYPE_LABEL].asString())); + rv->setPreferredType( + LLFolderType::lookup( + sd_cat[INV_PREFERRED_TYPE_LABEL].asString())); + return rv; +} |