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 | |
parent | 069ea06848f766466f1a281144c82a0f2bd79f3a (diff) |
Fix line endlings
Diffstat (limited to 'indra/llinventory')
-rw-r--r-- | indra/llinventory/llfoldertype.cpp | 444 | ||||
-rw-r--r-- | indra/llinventory/llinventory.cpp | 3034 | ||||
-rw-r--r-- | indra/llinventory/llinventory.h | 586 | ||||
-rw-r--r-- | indra/llinventory/llnotecard.cpp | 578 | ||||
-rw-r--r-- | indra/llinventory/llparcel.cpp | 2550 | ||||
-rw-r--r-- | indra/llinventory/llparcel.h | 1354 | ||||
-rw-r--r-- | indra/llinventory/llpermissions.cpp | 2104 | ||||
-rw-r--r-- | indra/llinventory/llpermissions.h | 900 | ||||
-rw-r--r-- | indra/llinventory/llsaleinfo.cpp | 630 | ||||
-rw-r--r-- | indra/llinventory/llsaleinfo.h | 240 | ||||
-rw-r--r-- | indra/llinventory/lltransactionflags.cpp | 336 | ||||
-rw-r--r-- | indra/llinventory/lltransactionflags.h | 130 | ||||
-rw-r--r-- | indra/llinventory/tests/inventorymisc_test.cpp | 1024 |
13 files changed, 6955 insertions, 6955 deletions
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index 6bd0f8df53..7e1be17ecc 100644 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -1,222 +1,222 @@ -/**
- * @file llfoldertype.cpp
- * @brief Implementatino of LLFolderType functionality.
- *
- * $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 "llfoldertype.h"
-#include "lldictionary.h"
-#include "llmemory.h"
-#include "llsingleton.h"
-
-///----------------------------------------------------------------------------
-/// Class LLFolderType
-///----------------------------------------------------------------------------
-struct FolderEntry : public LLDictionaryEntry
-{
- FolderEntry(const std::string &type_name, // 8 character limit!
- bool is_protected, // can the viewer change categories of this type?
- bool is_automatic, // always made before first login?
- bool is_singleton // should exist as a unique copy under root
- )
- :
- LLDictionaryEntry(type_name),
- mIsProtected(is_protected),
- mIsAutomatic(is_automatic),
- mIsSingleton(is_singleton)
- {
- llassert(type_name.length() <= 8);
- }
-
- const bool mIsProtected;
- const bool mIsAutomatic;
- const bool mIsSingleton;
-};
-
-class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
- public LLDictionary<LLFolderType::EType, FolderEntry>
-{
- LLSINGLETON(LLFolderDictionary);
-protected:
- virtual LLFolderType::EType notFound() const override
- {
- return LLFolderType::FT_NONE;
- }
-};
-
-// Folder types
-//
-// PROTECTED means that folders of this type can't be moved, deleted
-// or otherwise modified by the viewer.
-//
-// SINGLETON means that there should always be exactly one folder of
-// this type, and it should be the root or a child of the root. This
-// is true for most types of folders.
-//
-// AUTOMATIC means that a copy of this folder should be created under
-// the root before the user ever logs in, and should never be created
-// from the viewer. A missing AUTOMATIC folder should be treated as a
-// fatal error by the viewer, since it indicates either corrupted
-// inventory or a failure in the inventory services.
-//
-LLFolderDictionary::LLFolderDictionary()
-{
- // TYPE NAME, PROTECTED, AUTOMATIC, SINGLETON
- addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", true, true, true));
- addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", true, true, true));
- addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", true, true, false));
- addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", true, false, false));
- addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", true, true, true));
- addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", true, true, true));
- addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", true, true, true));
- addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", true, true, true));
- addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", true, true, true));
- addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", true, true, true));
- addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", true, false, true));
- addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", true, true, true));
- addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", true, true, true));
- addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", true, true, true));
- addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", true, true, true));
- addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", true, false, true));
-
- for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++)
- {
- addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", false, false, false)); // Not used
- }
-
- addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", true, false, true));
- addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", false, false, false));
- addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", true, false, true));
-
- addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", true, false, false)); // Not used?
-
- addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", true, false, true));
- addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", true, false, false));
-
- addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", true, false, false));
-
- addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", false, false, false));
- addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", false, false, false));
- addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", false, false, false));
-
- addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", true, false, true));
- addEntry(LLFolderType::FT_MATERIAL, new FolderEntry("material", true, false, true));
-
- addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", false, false, false));
-};
-
-// static
-LLFolderType::EType LLFolderType::lookup(const std::string& name)
-{
- return LLFolderDictionary::getInstance()->lookup(name);
-}
-
-// static
-const std::string &LLFolderType::lookup(LLFolderType::EType folder_type)
-{
- const FolderEntry *entry = LLFolderDictionary::getInstance()->lookup(folder_type);
- if (entry)
- {
- return entry->mName;
- }
- else
- {
- return badLookup();
- }
-}
-
-// static
-// Only plain folders and a few other types aren't protected. "Protected" means
-// you can't move, deleted, or change certain properties such as their type.
-bool LLFolderType::lookupIsProtectedType(EType folder_type)
-{
- const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
- const FolderEntry *entry = dict->lookup(folder_type);
- if (entry)
- {
- return entry->mIsProtected;
- }
- return true;
-}
-
-// static
-// Is this folder type automatically created outside the viewer?
-bool LLFolderType::lookupIsAutomaticType(EType folder_type)
-{
- const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
- const FolderEntry *entry = dict->lookup(folder_type);
- if (entry)
- {
- return entry->mIsAutomatic;
- }
- return true;
-}
-
-// static
-// Should this folder always exist as a single copy under (or as) the root?
-bool LLFolderType::lookupIsSingletonType(EType folder_type)
-{
- const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
- const FolderEntry *entry = dict->lookup(folder_type);
- if (entry)
- {
- return entry->mIsSingleton;
- }
- return true;
-}
-
-// static
-bool LLFolderType::lookupIsEnsembleType(EType folder_type)
-{
- return (folder_type >= FT_ENSEMBLE_START &&
- folder_type <= FT_ENSEMBLE_END);
-}
-
-// static
-LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type)
-{
- if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::BADLOOKUP)
- {
- LL_WARNS() << "Converting to unknown asset type " << folder_type << LL_ENDL;
- }
- return (LLAssetType::EType)folder_type;
-}
-
-// static
-LLFolderType::EType LLFolderType::assetTypeToFolderType(LLAssetType::EType asset_type)
-{
- if (LLFolderType::lookup(LLFolderType::EType(asset_type)) == LLFolderType::badLookup())
- {
- LL_WARNS() << "Converting to unknown folder type " << asset_type << LL_ENDL;
- }
- return (LLFolderType::EType)asset_type;
-}
-
-// static
-const std::string &LLFolderType::badLookup()
-{
- static const std::string sBadLookup = "llfoldertype_bad_lookup";
- return sBadLookup;
-}
+/** + * @file llfoldertype.cpp + * @brief Implementatino of LLFolderType functionality. + * + * $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 "llfoldertype.h" +#include "lldictionary.h" +#include "llmemory.h" +#include "llsingleton.h" + +///---------------------------------------------------------------------------- +/// Class LLFolderType +///---------------------------------------------------------------------------- +struct FolderEntry : public LLDictionaryEntry +{ + FolderEntry(const std::string &type_name, // 8 character limit! + bool is_protected, // can the viewer change categories of this type? + bool is_automatic, // always made before first login? + bool is_singleton // should exist as a unique copy under root + ) + : + LLDictionaryEntry(type_name), + mIsProtected(is_protected), + mIsAutomatic(is_automatic), + mIsSingleton(is_singleton) + { + llassert(type_name.length() <= 8); + } + + const bool mIsProtected; + const bool mIsAutomatic; + const bool mIsSingleton; +}; + +class LLFolderDictionary : public LLSingleton<LLFolderDictionary>, + public LLDictionary<LLFolderType::EType, FolderEntry> +{ + LLSINGLETON(LLFolderDictionary); +protected: + virtual LLFolderType::EType notFound() const override + { + return LLFolderType::FT_NONE; + } +}; + +// Folder types +// +// PROTECTED means that folders of this type can't be moved, deleted +// or otherwise modified by the viewer. +// +// SINGLETON means that there should always be exactly one folder of +// this type, and it should be the root or a child of the root. This +// is true for most types of folders. +// +// AUTOMATIC means that a copy of this folder should be created under +// the root before the user ever logs in, and should never be created +// from the viewer. A missing AUTOMATIC folder should be treated as a +// fatal error by the viewer, since it indicates either corrupted +// inventory or a failure in the inventory services. +// +LLFolderDictionary::LLFolderDictionary() +{ + // TYPE NAME, PROTECTED, AUTOMATIC, SINGLETON + addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", true, true, true)); + addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", true, true, true)); + addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", true, true, false)); + addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", true, false, false)); + addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", true, true, true)); + addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", true, true, true)); + addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", true, true, true)); + addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", true, true, true)); + addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", true, true, true)); + addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", true, true, true)); + addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", true, false, true)); + addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", true, true, true)); + addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", true, true, true)); + addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", true, true, true)); + addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", true, true, true)); + addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", true, false, true)); + + for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++) + { + addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", false, false, false)); // Not used + } + + addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", true, false, true)); + addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", false, false, false)); + addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", true, false, true)); + + addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", true, false, false)); // Not used? + + addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", true, false, true)); + addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", true, false, false)); + + addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", true, false, false)); + + addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", false, false, false)); + addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", false, false, false)); + addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", false, false, false)); + + addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", true, false, true)); + addEntry(LLFolderType::FT_MATERIAL, new FolderEntry("material", true, false, true)); + + addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", false, false, false)); +}; + +// static +LLFolderType::EType LLFolderType::lookup(const std::string& name) +{ + return LLFolderDictionary::getInstance()->lookup(name); +} + +// static +const std::string &LLFolderType::lookup(LLFolderType::EType folder_type) +{ + const FolderEntry *entry = LLFolderDictionary::getInstance()->lookup(folder_type); + if (entry) + { + return entry->mName; + } + else + { + return badLookup(); + } +} + +// static +// Only plain folders and a few other types aren't protected. "Protected" means +// you can't move, deleted, or change certain properties such as their type. +bool LLFolderType::lookupIsProtectedType(EType folder_type) +{ + const LLFolderDictionary *dict = LLFolderDictionary::getInstance(); + const FolderEntry *entry = dict->lookup(folder_type); + if (entry) + { + return entry->mIsProtected; + } + return true; +} + +// static +// Is this folder type automatically created outside the viewer? +bool LLFolderType::lookupIsAutomaticType(EType folder_type) +{ + const LLFolderDictionary *dict = LLFolderDictionary::getInstance(); + const FolderEntry *entry = dict->lookup(folder_type); + if (entry) + { + return entry->mIsAutomatic; + } + return true; +} + +// static +// Should this folder always exist as a single copy under (or as) the root? +bool LLFolderType::lookupIsSingletonType(EType folder_type) +{ + const LLFolderDictionary *dict = LLFolderDictionary::getInstance(); + const FolderEntry *entry = dict->lookup(folder_type); + if (entry) + { + return entry->mIsSingleton; + } + return true; +} + +// static +bool LLFolderType::lookupIsEnsembleType(EType folder_type) +{ + return (folder_type >= FT_ENSEMBLE_START && + folder_type <= FT_ENSEMBLE_END); +} + +// static +LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type) +{ + if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::BADLOOKUP) + { + LL_WARNS() << "Converting to unknown asset type " << folder_type << LL_ENDL; + } + return (LLAssetType::EType)folder_type; +} + +// static +LLFolderType::EType LLFolderType::assetTypeToFolderType(LLAssetType::EType asset_type) +{ + if (LLFolderType::lookup(LLFolderType::EType(asset_type)) == LLFolderType::badLookup()) + { + LL_WARNS() << "Converting to unknown folder type " << asset_type << LL_ENDL; + } + return (LLFolderType::EType)asset_type; +} + +// static +const std::string &LLFolderType::badLookup() +{ + static const std::string sBadLookup = "llfoldertype_bad_lookup"; + return sBadLookup; +} 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; +} diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 38ce3197e9..e63f2deba7 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -1,293 +1,293 @@ -/**
- * @file llinventory.h
- * @brief LLInventoryItem and LLInventoryCategory class declaration.
- *
- * $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$
- */
-
-#ifndef LL_LLINVENTORY_H
-#define LL_LLINVENTORY_H
-
-#include "llfoldertype.h"
-#include "llinventorytype.h"
-#include "llpermissions.h"
-#include "llrefcount.h"
-#include "llsaleinfo.h"
-#include "llsd.h"
-#include "lluuid.h"
-#include "lltrace.h"
-
-class LLMessageSystem;
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryObject
-//
-// Base class for anything in the user's inventory. Handles the common code
-// between items and categories.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryObject : public LLRefCount
-{
-public:
- typedef std::list<LLPointer<LLInventoryObject> > object_list_t;
- typedef std::list<LLConstPointer<LLInventoryObject> > const_object_list_t;
-
- //--------------------------------------------------------------------
- // Initialization
- //--------------------------------------------------------------------
-public:
- LLInventoryObject();
- LLInventoryObject(const LLUUID& uuid,
- const LLUUID& parent_uuid,
- LLAssetType::EType type,
- const std::string& name);
- void copyObject(const LLInventoryObject* other); // LLRefCount requires custom copy
-protected:
- virtual ~LLInventoryObject();
-
- //--------------------------------------------------------------------
- // Accessors
- //--------------------------------------------------------------------
-public:
- virtual const LLUUID& getUUID() const; // inventoryID that this item points to
- virtual const LLUUID& getLinkedUUID() const; // inventoryID that this item points to, else this item's inventoryID
- const LLUUID& getParentUUID() const;
- virtual const LLUUID& getThumbnailUUID() const;
- virtual const std::string& getName() const;
- virtual LLAssetType::EType getType() const;
- LLAssetType::EType getActualType() const; // bypasses indirection for linked items
- bool getIsLinkType() const;
- virtual time_t getCreationDate() const;
-
- //--------------------------------------------------------------------
- // Mutators
- // Will not call updateServer
- //--------------------------------------------------------------------
-public:
- void setUUID(const LLUUID& new_uuid);
- virtual void rename(const std::string& new_name);
- void setParent(const LLUUID& new_parent);
- virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid);
- void setType(LLAssetType::EType type);
- virtual void setCreationDate(time_t creation_date_utc); // only stored for items
-
- // in place correction for inventory name string
- static void correctInventoryName(std::string& name);
-
- //--------------------------------------------------------------------
- // File Support
- // Implemented here so that a minimal information set can be transmitted
- // between simulator and viewer.
- //--------------------------------------------------------------------
-
- virtual bool importLegacyStream(std::istream& input_stream);
- virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const;
-
- virtual void updateParentOnServer(bool) const;
- virtual void updateServer(bool) const;
-
- //--------------------------------------------------------------------
- // Member Variables
- //--------------------------------------------------------------------
-protected:
- LLUUID mUUID;
- LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
- LLUUID mThumbnailUUID;
- LLAssetType::EType mType;
- std::string mName;
- time_t mCreationDate; // seconds from 1/1/1970, UTC
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryItem
-//
-// An item in the current user's inventory.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryItem : public LLInventoryObject
-{
-public:
- typedef std::vector<LLPointer<LLInventoryItem> > item_array_t;
-
- //--------------------------------------------------------------------
- // Initialization
- //--------------------------------------------------------------------
-public:
- 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);
- LLInventoryItem();
- // Create a copy of an inventory item from a pointer to another item
- // Note: Because InventoryItems are ref counted, reference copy (a = b)
- // is prohibited
- LLInventoryItem(const LLInventoryItem* other);
- virtual void copyItem(const LLInventoryItem* other); // LLRefCount requires custom copy
- void generateUUID() { mUUID.generate(); }
-protected:
- ~LLInventoryItem(); // ref counted
-
- //--------------------------------------------------------------------
- // Accessors
- //--------------------------------------------------------------------
-public:
- virtual const LLUUID& getLinkedUUID() const;
- virtual const LLPermissions& getPermissions() const;
- virtual const LLUUID& getCreatorUUID() const;
- virtual const LLUUID& getAssetUUID() const;
- virtual const std::string& getDescription() const;
- virtual const std::string& getActualDescription() const; // Does not follow links
- virtual const LLSaleInfo& getSaleInfo() const;
- virtual LLInventoryType::EType getInventoryType() const;
- virtual U32 getFlags() const;
- virtual time_t getCreationDate() const;
- virtual U32 getCRC32() const; // really more of a checksum.
-
- //--------------------------------------------------------------------
- // Mutators
- // Will not call updateServer and will never fail
- // (though it may correct to sane values)
- //--------------------------------------------------------------------
-public:
- void setAssetUUID(const LLUUID& asset_id);
- static void correctInventoryDescription(std::string& name);
- void setDescription(const std::string& new_desc);
- void setSaleInfo(const LLSaleInfo& sale_info);
- void setPermissions(const LLPermissions& perm);
- void setInventoryType(LLInventoryType::EType inv_type);
- void setFlags(U32 flags);
- void setCreator(const LLUUID& creator); // only used for calling cards
-
- // Check for changes in permissions masks and sale info
- // and set the corresponding bits in mFlags.
- void accumulatePermissionSlamBits(const LLInventoryItem& old_item);
-
- // Put this inventory item onto the current outgoing mesage.
- // Assumes you have already called nextBlock().
- virtual void packMessage(LLMessageSystem* msg) const;
-
- // Returns true if the inventory item came through the network correctly.
- // Uses a simple crc check which is defeatable, but we want to detect
- // network mangling somehow.
- virtual bool unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
-
- //--------------------------------------------------------------------
- // File Support
- //--------------------------------------------------------------------
-public:
- virtual bool importLegacyStream(std::istream& input_stream);
- virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const;
-
- //--------------------------------------------------------------------
- // Helper Functions
- //--------------------------------------------------------------------
-public:
- LLSD asLLSD() const;
- void asLLSD( LLSD& sd ) const;
- bool fromLLSD(const LLSD& sd, bool is_new = true);
-
- //--------------------------------------------------------------------
- // Member Variables
- //--------------------------------------------------------------------
-protected:
- LLPermissions mPermissions;
- LLUUID mAssetUUID;
- std::string mDescription;
- LLSaleInfo mSaleInfo;
- LLInventoryType::EType mInventoryType;
- U32 mFlags;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryCategory
-//
-// A category/folder of inventory items. Users come with a set of default
-// categories, and can create new ones as needed.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryCategory : public LLInventoryObject
-{
-public:
- typedef std::vector<LLPointer<LLInventoryCategory> > cat_array_t;
-
- //--------------------------------------------------------------------
- // Initialization
- //--------------------------------------------------------------------
-public:
- LLInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid,
- LLFolderType::EType preferred_type,
- const std::string& name);
- LLInventoryCategory();
- LLInventoryCategory(const LLInventoryCategory* other);
- void copyCategory(const LLInventoryCategory* other); // LLRefCount requires custom copy
-protected:
- virtual ~LLInventoryCategory();
-
- //--------------------------------------------------------------------
- // Accessors And Mutators
- //--------------------------------------------------------------------
-public:
- LLFolderType::EType getPreferredType() const;
- void setPreferredType(LLFolderType::EType type);
- LLSD asLLSD() const;
- LLSD asAISCreateCatLLSD() const;
- bool fromLLSD(const LLSD& sd);
-
- //--------------------------------------------------------------------
- // Messaging
- //--------------------------------------------------------------------
-public:
- virtual void packMessage(LLMessageSystem* msg) const;
- virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
-
- //--------------------------------------------------------------------
- // File Support
- //--------------------------------------------------------------------
-public:
- virtual bool importLegacyStream(std::istream& input_stream);
- virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const;
-
- LLSD exportLLSD() const;
- bool importLLSD(const LLSD& cat_data);
- //--------------------------------------------------------------------
- // Member Variables
- //--------------------------------------------------------------------
-protected:
- LLFolderType::EType mPreferredType; // Type that this category was "meant" to hold (although it may hold any type).
-};
-
-
-//-----------------------------------------------------------------------------
-// Convertors
-//
-// These functions convert between structured data and an inventory
-// item, appropriate for serialization.
-//-----------------------------------------------------------------------------
-LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item);
-LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat);
-LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat);
-
-#endif // LL_LLINVENTORY_H
+/** + * @file llinventory.h + * @brief LLInventoryItem and LLInventoryCategory class declaration. + * + * $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$ + */ + +#ifndef LL_LLINVENTORY_H +#define LL_LLINVENTORY_H + +#include "llfoldertype.h" +#include "llinventorytype.h" +#include "llpermissions.h" +#include "llrefcount.h" +#include "llsaleinfo.h" +#include "llsd.h" +#include "lluuid.h" +#include "lltrace.h" + +class LLMessageSystem; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryObject +// +// Base class for anything in the user's inventory. Handles the common code +// between items and categories. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryObject : public LLRefCount +{ +public: + typedef std::list<LLPointer<LLInventoryObject> > object_list_t; + typedef std::list<LLConstPointer<LLInventoryObject> > const_object_list_t; + + //-------------------------------------------------------------------- + // Initialization + //-------------------------------------------------------------------- +public: + LLInventoryObject(); + LLInventoryObject(const LLUUID& uuid, + const LLUUID& parent_uuid, + LLAssetType::EType type, + const std::string& name); + void copyObject(const LLInventoryObject* other); // LLRefCount requires custom copy +protected: + virtual ~LLInventoryObject(); + + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + virtual const LLUUID& getUUID() const; // inventoryID that this item points to + virtual const LLUUID& getLinkedUUID() const; // inventoryID that this item points to, else this item's inventoryID + const LLUUID& getParentUUID() const; + virtual const LLUUID& getThumbnailUUID() const; + virtual const std::string& getName() const; + virtual LLAssetType::EType getType() const; + LLAssetType::EType getActualType() const; // bypasses indirection for linked items + bool getIsLinkType() const; + virtual time_t getCreationDate() const; + + //-------------------------------------------------------------------- + // Mutators + // Will not call updateServer + //-------------------------------------------------------------------- +public: + void setUUID(const LLUUID& new_uuid); + virtual void rename(const std::string& new_name); + void setParent(const LLUUID& new_parent); + virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid); + void setType(LLAssetType::EType type); + virtual void setCreationDate(time_t creation_date_utc); // only stored for items + + // in place correction for inventory name string + static void correctInventoryName(std::string& name); + + //-------------------------------------------------------------------- + // File Support + // Implemented here so that a minimal information set can be transmitted + // between simulator and viewer. + //-------------------------------------------------------------------- + + virtual bool importLegacyStream(std::istream& input_stream); + virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const; + + virtual void updateParentOnServer(bool) const; + virtual void updateServer(bool) const; + + //-------------------------------------------------------------------- + // Member Variables + //-------------------------------------------------------------------- +protected: + LLUUID mUUID; + LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL. + LLUUID mThumbnailUUID; + LLAssetType::EType mType; + std::string mName; + time_t mCreationDate; // seconds from 1/1/1970, UTC +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryItem +// +// An item in the current user's inventory. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryItem : public LLInventoryObject +{ +public: + typedef std::vector<LLPointer<LLInventoryItem> > item_array_t; + + //-------------------------------------------------------------------- + // Initialization + //-------------------------------------------------------------------- +public: + 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); + LLInventoryItem(); + // Create a copy of an inventory item from a pointer to another item + // Note: Because InventoryItems are ref counted, reference copy (a = b) + // is prohibited + LLInventoryItem(const LLInventoryItem* other); + virtual void copyItem(const LLInventoryItem* other); // LLRefCount requires custom copy + void generateUUID() { mUUID.generate(); } +protected: + ~LLInventoryItem(); // ref counted + + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + virtual const LLUUID& getLinkedUUID() const; + virtual const LLPermissions& getPermissions() const; + virtual const LLUUID& getCreatorUUID() const; + virtual const LLUUID& getAssetUUID() const; + virtual const std::string& getDescription() const; + virtual const std::string& getActualDescription() const; // Does not follow links + virtual const LLSaleInfo& getSaleInfo() const; + virtual LLInventoryType::EType getInventoryType() const; + virtual U32 getFlags() const; + virtual time_t getCreationDate() const; + virtual U32 getCRC32() const; // really more of a checksum. + + //-------------------------------------------------------------------- + // Mutators + // Will not call updateServer and will never fail + // (though it may correct to sane values) + //-------------------------------------------------------------------- +public: + void setAssetUUID(const LLUUID& asset_id); + static void correctInventoryDescription(std::string& name); + void setDescription(const std::string& new_desc); + void setSaleInfo(const LLSaleInfo& sale_info); + void setPermissions(const LLPermissions& perm); + void setInventoryType(LLInventoryType::EType inv_type); + void setFlags(U32 flags); + void setCreator(const LLUUID& creator); // only used for calling cards + + // Check for changes in permissions masks and sale info + // and set the corresponding bits in mFlags. + void accumulatePermissionSlamBits(const LLInventoryItem& old_item); + + // Put this inventory item onto the current outgoing mesage. + // Assumes you have already called nextBlock(). + virtual void packMessage(LLMessageSystem* msg) const; + + // Returns true if the inventory item came through the network correctly. + // Uses a simple crc check which is defeatable, but we want to detect + // network mangling somehow. + virtual bool unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); + + //-------------------------------------------------------------------- + // File Support + //-------------------------------------------------------------------- +public: + virtual bool importLegacyStream(std::istream& input_stream); + virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const; + + //-------------------------------------------------------------------- + // Helper Functions + //-------------------------------------------------------------------- +public: + LLSD asLLSD() const; + void asLLSD( LLSD& sd ) const; + bool fromLLSD(const LLSD& sd, bool is_new = true); + + //-------------------------------------------------------------------- + // Member Variables + //-------------------------------------------------------------------- +protected: + LLPermissions mPermissions; + LLUUID mAssetUUID; + std::string mDescription; + LLSaleInfo mSaleInfo; + LLInventoryType::EType mInventoryType; + U32 mFlags; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLInventoryCategory +// +// A category/folder of inventory items. Users come with a set of default +// categories, and can create new ones as needed. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLInventoryCategory : public LLInventoryObject +{ +public: + typedef std::vector<LLPointer<LLInventoryCategory> > cat_array_t; + + //-------------------------------------------------------------------- + // Initialization + //-------------------------------------------------------------------- +public: + LLInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid, + LLFolderType::EType preferred_type, + const std::string& name); + LLInventoryCategory(); + LLInventoryCategory(const LLInventoryCategory* other); + void copyCategory(const LLInventoryCategory* other); // LLRefCount requires custom copy +protected: + virtual ~LLInventoryCategory(); + + //-------------------------------------------------------------------- + // Accessors And Mutators + //-------------------------------------------------------------------- +public: + LLFolderType::EType getPreferredType() const; + void setPreferredType(LLFolderType::EType type); + LLSD asLLSD() const; + LLSD asAISCreateCatLLSD() const; + bool fromLLSD(const LLSD& sd); + + //-------------------------------------------------------------------- + // Messaging + //-------------------------------------------------------------------- +public: + virtual void packMessage(LLMessageSystem* msg) const; + virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); + + //-------------------------------------------------------------------- + // File Support + //-------------------------------------------------------------------- +public: + virtual bool importLegacyStream(std::istream& input_stream); + virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const; + + LLSD exportLLSD() const; + bool importLLSD(const LLSD& cat_data); + //-------------------------------------------------------------------- + // Member Variables + //-------------------------------------------------------------------- +protected: + LLFolderType::EType mPreferredType; // Type that this category was "meant" to hold (although it may hold any type). +}; + + +//----------------------------------------------------------------------------- +// Convertors +// +// These functions convert between structured data and an inventory +// item, appropriate for serialization. +//----------------------------------------------------------------------------- +LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item); +LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat); +LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat); + +#endif // LL_LLINVENTORY_H diff --git a/indra/llinventory/llnotecard.cpp b/indra/llinventory/llnotecard.cpp index 37f28272fe..d73e9c8966 100644 --- a/indra/llinventory/llnotecard.cpp +++ b/indra/llinventory/llnotecard.cpp @@ -1,289 +1,289 @@ -/**
- * @file llnotecard.cpp
- * @brief LLNotecard class definition
- *
- * $LicenseInfo:firstyear=2006&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 "llnotecard.h"
-#include "llstreamtools.h"
-
-LLNotecard::LLNotecard(S32 max_text)
- : mMaxText(max_text),
- mVersion(0),
- mEmbeddedVersion(0)
-{
-}
-
-LLNotecard::~LLNotecard()
-{
-}
-
-bool LLNotecard::importEmbeddedItemsStream(std::istream& str)
-{
- // Version 1 format:
- // LLEmbeddedItems version 1
- // {
- // count <number of entries being used and not deleted>
- // {
- // ext char index <index>
- // <InventoryItem chunk>
- // }
- // }
-
- S32 i;
- S32 count = 0;
-
- str >> std::ws >> "LLEmbeddedItems version" >> mEmbeddedVersion >> "\n";
- if (str.fail())
- {
- LL_WARNS() << "Invalid Linden text file header" << LL_ENDL;
- goto import_file_failed;
- }
-
- if( 1 != mEmbeddedVersion )
- {
- LL_WARNS() << "Invalid LLEmbeddedItems version: " << mEmbeddedVersion << LL_ENDL;
- goto import_file_failed;
- }
-
- str >> std::ws >> "{\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid Linden text file format: missing {" << LL_ENDL;
- goto import_file_failed;
- }
-
- str >> std::ws >> "count " >> count >> "\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid LLEmbeddedItems count" << LL_ENDL;
- goto import_file_failed;
- }
-
- if((count < 0))
- {
- LL_WARNS() << "Invalid LLEmbeddedItems count value: " << count << LL_ENDL;
- goto import_file_failed;
- }
-
- for(i = 0; i < count; i++)
- {
- str >> std::ws >> "{\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid LLEmbeddedItems file format: missing {" << LL_ENDL;
- goto import_file_failed;
- }
-
- U32 index = 0;
- str >> std::ws >> "ext char index " >> index >> "\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid LLEmbeddedItems file format: missing ext char index" << LL_ENDL;
- goto import_file_failed;
- }
-
- str >> std::ws >> "inv_item\t0\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid LLEmbeddedItems file format: missing inv_item" << LL_ENDL;
- goto import_file_failed;
- }
-
- LLPointer<LLInventoryItem> item = new LLInventoryItem;
- if (!item->importLegacyStream(str))
- {
- LL_INFOS() << "notecard import failed" << LL_ENDL;
- goto import_file_failed;
- }
- mItems.push_back(item);
-
- str >> std::ws >> "}\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid LLEmbeddedItems file format: missing }" << LL_ENDL;
- goto import_file_failed;
- }
- }
-
- str >> std::ws >> "}\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid LLEmbeddedItems file format: missing }" << LL_ENDL;
- goto import_file_failed;
- }
-
- return true;
-
- import_file_failed:
- return false;
-}
-
-bool LLNotecard::importStream(std::istream& str)
-{
- // Version 1 format:
- // Linden text version 1
- // {
- // <EmbeddedItemList chunk>
- // Text length
- // <ASCII text; 0x80 | index = embedded item>
- // }
-
- // Version 2 format: (NOTE: Imports identically to version 1)
- // Linden text version 2
- // {
- // <EmbeddedItemList chunk>
- // Text length
- // <UTF8 text; FIRST_EMBEDDED_CHAR + index = embedded item>
- // }
-
- str >> std::ws >> "Linden text version " >> mVersion >> "\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid Linden text file header " << LL_ENDL;
- return false;
- }
-
- if( 1 != mVersion && 2 != mVersion)
- {
- LL_WARNS() << "Invalid Linden text file version: " << mVersion << LL_ENDL;
- return false;
- }
-
- str >> std::ws >> "{\n";
- if(str.fail())
- {
- LL_WARNS() << "Invalid Linden text file format" << LL_ENDL;
- return false;
- }
-
- if(!importEmbeddedItemsStream(str))
- {
- return false;
- }
-
- char line_buf[STD_STRING_BUF_SIZE]; /* Flawfinder: ignore */
- str.getline(line_buf, STD_STRING_BUF_SIZE);
- if(str.fail())
- {
- LL_WARNS() << "Invalid Linden text length field" << LL_ENDL;
- return false;
- }
- line_buf[STD_STRING_STR_LEN] = '\0';
-
- S32 text_len = 0;
- if( 1 != sscanf(line_buf, "Text length %d", &text_len) )
- {
- LL_WARNS() << "Invalid Linden text length field" << LL_ENDL;
- return false;
- }
-
- if(text_len > mMaxText || text_len < 0)
- {
- LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL;
- return false;
- }
-
- bool success = true;
-
- char* text = new char[text_len + 1];
- fullread(str, text, text_len);
- if(str.fail())
- {
- LL_WARNS() << "Invalid Linden text: text shorter than text length: " << text_len << LL_ENDL;
- success = false;
- }
- text[text_len] = '\0';
-
- if(success)
- {
- // Actually set the text
- mText = std::string(text);
- }
-
- delete[] text;
-
- return success;
-}
-
-////////////////////////////////////////////////////////////////////////////
-
-bool LLNotecard::exportEmbeddedItemsStream( std::ostream& out_stream )
-{
- out_stream << "LLEmbeddedItems version 1\n";
- out_stream << "{\n";
-
- out_stream << llformat("count %d\n", mItems.size() );
-
- S32 idx = 0;
- for (std::vector<LLPointer<LLInventoryItem> >::iterator iter = mItems.begin();
- iter != mItems.end(); ++iter)
- {
- LLInventoryItem* item = *iter;
- if (item)
- {
- out_stream << "{\n";
- out_stream << llformat("ext char index %d\n", idx );
- if( !item->exportLegacyStream( out_stream ) )
- {
- return false;
- }
- out_stream << "}\n";
- }
- ++idx;
- }
-
- out_stream << "}\n";
-
- return true;
-}
-
-bool LLNotecard::exportStream( std::ostream& out_stream )
-{
- out_stream << "Linden text version 2\n";
- out_stream << "{\n";
-
- if( !exportEmbeddedItemsStream( out_stream ) )
- {
- return false;
- }
-
- out_stream << llformat("Text length %d\n", mText.length() );
- out_stream << mText;
- out_stream << "}\n";
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////
-
-void LLNotecard::setItems(const std::vector<LLPointer<LLInventoryItem> >& items)
-{
- mItems = items;
-}
-
-void LLNotecard::setText(const std::string& text)
-{
- mText = text;
-}
+/** + * @file llnotecard.cpp + * @brief LLNotecard class definition + * + * $LicenseInfo:firstyear=2006&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 "llnotecard.h" +#include "llstreamtools.h" + +LLNotecard::LLNotecard(S32 max_text) + : mMaxText(max_text), + mVersion(0), + mEmbeddedVersion(0) +{ +} + +LLNotecard::~LLNotecard() +{ +} + +bool LLNotecard::importEmbeddedItemsStream(std::istream& str) +{ + // Version 1 format: + // LLEmbeddedItems version 1 + // { + // count <number of entries being used and not deleted> + // { + // ext char index <index> + // <InventoryItem chunk> + // } + // } + + S32 i; + S32 count = 0; + + str >> std::ws >> "LLEmbeddedItems version" >> mEmbeddedVersion >> "\n"; + if (str.fail()) + { + LL_WARNS() << "Invalid Linden text file header" << LL_ENDL; + goto import_file_failed; + } + + if( 1 != mEmbeddedVersion ) + { + LL_WARNS() << "Invalid LLEmbeddedItems version: " << mEmbeddedVersion << LL_ENDL; + goto import_file_failed; + } + + str >> std::ws >> "{\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid Linden text file format: missing {" << LL_ENDL; + goto import_file_failed; + } + + str >> std::ws >> "count " >> count >> "\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid LLEmbeddedItems count" << LL_ENDL; + goto import_file_failed; + } + + if((count < 0)) + { + LL_WARNS() << "Invalid LLEmbeddedItems count value: " << count << LL_ENDL; + goto import_file_failed; + } + + for(i = 0; i < count; i++) + { + str >> std::ws >> "{\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid LLEmbeddedItems file format: missing {" << LL_ENDL; + goto import_file_failed; + } + + U32 index = 0; + str >> std::ws >> "ext char index " >> index >> "\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid LLEmbeddedItems file format: missing ext char index" << LL_ENDL; + goto import_file_failed; + } + + str >> std::ws >> "inv_item\t0\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid LLEmbeddedItems file format: missing inv_item" << LL_ENDL; + goto import_file_failed; + } + + LLPointer<LLInventoryItem> item = new LLInventoryItem; + if (!item->importLegacyStream(str)) + { + LL_INFOS() << "notecard import failed" << LL_ENDL; + goto import_file_failed; + } + mItems.push_back(item); + + str >> std::ws >> "}\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid LLEmbeddedItems file format: missing }" << LL_ENDL; + goto import_file_failed; + } + } + + str >> std::ws >> "}\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid LLEmbeddedItems file format: missing }" << LL_ENDL; + goto import_file_failed; + } + + return true; + + import_file_failed: + return false; +} + +bool LLNotecard::importStream(std::istream& str) +{ + // Version 1 format: + // Linden text version 1 + // { + // <EmbeddedItemList chunk> + // Text length + // <ASCII text; 0x80 | index = embedded item> + // } + + // Version 2 format: (NOTE: Imports identically to version 1) + // Linden text version 2 + // { + // <EmbeddedItemList chunk> + // Text length + // <UTF8 text; FIRST_EMBEDDED_CHAR + index = embedded item> + // } + + str >> std::ws >> "Linden text version " >> mVersion >> "\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid Linden text file header " << LL_ENDL; + return false; + } + + if( 1 != mVersion && 2 != mVersion) + { + LL_WARNS() << "Invalid Linden text file version: " << mVersion << LL_ENDL; + return false; + } + + str >> std::ws >> "{\n"; + if(str.fail()) + { + LL_WARNS() << "Invalid Linden text file format" << LL_ENDL; + return false; + } + + if(!importEmbeddedItemsStream(str)) + { + return false; + } + + char line_buf[STD_STRING_BUF_SIZE]; /* Flawfinder: ignore */ + str.getline(line_buf, STD_STRING_BUF_SIZE); + if(str.fail()) + { + LL_WARNS() << "Invalid Linden text length field" << LL_ENDL; + return false; + } + line_buf[STD_STRING_STR_LEN] = '\0'; + + S32 text_len = 0; + if( 1 != sscanf(line_buf, "Text length %d", &text_len) ) + { + LL_WARNS() << "Invalid Linden text length field" << LL_ENDL; + return false; + } + + if(text_len > mMaxText || text_len < 0) + { + LL_WARNS() << "Invalid Linden text length: " << text_len << LL_ENDL; + return false; + } + + bool success = true; + + char* text = new char[text_len + 1]; + fullread(str, text, text_len); + if(str.fail()) + { + LL_WARNS() << "Invalid Linden text: text shorter than text length: " << text_len << LL_ENDL; + success = false; + } + text[text_len] = '\0'; + + if(success) + { + // Actually set the text + mText = std::string(text); + } + + delete[] text; + + return success; +} + +//////////////////////////////////////////////////////////////////////////// + +bool LLNotecard::exportEmbeddedItemsStream( std::ostream& out_stream ) +{ + out_stream << "LLEmbeddedItems version 1\n"; + out_stream << "{\n"; + + out_stream << llformat("count %d\n", mItems.size() ); + + S32 idx = 0; + for (std::vector<LLPointer<LLInventoryItem> >::iterator iter = mItems.begin(); + iter != mItems.end(); ++iter) + { + LLInventoryItem* item = *iter; + if (item) + { + out_stream << "{\n"; + out_stream << llformat("ext char index %d\n", idx ); + if( !item->exportLegacyStream( out_stream ) ) + { + return false; + } + out_stream << "}\n"; + } + ++idx; + } + + out_stream << "}\n"; + + return true; +} + +bool LLNotecard::exportStream( std::ostream& out_stream ) +{ + out_stream << "Linden text version 2\n"; + out_stream << "{\n"; + + if( !exportEmbeddedItemsStream( out_stream ) ) + { + return false; + } + + out_stream << llformat("Text length %d\n", mText.length() ); + out_stream << mText; + out_stream << "}\n"; + + return true; +} + +//////////////////////////////////////////////////////////////////////////// + +void LLNotecard::setItems(const std::vector<LLPointer<LLInventoryItem> >& items) +{ + mItems = items; +} + +void LLNotecard::setText(const std::string& text) +{ + mText = text; +} diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 30daf0af44..ef6ddb3cab 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -1,1275 +1,1275 @@ -/**
- * @file llparcel.cpp
- * @brief A land parcel.
- *
- * $LicenseInfo:firstyear=2002&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 "indra_constants.h"
-#include <iostream>
-
-#include "llparcel.h"
-#include "llstreamtools.h"
-
-#include "llmath.h"
-#include "llsd.h"
-#include "llsdutil.h"
-#include "lltransactiontypes.h"
-#include "lltransactionflags.h"
-#include "llsdutil_math.h"
-#include "message.h"
-#include "u64.h"
-#include "llregionflags.h"
-#include <boost/range/adaptor/map.hpp>
-
-static const F32 SOME_BIG_NUMBER = 1000.0f;
-static const F32 SOME_BIG_NEG_NUMBER = -1000.0f;
-static const std::string PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT+1] =
-{
- "leased",
- "lease_pending",
- "abandoned",
- "none"
-};
-
-// NOTE: Adding parcel categories also requires updating:
-// * floater_about_land.xml category combobox
-// * Web site "create event" tools
-// DO NOT DELETE ITEMS FROM THIS LIST WITHOUT DEEPLY UNDERSTANDING WHAT YOU'RE DOING.
-//
-static const std::string PARCEL_CATEGORY_STRING[LLParcel::C_COUNT] =
-{
- "none",
- "linden",
- "adult",
- "arts",
- "store", // "business" legacy name
- "educational",
- "game", // "gaming" legacy name
- "gather", // "hangout" legacy name
- "newcomer",
- "park",
- "home", // "residential" legacy name
- "shopping",
- "stage",
- "other",
- "rental"
-};
-static const std::string PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] =
-{
- "None",
- "Linden Location",
- "Adult",
- "Arts and Culture",
- "Business",
- "Educational",
- "Gaming",
- "Hangout",
- "Newcomer Friendly",
- "Parks and Nature",
- "Residential",
- "Shopping",
- "Stage",
- "Other",
- "Rental",
- "Any", // valid string for parcel searches
-};
-
-static const std::string PARCEL_ACTION_STRING[LLParcel::A_COUNT + 1] =
-{
- "create",
- "release",
- "absorb",
- "absorbed",
- "divide",
- "division",
- "acquire",
- "relinquish",
- "confirm",
- "unknown"
-};
-
-
-
-//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action);
-//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s);
-const std::string& category_to_ui_string(LLParcel::ECategory category);
-LLParcel::ECategory category_ui_string_to_category(const std::string& s);
-
-LLParcel::LLParcel()
-{
- init(LLUUID::null, true, false, false, 0, 0, 0, 0, 0, 1.f, 0);
-}
-
-
-LLParcel::LLParcel(const LLUUID &owner_id,
- bool modify, bool terraform, bool damage,
- time_t claim_date, S32 claim_price_per_meter,
- S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
- bool is_group_owned)
-{
- init( owner_id, modify, terraform, damage, claim_date,
- claim_price_per_meter, rent_price_per_meter, area, sim_object_limit, parcel_object_bonus,
- is_group_owned);
-}
-
-
-// virtual
-LLParcel::~LLParcel()
-{
- // user list cleaned up by std::vector destructor.
-}
-
-void LLParcel::init(const LLUUID &owner_id,
- bool modify, bool terraform, bool damage,
- time_t claim_date, S32 claim_price_per_meter,
- S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
- bool is_group_owned)
-{
- mID.setNull();
- mOwnerID = owner_id;
- mGroupOwned = is_group_owned;
- mClaimDate = claim_date;
- mClaimPricePerMeter = claim_price_per_meter;
- mRentPricePerMeter = rent_price_per_meter;
- mArea = area;
- mDiscountRate = 1.0f;
- mDrawDistance = 512.f;
-
- mUserLookAt.setVec(0.0f, 0.f, 0.f);
- // Default to using the parcel's landing point, if any.
- mLandingType = L_LANDING_POINT;
-
- // *FIX: if owner_id != null, should be owned or sale pending,
- // investigate init callers.
- mStatus = OS_NONE;
- mCategory = C_NONE;
- mAuthBuyerID.setNull();
- //mBuyerID.setNull();
- //mJoinNeighbors = 0x0;
- mSaleTimerExpires.setTimerExpirySec(0);
- mSaleTimerExpires.stop();
- mGraceExtension = 0;
- //mExpireAction = STEA_REVERT;
- //mRecordTransaction = false;
-
- mAuctionID = 0;
- mInEscrow = false;
-
- mParcelFlags = PF_DEFAULT;
- setParcelFlag(PF_CREATE_OBJECTS, modify);
- setParcelFlag(PF_ALLOW_TERRAFORM, terraform);
- setParcelFlag(PF_ALLOW_DAMAGE, damage);
-
- mSalePrice = 10000;
- setName(LLStringUtil::null);
- setDesc(LLStringUtil::null);
- setMusicURL(LLStringUtil::null);
- setMediaURL(LLStringUtil::null);
- setMediaDesc(LLStringUtil::null);
- setMediaType(LLStringUtil::null);
- mMediaID.setNull();
- mMediaAutoScale = 0;
- mMediaLoop = 1;
- mMediaWidth = 0;
- mMediaHeight = 0;
- setMediaCurrentURL(LLStringUtil::null);
- mMediaAllowNavigate = 1;
- mMediaURLTimeout = 0.0f;
- mMediaPreventCameraZoom = 0;
-
- mGroupID.setNull();
-
- mPassPrice = PARCEL_PASS_PRICE_DEFAULT;
- mPassHours = PARCEL_PASS_HOURS_DEFAULT;
-
- mAABBMin.setVec(SOME_BIG_NUMBER, SOME_BIG_NUMBER, SOME_BIG_NUMBER);
- mAABBMax.setVec(SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER);
-
- mLocalID = INVALID_PARCEL_ID;
-
- //mSimWidePrimCorrection = 0;
- setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
- setSimWideMaxPrimCapacity(0);
- setSimWidePrimCount(0);
- setOwnerPrimCount(0);
- setGroupPrimCount(0);
- setOtherPrimCount(0);
- setSelectedPrimCount(0);
- setTempPrimCount(0);
- setCleanOtherTime(0);
- setRegionPushOverride(false);
- setRegionDenyAnonymousOverride(false);
- setRegionDenyAgeUnverifiedOverride(false);
- setParcelPrimBonus(parcel_object_bonus);
-
- setPreviousOwnerID(LLUUID::null);
- setPreviouslyGroupOwned(false);
-
- setSeeAVs(true);
- setAllowGroupAVSounds(true);
- setAllowAnyAVSounds(true);
- setHaveNewParcelLimitData(false);
-
- setRegionAllowEnvironmentOverride(false);
- setParcelEnvironmentVersion(INVALID_PARCEL_ENVIRONMENT_VERSION);
-
- setObscureMOAP(false);
-}
-
-void LLParcel::overrideOwner(const LLUUID& owner_id, bool is_group_owned)
-{
- // Override with system permission (LLUUID::null)
- // Overridden parcels have no group
- mOwnerID = owner_id;
- mGroupOwned = is_group_owned;
- if(mGroupOwned)
- {
- mGroupID = mOwnerID;
- }
- else
- {
- mGroupID.setNull();
- }
- mInEscrow = false;
-}
-
-void LLParcel::overrideParcelFlags(U32 flags)
-{
- mParcelFlags = flags;
-}
-void LLParcel::setName(const std::string& name)
-{
- // The escaping here must match the escaping in the database
- // abstraction layer.
- mName = name;
- LLStringFn::replace_nonprintable_in_ascii(mName, LL_UNKNOWN_CHAR);
-}
-
-void LLParcel::setDesc(const std::string& desc)
-{
- // The escaping here must match the escaping in the database
- // abstraction layer.
- mDesc = desc;
- mDesc = rawstr_to_utf8(mDesc);
-}
-
-void LLParcel::setMusicURL(const std::string& url)
-{
- mMusicURL = url;
- // The escaping here must match the escaping in the database
- // abstraction layer.
- // This should really filter the url in some way. Other than
- // simply requiring non-printable.
- LLStringFn::replace_nonprintable_in_ascii(mMusicURL, LL_UNKNOWN_CHAR);
-}
-
-void LLParcel::setMediaURL(const std::string& url)
-{
- mMediaURL = url;
- // The escaping here must match the escaping in the database
- // abstraction layer if it's ever added.
- // This should really filter the url in some way. Other than
- // simply requiring non-printable.
- LLStringFn::replace_nonprintable_in_ascii(mMediaURL, LL_UNKNOWN_CHAR);
-}
-
-void LLParcel::setMediaDesc(const std::string& desc)
-{
- // The escaping here must match the escaping in the database
- // abstraction layer.
- mMediaDesc = desc;
- mMediaDesc = rawstr_to_utf8(mMediaDesc);
-}
-void LLParcel::setMediaType(const std::string& type)
-{
- // The escaping here must match the escaping in the database
- // abstraction layer.
- mMediaType = type;
- mMediaType = rawstr_to_utf8(mMediaType);
-
- // This code attempts to preserve legacy movie functioning
- if(mMediaType.empty() && ! mMediaURL.empty())
- {
- setMediaType(std::string("video/vnd.secondlife.qt.legacy"));
- }
-}
-void LLParcel::setMediaWidth(S32 width)
-{
- mMediaWidth = width;
-}
-void LLParcel::setMediaHeight(S32 height)
-{
- mMediaHeight = height;
-}
-
-void LLParcel::setMediaCurrentURL(const std::string& url)
-{
- mMediaCurrentURL = url;
- // The escaping here must match the escaping in the database
- // abstraction layer if it's ever added.
- // This should really filter the url in some way. Other than
- // simply requiring non-printable.
- LLStringFn::replace_nonprintable_in_ascii(mMediaCurrentURL, LL_UNKNOWN_CHAR);
-
-}
-
-void LLParcel::setMediaURLResetTimer(F32 time)
-{
- mMediaResetTimer.start();
- mMediaResetTimer.setTimerExpirySec(time);
-}
-
-// virtual
-void LLParcel::setLocalID(S32 local_id)
-{
- mLocalID = local_id;
-}
-
-void LLParcel::setAllParcelFlags(U32 flags)
-{
- mParcelFlags = flags;
-}
-
-void LLParcel::setParcelFlag(U32 flag, bool b)
-{
- if (b)
- {
- mParcelFlags |= flag;
- }
- else
- {
- mParcelFlags &= ~flag;
- }
-}
-
-
-bool LLParcel::allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const
-{
- if (agent_id == LLUUID::null)
- {
- // system always can enter
- return true;
- }
- else if (isPublic())
- {
- return true;
- }
- else if (agent_id == mOwnerID)
- {
- // owner can always perform operations
- return true;
- }
- else if (mParcelFlags & PF_CREATE_OBJECTS)
- {
- return true;
- }
- else if ((mParcelFlags & PF_CREATE_GROUP_OBJECTS)
- && group_id.notNull() )
- {
- return (getGroupID() == group_id);
- }
-
- return false;
-}
-
-bool LLParcel::allowTerraformBy(const LLUUID &agent_id) const
-{
- if (agent_id == LLUUID::null)
- {
- // system always can enter
- return true;
- }
- else if(OS_LEASED == mStatus)
- {
- if(agent_id == mOwnerID)
- {
- // owner can modify leased land
- return true;
- }
- else
- {
- // otherwise check other people
- return mParcelFlags & PF_ALLOW_TERRAFORM;
- }
- }
- else
- {
- return false;
- }
-}
-
-
-
-void LLParcel::setArea(S32 area, S32 sim_object_limit)
-{
- mArea = area;
- setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
-}
-
-void LLParcel::setDiscountRate(F32 rate)
-{
- // this is to make sure that the rate is at least sane - this is
- // not intended to enforce economy rules. It only enfoces that the
- // rate is a scaler between 0 and 1.
- mDiscountRate = llclampf(rate);
-}
-
-
-//-----------------------------------------------------------
-// File input and output
-//-----------------------------------------------------------
-
-bool LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entry)
-{
- skip_to_end_of_next_keyword("{", input_stream);
- while (input_stream.good())
- {
- skip_comments_and_emptyspace(input_stream);
- std::string line, keyword, value;
- get_line(line, input_stream, MAX_STRING);
- get_keyword_and_value(keyword, value, line);
-
- if ("}" == keyword)
- {
- break;
- }
- else if ("id" == keyword)
- {
- entry->mID.set( value );
- }
- else if ("name" == keyword)
- {
- // deprecated
- }
- else if ("time" == keyword)
- {
- S32 when{};
- LLStringUtil::convertToS32(value, when);
- entry->mTime = when;
- }
- else if ("flags" == keyword)
- {
- U32 setting{};
- LLStringUtil::convertToU32(value, setting);
- entry->mFlags = setting;
- }
- else
- {
- LL_WARNS() << "Unknown keyword in parcel access entry section: <"
- << keyword << ">" << LL_ENDL;
- }
- }
- return input_stream.good();
-}
-
-// Assumes we are in a block "ParcelData"
-void LLParcel::packMessage(LLMessageSystem* msg)
-{
- msg->addU32Fast( _PREHASH_ParcelFlags, getParcelFlags() );
- msg->addS32Fast( _PREHASH_SalePrice, getSalePrice() );
- msg->addStringFast( _PREHASH_Name, getName() );
- msg->addStringFast( _PREHASH_Desc, getDesc() );
- msg->addStringFast( _PREHASH_MusicURL, getMusicURL() );
- msg->addStringFast( _PREHASH_MediaURL, getMediaURL() );
- msg->addU8 ( "MediaAutoScale", getMediaAutoScale () );
- msg->addUUIDFast( _PREHASH_MediaID, getMediaID() );
- msg->addUUIDFast( _PREHASH_GroupID, getGroupID() );
- msg->addS32Fast( _PREHASH_PassPrice, mPassPrice );
- msg->addF32Fast( _PREHASH_PassHours, mPassHours );
- msg->addU8Fast( _PREHASH_Category, (U8)mCategory);
- msg->addUUIDFast( _PREHASH_AuthBuyerID, mAuthBuyerID);
- msg->addUUIDFast( _PREHASH_SnapshotID, mSnapshotID);
- msg->addVector3Fast(_PREHASH_UserLocation, mUserLocation);
- msg->addVector3Fast(_PREHASH_UserLookAt, mUserLookAt);
- msg->addU8Fast( _PREHASH_LandingType, (U8)mLandingType);
-}
-
-// Assumes we are in a block "ParcelData"
-void LLParcel::packMessage(LLSD& msg)
-{
- // used in the viewer, the sim uses it's own packer
- msg["local_id"] = getLocalID();
- msg["parcel_flags"] = ll_sd_from_U32(getParcelFlags());
- msg["sale_price"] = getSalePrice();
- msg["name"] = getName();
- msg["description"] = getDesc();
- msg["music_url"] = getMusicURL();
- msg["media_url"] = getMediaURL();
- msg["media_desc"] = getMediaDesc();
- msg["media_type"] = getMediaType();
- msg["media_width"] = getMediaWidth();
- msg["media_height"] = getMediaHeight();
- msg["auto_scale"] = getMediaAutoScale();
- msg["media_loop"] = getMediaLoop();
- msg["media_current_url"] = getMediaCurrentURL();
- msg["obscure_media"] = false; // OBSOLETE - no longer used
- msg["obscure_music"] = false; // OBSOLETE - no longer used
- msg["media_id"] = getMediaID();
- msg["media_allow_navigate"] = getMediaAllowNavigate();
- msg["media_prevent_camera_zoom"] = getMediaPreventCameraZoom();
- msg["media_url_timeout"] = getMediaURLTimeout();
- msg["group_id"] = getGroupID();
- msg["pass_price"] = mPassPrice;
- msg["pass_hours"] = mPassHours;
- msg["category"] = (U8)mCategory;
- msg["auth_buyer_id"] = mAuthBuyerID;
- msg["snapshot_id"] = mSnapshotID;
- msg["user_location"] = ll_sd_from_vector3(mUserLocation);
- msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt);
- msg["landing_type"] = (U8)mLandingType;
- msg["see_avs"] = (LLSD::Boolean) getSeeAVs();
- msg["group_av_sounds"] = (LLSD::Boolean) getAllowGroupAVSounds();
- msg["any_av_sounds"] = (LLSD::Boolean) getAllowAnyAVSounds();
- msg["obscure_moap"] = (LLSD::Boolean) getObscureMOAP();
-}
-
-
-void LLParcel::unpackMessage(LLMessageSystem* msg)
-{
- std::string buffer;
-
- msg->getU32Fast( _PREHASH_ParcelData,_PREHASH_ParcelFlags, mParcelFlags );
- msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_SalePrice, mSalePrice );
- msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Name, buffer );
- setName(buffer);
- msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Desc, buffer );
- setDesc(buffer);
- msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MusicURL, buffer );
- setMusicURL(buffer);
- msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, buffer );
- setMediaURL(buffer);
-
- bool see_avs = true; // All default to true for legacy server behavior
- bool any_av_sounds = true;
- bool group_av_sounds = true;
- bool have_new_parcel_limit_data = (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_SeeAVs) > 0); // New version of server should send all 3 of these values
- have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds) > 0);
- have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds) > 0);
- if (have_new_parcel_limit_data)
- {
- msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_SeeAVs, see_avs);
- msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds, any_av_sounds);
- msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds, group_av_sounds);
- }
- setSeeAVs((bool) see_avs);
- setAllowAnyAVSounds((bool) any_av_sounds);
- setAllowGroupAVSounds((bool) group_av_sounds);
-
- setHaveNewParcelLimitData(have_new_parcel_limit_data);
-
- // non-optimized version
- msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale );
-
- msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_MediaID, mMediaID );
- msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_GroupID, mGroupID );
- msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_PassPrice, mPassPrice );
- msg->getF32Fast( _PREHASH_ParcelData,_PREHASH_PassHours, mPassHours );
- U8 category;
- msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_Category, category);
- mCategory = (ECategory)category;
- msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_AuthBuyerID, mAuthBuyerID);
- msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_SnapshotID, mSnapshotID);
- msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLocation, mUserLocation);
- msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLookAt, mUserLookAt);
- U8 landing_type;
- msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_LandingType, landing_type);
- mLandingType = (ELandingType)landing_type;
-
- // New Media Data
- // Note: the message has been converted to TCP
- if(msg->has("MediaData"))
- {
- msg->getString("MediaData", "MediaDesc", buffer);
- setMediaDesc(buffer);
- msg->getString("MediaData", "MediaType", buffer);
- setMediaType(buffer);
- msg->getS32("MediaData", "MediaWidth", mMediaWidth);
- msg->getS32("MediaData", "MediaHeight", mMediaHeight);
- msg->getU8 ( "MediaData", "MediaLoop", mMediaLoop );
- // the ObscureMedia and ObscureMusic flags previously set here are no longer used
- }
- else
- {
- setMediaType(std::string("video/vnd.secondlife.qt.legacy"));
- setMediaDesc(std::string("No Description available without Server Upgrade"));
- mMediaLoop = true;
- }
-
- if(msg->getNumberOfBlocks("MediaLinkSharing") > 0)
- {
- msg->getString("MediaLinkSharing", "MediaCurrentURL", buffer);
- setMediaCurrentURL(buffer);
- msg->getU8 ( "MediaLinkSharing", "MediaAllowNavigate", mMediaAllowNavigate );
- msg->getU8 ( "MediaLinkSharing", "MediaPreventCameraZoom", mMediaPreventCameraZoom );
- msg->getF32( "MediaLinkSharing", "MediaURLTimeout", mMediaURLTimeout);
- }
- else
- {
- setMediaCurrentURL(LLStringUtil::null);
- }
-
-}
-
-void LLParcel::packAccessEntries(LLMessageSystem* msg,
- const std::map<LLUUID,LLAccessEntry>& list)
-{
- LLAccessEntry::map::const_iterator cit = list.begin();
- LLAccessEntry::map::const_iterator end = list.end();
-
- if (cit == end)
- {
- msg->nextBlockFast(_PREHASH_List);
- msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
- msg->addS32Fast(_PREHASH_Time, 0 );
- msg->addU32Fast(_PREHASH_Flags, 0 );
- return;
- }
-
- for ( ; cit != end; ++cit)
- {
- const LLAccessEntry& entry = (*cit).second;
-
- msg->nextBlockFast(_PREHASH_List);
- msg->addUUIDFast(_PREHASH_ID, entry.mID );
- msg->addS32Fast(_PREHASH_Time, entry.mTime );
- msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
- }
-}
-
-
-void LLParcel::unpackAccessEntries(LLMessageSystem* msg,
- std::map<LLUUID,LLAccessEntry>* list)
-{
- LLUUID id;
- S32 time;
- U32 flags;
-
- S32 i;
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
- for (i = 0; i < count; i++)
- {
- msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
- msg->getS32Fast( _PREHASH_List, _PREHASH_Time, time, i);
- msg->getU32Fast( _PREHASH_List, _PREHASH_Flags, flags, i);
-
- if (id.notNull())
- {
- LLAccessEntry entry;
- entry.mID = id;
- entry.mTime = time;
- entry.mFlags = flags;
-
- (*list)[entry.mID] = entry;
- }
- }
-}
-
-
-void LLParcel::unpackExperienceEntries( LLMessageSystem* msg, U32 type )
-{
- LLUUID id;
-
- S32 i;
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
- for (i = 0; i < count; i++)
- {
- msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
-
- if (id.notNull())
- {
- mExperienceKeys[id]=type;
- }
- }
-}
-
-
-
-void LLParcel::expirePasses(S32 now)
-{
- LLAccessEntry::map::iterator itor = mAccessList.begin();
- while (itor != mAccessList.end())
- {
- const LLAccessEntry& entry = (*itor).second;
-
- if (entry.mTime != 0 && entry.mTime < now)
- {
- mAccessList.erase(itor++);
- }
- else
- {
- ++itor;
- }
- }
-}
-
-
-bool LLParcel::operator==(const LLParcel &rhs) const
-{
- if (mOwnerID != rhs.mOwnerID)
- return false;
-
- if (mParcelFlags != rhs.mParcelFlags)
- return false;
-
- if (mClaimDate != rhs.mClaimDate)
- return false;
-
- if (mClaimPricePerMeter != rhs.mClaimPricePerMeter)
- return false;
-
- if (mRentPricePerMeter != rhs.mRentPricePerMeter)
- return false;
-
- return true;
-}
-
-// Calculate rent
-S32 LLParcel::getTotalRent() const
-{
- return (S32)floor(0.5f + (F32)mArea * (F32)mRentPricePerMeter * (1.0f - mDiscountRate));
-}
-
-F32 LLParcel::getAdjustedRentPerMeter() const
-{
- return ((F32)mRentPricePerMeter * (1.0f - mDiscountRate));
-}
-
-LLVector3 LLParcel::getCenterpoint() const
-{
- LLVector3 rv;
- rv.mV[VX] = (getAABBMin().mV[VX] + getAABBMax().mV[VX]) * 0.5f;
- rv.mV[VY] = (getAABBMin().mV[VY] + getAABBMax().mV[VY]) * 0.5f;
- rv.mV[VZ] = 0.0f;
- return rv;
-}
-
-void LLParcel::extendAABB(const LLVector3& box_min, const LLVector3& box_max)
-{
- // Patch up min corner of AABB
- S32 i;
- for (i=0; i<3; i++)
- {
- if (box_min.mV[i] < mAABBMin.mV[i])
- {
- mAABBMin.mV[i] = box_min.mV[i];
- }
- }
-
- // Patch up max corner of AABB
- for (i=0; i<3; i++)
- {
- if (box_max.mV[i] > mAABBMax.mV[i])
- {
- mAABBMax.mV[i] = box_max.mV[i];
- }
- }
-}
-
-bool LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
-{
- if (mAccessList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
- {
- return false;
- }
- if (agent_id == getOwnerID())
- {
- // Can't add owner to these lists
- return false;
- }
- LLAccessEntry::map::iterator itor = mAccessList.begin();
- while (itor != mAccessList.end())
- {
- const LLAccessEntry& entry = (*itor).second;
- if (entry.mID == agent_id)
- {
- if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
- {
- mAccessList.erase(itor++);
- }
- else
- {
- // existing one expires later
- return false;
- }
- }
- else
- {
- ++itor;
- }
- }
-
- LLAccessEntry new_entry;
- new_entry.mID = agent_id;
- new_entry.mTime = time;
- new_entry.mFlags = 0x0;
- mAccessList[new_entry.mID] = new_entry;
- return true;
-}
-
-bool LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
-{
- if (mBanList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
- {
- // Not using ban list, so not a rational thing to do
- return false;
- }
- if (agent_id == getOwnerID())
- {
- // Can't add owner to these lists
- return false;
- }
-
- LLAccessEntry::map::iterator itor = mBanList.begin();
- while (itor != mBanList.end())
- {
- const LLAccessEntry& entry = (*itor).second;
- if (entry.mID == agent_id)
- {
- if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
- {
- mBanList.erase(itor++);
- }
- else
- {
- // existing one expires later
- return false;
- }
- }
- else
- {
- ++itor;
- }
- }
-
- LLAccessEntry new_entry;
- new_entry.mID = agent_id;
- new_entry.mTime = time;
- new_entry.mFlags = 0x0;
- mBanList[new_entry.mID] = new_entry;
- return true;
-}
-
-bool remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list,
- const LLUUID& agent_id)
-{
- bool removed = false;
- LLAccessEntry::map::iterator itor = list->begin();
- while (itor != list->end())
- {
- const LLAccessEntry& entry = (*itor).second;
- if (entry.mID == agent_id)
- {
- list->erase(itor++);
- removed = true;
- }
- else
- {
- ++itor;
- }
- }
- return removed;
-}
-
-bool LLParcel::removeFromAccessList(const LLUUID& agent_id)
-{
- return remove_from_access_array(&mAccessList, agent_id);
-}
-
-bool LLParcel::removeFromBanList(const LLUUID& agent_id)
-{
- return remove_from_access_array(&mBanList, agent_id);
-}
-
-// static
-const std::string& LLParcel::getOwnershipStatusString(EOwnershipStatus status)
-{
- return ownership_status_to_string(status);
-}
-
-// static
-const std::string& LLParcel::getCategoryString(ECategory category)
-{
- return category_to_string(category);
-}
-
-// static
-const std::string& LLParcel::getCategoryUIString(ECategory category)
-{
- return category_to_ui_string(category);
-}
-
-// static
-LLParcel::ECategory LLParcel::getCategoryFromString(const std::string& string)
-{
- return category_string_to_category(string);
-}
-
-// static
-LLParcel::ECategory LLParcel::getCategoryFromUIString(const std::string& string)
-{
- return category_ui_string_to_category(string);
-}
-
-// static
-const std::string& LLParcel::getActionString(LLParcel::EAction action)
-{
- S32 index = 0;
- if((action >= 0) && (action < LLParcel::A_COUNT))
- {
- index = action;
- }
- else
- {
- index = A_COUNT;
- }
- return PARCEL_ACTION_STRING[index];
-}
-
-bool LLParcel::isSaleTimerExpired(const U64& time)
-{
- if (!mSaleTimerExpires.getStarted())
- {
- return false;
- }
- bool expired = mSaleTimerExpires.checkExpirationAndReset(0.0);
- if (expired)
- {
- mSaleTimerExpires.stop();
- }
- return expired;
-}
-
-bool LLParcel::isMediaResetTimerExpired(const U64& time)
-{
- if (!mMediaResetTimer.getStarted())
- {
- return false;
- }
- bool expired = mMediaResetTimer.checkExpirationAndReset(0.0);
- if (expired)
- {
- mMediaResetTimer.stop();
- }
- return expired;
-}
-
-
-void LLParcel::startSale(const LLUUID& buyer_id, bool is_buyer_group)
-{
- // TODO -- this and all Sale related methods need to move out of the LLParcel
- // base class and into server-side-only LLSimParcel class
- setPreviousOwnerID(mOwnerID);
- setPreviouslyGroupOwned(mGroupOwned);
-
- mOwnerID = buyer_id;
- mGroupOwned = is_buyer_group;
- if(mGroupOwned)
- {
- mGroupID = mOwnerID;
- }
- else
- {
- mGroupID.setNull();
- }
- mSaleTimerExpires.start();
- mSaleTimerExpires.setTimerExpirySec(U64Microseconds(DEFAULT_USEC_SALE_TIMEOUT));
- mStatus = OS_LEASE_PENDING;
- mClaimDate = time(NULL);
- setAuctionID(0);
- // clear the autoreturn whenever land changes hands
- setCleanOtherTime(0);
-}
-
-void LLParcel::expireSale(
- U32& type,
- U8& flags,
- LLUUID& from_id,
- LLUUID& to_id)
-{
- mSaleTimerExpires.setTimerExpirySec(0.0);
- mSaleTimerExpires.stop();
- setPreviousOwnerID(LLUUID::null);
- setPreviouslyGroupOwned(false);
- setSellWithObjects(false);
- type = TRANS_LAND_RELEASE;
- mStatus = OS_NONE;
- flags = pack_transaction_flags(mGroupOwned, false);
- mAuthBuyerID.setNull();
- from_id = mOwnerID;
- mOwnerID.setNull();
- to_id.setNull();
-}
-
-void LLParcel::completeSale(
- U32& type,
- U8& flags,
- LLUUID& to_id)
-{
- mSaleTimerExpires.setTimerExpirySec(0.0);
- mSaleTimerExpires.stop();
- mStatus = OS_LEASED;
- type = TRANS_LAND_SALE;
- flags = pack_transaction_flags(mGroupOwned, mGroupOwned);
- to_id = mOwnerID;
- mAuthBuyerID.setNull();
-
- // Purchased parcels are assumed to no longer be for sale.
- // Otherwise someone can snipe the sale.
- setForSale(false);
- setAuctionID(0);
-
- // Turn off show directory, since it's a recurring fee that
- // the buyer may not want.
- setParcelFlag(PF_SHOW_DIRECTORY, false);
-
- //should be cleared on sale.
- mAccessList.clear();
- mBanList.clear();
-}
-
-void LLParcel::clearSale()
-{
- mSaleTimerExpires.setTimerExpirySec(0.0);
- mSaleTimerExpires.stop();
- if(isPublic())
- {
- mStatus = OS_NONE;
- }
- else
- {
- mStatus = OS_LEASED;
- }
- mAuthBuyerID.setNull();
- setForSale(false);
- setAuctionID(0);
- setPreviousOwnerID(LLUUID::null);
- setPreviouslyGroupOwned(false);
- setSellWithObjects(false);
-}
-
-bool LLParcel::isPublic() const
-{
- return (mOwnerID.isNull());
-}
-
-bool LLParcel::isBuyerAuthorized(const LLUUID& buyer_id) const
-{
- if(mAuthBuyerID.isNull())
- {
- return true;
- }
- return (mAuthBuyerID == buyer_id);
-}
-
-void LLParcel::clearParcel()
-{
- overrideParcelFlags(PF_DEFAULT);
- setName(LLStringUtil::null);
- setDesc(LLStringUtil::null);
- setMediaURL(LLStringUtil::null);
- setMediaType(LLStringUtil::null);
- setMediaID(LLUUID::null);
- setMediaDesc(LLStringUtil::null);
- setMediaAutoScale(0);
- setMediaLoop(1);
- mMediaWidth = 0;
- mMediaHeight = 0;
- setMediaCurrentURL(LLStringUtil::null);
- setMediaAllowNavigate(1);
- setMediaPreventCameraZoom(0);
- setMediaURLTimeout(0.0f);
- setMusicURL(LLStringUtil::null);
- setInEscrow(false);
- setAuthorizedBuyerID(LLUUID::null);
- setCategory(C_NONE);
- setSnapshotID(LLUUID::null);
- setUserLocation(LLVector3::zero);
- setUserLookAt(LLVector3::x_axis);
- setLandingType(L_LANDING_POINT);
- setAuctionID(0);
- setGroupID(LLUUID::null);
- setPassPrice(0);
- setPassHours(0.f);
- mAccessList.clear();
- mBanList.clear();
- //mRenterList.reset();
-}
-
-void LLParcel::dump()
-{
- LL_INFOS() << "parcel " << mLocalID << " area " << mArea << LL_ENDL;
- LL_INFOS() << " name <" << mName << ">" << LL_ENDL;
- LL_INFOS() << " desc <" << mDesc << ">" << LL_ENDL;
-}
-
-const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status)
-{
- if(status >= 0 && status < LLParcel::OS_COUNT)
- {
- return PARCEL_OWNERSHIP_STATUS_STRING[status];
- }
- return PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT];
-}
-
-LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s)
-{
- for(S32 i = 0; i < LLParcel::OS_COUNT; ++i)
- {
- if(s == PARCEL_OWNERSHIP_STATUS_STRING[i])
- {
- return (LLParcel::EOwnershipStatus)i;
- }
- }
- return LLParcel::OS_NONE;
-}
-
-//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action)
-//{
-// S32 index = 0;
-// if(action >= 0 && action < LLParcel::STEA_COUNT)
-// {
-// index = action;
-// }
-// return PARCEL_SALE_TIMER_ACTION[index];
-//}
-
-//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s)
-//{
-// for(S32 i = 0; i < LLParcel::STEA_COUNT; ++i)
-// {
-// if(0 == strcmp(s, PARCEL_SALE_TIMER_ACTION[i]))
-// {
-// return (LLParcel::ESaleTimerExpireAction)i;
-// }
-// }
-// return LLParcel::STEA_REVERT;
-//}
-
-const std::string& category_to_string(LLParcel::ECategory category)
-{
- S32 index = 0;
- if((category >= 0) && (category < LLParcel::C_COUNT))
- {
- index = category;
- }
- return PARCEL_CATEGORY_STRING[index];
-}
-
-const std::string& category_to_ui_string(LLParcel::ECategory category)
-{
- S32 index = 0;
- if((category >= 0) && (category < LLParcel::C_COUNT))
- {
- index = category;
- }
- else
- {
- // C_ANY = -1 , but the "Any" string is at the end of the list
- index = ((S32) LLParcel::C_COUNT);
- }
- return PARCEL_CATEGORY_UI_STRING[index];
-}
-
-LLParcel::ECategory category_string_to_category(const std::string& s)
-{
- for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
- {
- if(s == PARCEL_CATEGORY_STRING[i])
- {
- return (LLParcel::ECategory)i;
- }
- }
- LL_WARNS() << "Parcel category outside of possibilities " << s << LL_ENDL;
- return LLParcel::C_NONE;
-}
-
-LLParcel::ECategory category_ui_string_to_category(const std::string& s)
-{
- for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
- {
- if(s == PARCEL_CATEGORY_UI_STRING[i])
- {
- return (LLParcel::ECategory)i;
- }
- }
- // "Any" is a valid category for searches, and
- // is a distinct option from "None" and "Other"
- return LLParcel::C_ANY;
-}
-
-LLAccessEntry::map LLParcel::getExperienceKeysByType( U32 type ) const
-{
- LLAccessEntry::map access;
- LLAccessEntry entry;
- xp_type_map_t::const_iterator it = mExperienceKeys.begin();
- for(/**/; it != mExperienceKeys.end(); ++it)
- {
- if(it->second == type)
- {
- entry.mID = it->first;
- access[entry.mID] = entry;
- }
- }
- return access;
-}
-
-void LLParcel::clearExperienceKeysByType( U32 type )
-{
- xp_type_map_t::iterator it = mExperienceKeys.begin();
- while(it != mExperienceKeys.end())
- {
- if(it->second == type)
- {
- mExperienceKeys.erase(it++);
- }
- else
- {
- ++it;
- }
- }
-}
-
-void LLParcel::setExperienceKeyType( const LLUUID& experience_key, U32 type )
-{
- if(type == EXPERIENCE_KEY_TYPE_NONE)
- {
- mExperienceKeys.erase(experience_key);
- }
- else
- {
- if(countExperienceKeyType(type) < PARCEL_MAX_EXPERIENCE_LIST)
- {
- mExperienceKeys[experience_key] = type;
- }
- }
-}
-
-U32 LLParcel::countExperienceKeyType( U32 type )
-{
- return std::count_if(
- boost::begin(mExperienceKeys | boost::adaptors::map_values),
- boost::end(mExperienceKeys | boost::adaptors::map_values),
- [type](U32 key){ return (key == type); });
-}
+/** + * @file llparcel.cpp + * @brief A land parcel. + * + * $LicenseInfo:firstyear=2002&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 "indra_constants.h" +#include <iostream> + +#include "llparcel.h" +#include "llstreamtools.h" + +#include "llmath.h" +#include "llsd.h" +#include "llsdutil.h" +#include "lltransactiontypes.h" +#include "lltransactionflags.h" +#include "llsdutil_math.h" +#include "message.h" +#include "u64.h" +#include "llregionflags.h" +#include <boost/range/adaptor/map.hpp> + +static const F32 SOME_BIG_NUMBER = 1000.0f; +static const F32 SOME_BIG_NEG_NUMBER = -1000.0f; +static const std::string PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT+1] = +{ + "leased", + "lease_pending", + "abandoned", + "none" +}; + +// NOTE: Adding parcel categories also requires updating: +// * floater_about_land.xml category combobox +// * Web site "create event" tools +// DO NOT DELETE ITEMS FROM THIS LIST WITHOUT DEEPLY UNDERSTANDING WHAT YOU'RE DOING. +// +static const std::string PARCEL_CATEGORY_STRING[LLParcel::C_COUNT] = +{ + "none", + "linden", + "adult", + "arts", + "store", // "business" legacy name + "educational", + "game", // "gaming" legacy name + "gather", // "hangout" legacy name + "newcomer", + "park", + "home", // "residential" legacy name + "shopping", + "stage", + "other", + "rental" +}; +static const std::string PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] = +{ + "None", + "Linden Location", + "Adult", + "Arts and Culture", + "Business", + "Educational", + "Gaming", + "Hangout", + "Newcomer Friendly", + "Parks and Nature", + "Residential", + "Shopping", + "Stage", + "Other", + "Rental", + "Any", // valid string for parcel searches +}; + +static const std::string PARCEL_ACTION_STRING[LLParcel::A_COUNT + 1] = +{ + "create", + "release", + "absorb", + "absorbed", + "divide", + "division", + "acquire", + "relinquish", + "confirm", + "unknown" +}; + + + +//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action); +//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s); +const std::string& category_to_ui_string(LLParcel::ECategory category); +LLParcel::ECategory category_ui_string_to_category(const std::string& s); + +LLParcel::LLParcel() +{ + init(LLUUID::null, true, false, false, 0, 0, 0, 0, 0, 1.f, 0); +} + + +LLParcel::LLParcel(const LLUUID &owner_id, + bool modify, bool terraform, bool damage, + time_t claim_date, S32 claim_price_per_meter, + S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus, + bool is_group_owned) +{ + init( owner_id, modify, terraform, damage, claim_date, + claim_price_per_meter, rent_price_per_meter, area, sim_object_limit, parcel_object_bonus, + is_group_owned); +} + + +// virtual +LLParcel::~LLParcel() +{ + // user list cleaned up by std::vector destructor. +} + +void LLParcel::init(const LLUUID &owner_id, + bool modify, bool terraform, bool damage, + time_t claim_date, S32 claim_price_per_meter, + S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus, + bool is_group_owned) +{ + mID.setNull(); + mOwnerID = owner_id; + mGroupOwned = is_group_owned; + mClaimDate = claim_date; + mClaimPricePerMeter = claim_price_per_meter; + mRentPricePerMeter = rent_price_per_meter; + mArea = area; + mDiscountRate = 1.0f; + mDrawDistance = 512.f; + + mUserLookAt.setVec(0.0f, 0.f, 0.f); + // Default to using the parcel's landing point, if any. + mLandingType = L_LANDING_POINT; + + // *FIX: if owner_id != null, should be owned or sale pending, + // investigate init callers. + mStatus = OS_NONE; + mCategory = C_NONE; + mAuthBuyerID.setNull(); + //mBuyerID.setNull(); + //mJoinNeighbors = 0x0; + mSaleTimerExpires.setTimerExpirySec(0); + mSaleTimerExpires.stop(); + mGraceExtension = 0; + //mExpireAction = STEA_REVERT; + //mRecordTransaction = false; + + mAuctionID = 0; + mInEscrow = false; + + mParcelFlags = PF_DEFAULT; + setParcelFlag(PF_CREATE_OBJECTS, modify); + setParcelFlag(PF_ALLOW_TERRAFORM, terraform); + setParcelFlag(PF_ALLOW_DAMAGE, damage); + + mSalePrice = 10000; + setName(LLStringUtil::null); + setDesc(LLStringUtil::null); + setMusicURL(LLStringUtil::null); + setMediaURL(LLStringUtil::null); + setMediaDesc(LLStringUtil::null); + setMediaType(LLStringUtil::null); + mMediaID.setNull(); + mMediaAutoScale = 0; + mMediaLoop = 1; + mMediaWidth = 0; + mMediaHeight = 0; + setMediaCurrentURL(LLStringUtil::null); + mMediaAllowNavigate = 1; + mMediaURLTimeout = 0.0f; + mMediaPreventCameraZoom = 0; + + mGroupID.setNull(); + + mPassPrice = PARCEL_PASS_PRICE_DEFAULT; + mPassHours = PARCEL_PASS_HOURS_DEFAULT; + + mAABBMin.setVec(SOME_BIG_NUMBER, SOME_BIG_NUMBER, SOME_BIG_NUMBER); + mAABBMax.setVec(SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER); + + mLocalID = INVALID_PARCEL_ID; + + //mSimWidePrimCorrection = 0; + setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS))); + setSimWideMaxPrimCapacity(0); + setSimWidePrimCount(0); + setOwnerPrimCount(0); + setGroupPrimCount(0); + setOtherPrimCount(0); + setSelectedPrimCount(0); + setTempPrimCount(0); + setCleanOtherTime(0); + setRegionPushOverride(false); + setRegionDenyAnonymousOverride(false); + setRegionDenyAgeUnverifiedOverride(false); + setParcelPrimBonus(parcel_object_bonus); + + setPreviousOwnerID(LLUUID::null); + setPreviouslyGroupOwned(false); + + setSeeAVs(true); + setAllowGroupAVSounds(true); + setAllowAnyAVSounds(true); + setHaveNewParcelLimitData(false); + + setRegionAllowEnvironmentOverride(false); + setParcelEnvironmentVersion(INVALID_PARCEL_ENVIRONMENT_VERSION); + + setObscureMOAP(false); +} + +void LLParcel::overrideOwner(const LLUUID& owner_id, bool is_group_owned) +{ + // Override with system permission (LLUUID::null) + // Overridden parcels have no group + mOwnerID = owner_id; + mGroupOwned = is_group_owned; + if(mGroupOwned) + { + mGroupID = mOwnerID; + } + else + { + mGroupID.setNull(); + } + mInEscrow = false; +} + +void LLParcel::overrideParcelFlags(U32 flags) +{ + mParcelFlags = flags; +} +void LLParcel::setName(const std::string& name) +{ + // The escaping here must match the escaping in the database + // abstraction layer. + mName = name; + LLStringFn::replace_nonprintable_in_ascii(mName, LL_UNKNOWN_CHAR); +} + +void LLParcel::setDesc(const std::string& desc) +{ + // The escaping here must match the escaping in the database + // abstraction layer. + mDesc = desc; + mDesc = rawstr_to_utf8(mDesc); +} + +void LLParcel::setMusicURL(const std::string& url) +{ + mMusicURL = url; + // The escaping here must match the escaping in the database + // abstraction layer. + // This should really filter the url in some way. Other than + // simply requiring non-printable. + LLStringFn::replace_nonprintable_in_ascii(mMusicURL, LL_UNKNOWN_CHAR); +} + +void LLParcel::setMediaURL(const std::string& url) +{ + mMediaURL = url; + // The escaping here must match the escaping in the database + // abstraction layer if it's ever added. + // This should really filter the url in some way. Other than + // simply requiring non-printable. + LLStringFn::replace_nonprintable_in_ascii(mMediaURL, LL_UNKNOWN_CHAR); +} + +void LLParcel::setMediaDesc(const std::string& desc) +{ + // The escaping here must match the escaping in the database + // abstraction layer. + mMediaDesc = desc; + mMediaDesc = rawstr_to_utf8(mMediaDesc); +} +void LLParcel::setMediaType(const std::string& type) +{ + // The escaping here must match the escaping in the database + // abstraction layer. + mMediaType = type; + mMediaType = rawstr_to_utf8(mMediaType); + + // This code attempts to preserve legacy movie functioning + if(mMediaType.empty() && ! mMediaURL.empty()) + { + setMediaType(std::string("video/vnd.secondlife.qt.legacy")); + } +} +void LLParcel::setMediaWidth(S32 width) +{ + mMediaWidth = width; +} +void LLParcel::setMediaHeight(S32 height) +{ + mMediaHeight = height; +} + +void LLParcel::setMediaCurrentURL(const std::string& url) +{ + mMediaCurrentURL = url; + // The escaping here must match the escaping in the database + // abstraction layer if it's ever added. + // This should really filter the url in some way. Other than + // simply requiring non-printable. + LLStringFn::replace_nonprintable_in_ascii(mMediaCurrentURL, LL_UNKNOWN_CHAR); + +} + +void LLParcel::setMediaURLResetTimer(F32 time) +{ + mMediaResetTimer.start(); + mMediaResetTimer.setTimerExpirySec(time); +} + +// virtual +void LLParcel::setLocalID(S32 local_id) +{ + mLocalID = local_id; +} + +void LLParcel::setAllParcelFlags(U32 flags) +{ + mParcelFlags = flags; +} + +void LLParcel::setParcelFlag(U32 flag, bool b) +{ + if (b) + { + mParcelFlags |= flag; + } + else + { + mParcelFlags &= ~flag; + } +} + + +bool LLParcel::allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const +{ + if (agent_id == LLUUID::null) + { + // system always can enter + return true; + } + else if (isPublic()) + { + return true; + } + else if (agent_id == mOwnerID) + { + // owner can always perform operations + return true; + } + else if (mParcelFlags & PF_CREATE_OBJECTS) + { + return true; + } + else if ((mParcelFlags & PF_CREATE_GROUP_OBJECTS) + && group_id.notNull() ) + { + return (getGroupID() == group_id); + } + + return false; +} + +bool LLParcel::allowTerraformBy(const LLUUID &agent_id) const +{ + if (agent_id == LLUUID::null) + { + // system always can enter + return true; + } + else if(OS_LEASED == mStatus) + { + if(agent_id == mOwnerID) + { + // owner can modify leased land + return true; + } + else + { + // otherwise check other people + return mParcelFlags & PF_ALLOW_TERRAFORM; + } + } + else + { + return false; + } +} + + + +void LLParcel::setArea(S32 area, S32 sim_object_limit) +{ + mArea = area; + setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS))); +} + +void LLParcel::setDiscountRate(F32 rate) +{ + // this is to make sure that the rate is at least sane - this is + // not intended to enforce economy rules. It only enfoces that the + // rate is a scaler between 0 and 1. + mDiscountRate = llclampf(rate); +} + + +//----------------------------------------------------------- +// File input and output +//----------------------------------------------------------- + +bool LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entry) +{ + skip_to_end_of_next_keyword("{", input_stream); + while (input_stream.good()) + { + skip_comments_and_emptyspace(input_stream); + std::string line, keyword, value; + get_line(line, input_stream, MAX_STRING); + get_keyword_and_value(keyword, value, line); + + if ("}" == keyword) + { + break; + } + else if ("id" == keyword) + { + entry->mID.set( value ); + } + else if ("name" == keyword) + { + // deprecated + } + else if ("time" == keyword) + { + S32 when{}; + LLStringUtil::convertToS32(value, when); + entry->mTime = when; + } + else if ("flags" == keyword) + { + U32 setting{}; + LLStringUtil::convertToU32(value, setting); + entry->mFlags = setting; + } + else + { + LL_WARNS() << "Unknown keyword in parcel access entry section: <" + << keyword << ">" << LL_ENDL; + } + } + return input_stream.good(); +} + +// Assumes we are in a block "ParcelData" +void LLParcel::packMessage(LLMessageSystem* msg) +{ + msg->addU32Fast( _PREHASH_ParcelFlags, getParcelFlags() ); + msg->addS32Fast( _PREHASH_SalePrice, getSalePrice() ); + msg->addStringFast( _PREHASH_Name, getName() ); + msg->addStringFast( _PREHASH_Desc, getDesc() ); + msg->addStringFast( _PREHASH_MusicURL, getMusicURL() ); + msg->addStringFast( _PREHASH_MediaURL, getMediaURL() ); + msg->addU8 ( "MediaAutoScale", getMediaAutoScale () ); + msg->addUUIDFast( _PREHASH_MediaID, getMediaID() ); + msg->addUUIDFast( _PREHASH_GroupID, getGroupID() ); + msg->addS32Fast( _PREHASH_PassPrice, mPassPrice ); + msg->addF32Fast( _PREHASH_PassHours, mPassHours ); + msg->addU8Fast( _PREHASH_Category, (U8)mCategory); + msg->addUUIDFast( _PREHASH_AuthBuyerID, mAuthBuyerID); + msg->addUUIDFast( _PREHASH_SnapshotID, mSnapshotID); + msg->addVector3Fast(_PREHASH_UserLocation, mUserLocation); + msg->addVector3Fast(_PREHASH_UserLookAt, mUserLookAt); + msg->addU8Fast( _PREHASH_LandingType, (U8)mLandingType); +} + +// Assumes we are in a block "ParcelData" +void LLParcel::packMessage(LLSD& msg) +{ + // used in the viewer, the sim uses it's own packer + msg["local_id"] = getLocalID(); + msg["parcel_flags"] = ll_sd_from_U32(getParcelFlags()); + msg["sale_price"] = getSalePrice(); + msg["name"] = getName(); + msg["description"] = getDesc(); + msg["music_url"] = getMusicURL(); + msg["media_url"] = getMediaURL(); + msg["media_desc"] = getMediaDesc(); + msg["media_type"] = getMediaType(); + msg["media_width"] = getMediaWidth(); + msg["media_height"] = getMediaHeight(); + msg["auto_scale"] = getMediaAutoScale(); + msg["media_loop"] = getMediaLoop(); + msg["media_current_url"] = getMediaCurrentURL(); + msg["obscure_media"] = false; // OBSOLETE - no longer used + msg["obscure_music"] = false; // OBSOLETE - no longer used + msg["media_id"] = getMediaID(); + msg["media_allow_navigate"] = getMediaAllowNavigate(); + msg["media_prevent_camera_zoom"] = getMediaPreventCameraZoom(); + msg["media_url_timeout"] = getMediaURLTimeout(); + msg["group_id"] = getGroupID(); + msg["pass_price"] = mPassPrice; + msg["pass_hours"] = mPassHours; + msg["category"] = (U8)mCategory; + msg["auth_buyer_id"] = mAuthBuyerID; + msg["snapshot_id"] = mSnapshotID; + msg["user_location"] = ll_sd_from_vector3(mUserLocation); + msg["user_look_at"] = ll_sd_from_vector3(mUserLookAt); + msg["landing_type"] = (U8)mLandingType; + msg["see_avs"] = (LLSD::Boolean) getSeeAVs(); + msg["group_av_sounds"] = (LLSD::Boolean) getAllowGroupAVSounds(); + msg["any_av_sounds"] = (LLSD::Boolean) getAllowAnyAVSounds(); + msg["obscure_moap"] = (LLSD::Boolean) getObscureMOAP(); +} + + +void LLParcel::unpackMessage(LLMessageSystem* msg) +{ + std::string buffer; + + msg->getU32Fast( _PREHASH_ParcelData,_PREHASH_ParcelFlags, mParcelFlags ); + msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_SalePrice, mSalePrice ); + msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Name, buffer ); + setName(buffer); + msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Desc, buffer ); + setDesc(buffer); + msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MusicURL, buffer ); + setMusicURL(buffer); + msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, buffer ); + setMediaURL(buffer); + + bool see_avs = true; // All default to true for legacy server behavior + bool any_av_sounds = true; + bool group_av_sounds = true; + bool have_new_parcel_limit_data = (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_SeeAVs) > 0); // New version of server should send all 3 of these values + have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds) > 0); + have_new_parcel_limit_data &= (msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds) > 0); + if (have_new_parcel_limit_data) + { + msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_SeeAVs, see_avs); + msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_AnyAVSounds, any_av_sounds); + msg->getBOOLFast(_PREHASH_ParcelData, _PREHASH_GroupAVSounds, group_av_sounds); + } + setSeeAVs((bool) see_avs); + setAllowAnyAVSounds((bool) any_av_sounds); + setAllowGroupAVSounds((bool) group_av_sounds); + + setHaveNewParcelLimitData(have_new_parcel_limit_data); + + // non-optimized version + msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale ); + + msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_MediaID, mMediaID ); + msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_GroupID, mGroupID ); + msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_PassPrice, mPassPrice ); + msg->getF32Fast( _PREHASH_ParcelData,_PREHASH_PassHours, mPassHours ); + U8 category; + msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_Category, category); + mCategory = (ECategory)category; + msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_AuthBuyerID, mAuthBuyerID); + msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_SnapshotID, mSnapshotID); + msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLocation, mUserLocation); + msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLookAt, mUserLookAt); + U8 landing_type; + msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_LandingType, landing_type); + mLandingType = (ELandingType)landing_type; + + // New Media Data + // Note: the message has been converted to TCP + if(msg->has("MediaData")) + { + msg->getString("MediaData", "MediaDesc", buffer); + setMediaDesc(buffer); + msg->getString("MediaData", "MediaType", buffer); + setMediaType(buffer); + msg->getS32("MediaData", "MediaWidth", mMediaWidth); + msg->getS32("MediaData", "MediaHeight", mMediaHeight); + msg->getU8 ( "MediaData", "MediaLoop", mMediaLoop ); + // the ObscureMedia and ObscureMusic flags previously set here are no longer used + } + else + { + setMediaType(std::string("video/vnd.secondlife.qt.legacy")); + setMediaDesc(std::string("No Description available without Server Upgrade")); + mMediaLoop = true; + } + + if(msg->getNumberOfBlocks("MediaLinkSharing") > 0) + { + msg->getString("MediaLinkSharing", "MediaCurrentURL", buffer); + setMediaCurrentURL(buffer); + msg->getU8 ( "MediaLinkSharing", "MediaAllowNavigate", mMediaAllowNavigate ); + msg->getU8 ( "MediaLinkSharing", "MediaPreventCameraZoom", mMediaPreventCameraZoom ); + msg->getF32( "MediaLinkSharing", "MediaURLTimeout", mMediaURLTimeout); + } + else + { + setMediaCurrentURL(LLStringUtil::null); + } + +} + +void LLParcel::packAccessEntries(LLMessageSystem* msg, + const std::map<LLUUID,LLAccessEntry>& list) +{ + LLAccessEntry::map::const_iterator cit = list.begin(); + LLAccessEntry::map::const_iterator end = list.end(); + + if (cit == end) + { + msg->nextBlockFast(_PREHASH_List); + msg->addUUIDFast(_PREHASH_ID, LLUUID::null ); + msg->addS32Fast(_PREHASH_Time, 0 ); + msg->addU32Fast(_PREHASH_Flags, 0 ); + return; + } + + for ( ; cit != end; ++cit) + { + const LLAccessEntry& entry = (*cit).second; + + msg->nextBlockFast(_PREHASH_List); + msg->addUUIDFast(_PREHASH_ID, entry.mID ); + msg->addS32Fast(_PREHASH_Time, entry.mTime ); + msg->addU32Fast(_PREHASH_Flags, entry.mFlags ); + } +} + + +void LLParcel::unpackAccessEntries(LLMessageSystem* msg, + std::map<LLUUID,LLAccessEntry>* list) +{ + LLUUID id; + S32 time; + U32 flags; + + S32 i; + S32 count = msg->getNumberOfBlocksFast(_PREHASH_List); + for (i = 0; i < count; i++) + { + msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i); + msg->getS32Fast( _PREHASH_List, _PREHASH_Time, time, i); + msg->getU32Fast( _PREHASH_List, _PREHASH_Flags, flags, i); + + if (id.notNull()) + { + LLAccessEntry entry; + entry.mID = id; + entry.mTime = time; + entry.mFlags = flags; + + (*list)[entry.mID] = entry; + } + } +} + + +void LLParcel::unpackExperienceEntries( LLMessageSystem* msg, U32 type ) +{ + LLUUID id; + + S32 i; + S32 count = msg->getNumberOfBlocksFast(_PREHASH_List); + for (i = 0; i < count; i++) + { + msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i); + + if (id.notNull()) + { + mExperienceKeys[id]=type; + } + } +} + + + +void LLParcel::expirePasses(S32 now) +{ + LLAccessEntry::map::iterator itor = mAccessList.begin(); + while (itor != mAccessList.end()) + { + const LLAccessEntry& entry = (*itor).second; + + if (entry.mTime != 0 && entry.mTime < now) + { + mAccessList.erase(itor++); + } + else + { + ++itor; + } + } +} + + +bool LLParcel::operator==(const LLParcel &rhs) const +{ + if (mOwnerID != rhs.mOwnerID) + return false; + + if (mParcelFlags != rhs.mParcelFlags) + return false; + + if (mClaimDate != rhs.mClaimDate) + return false; + + if (mClaimPricePerMeter != rhs.mClaimPricePerMeter) + return false; + + if (mRentPricePerMeter != rhs.mRentPricePerMeter) + return false; + + return true; +} + +// Calculate rent +S32 LLParcel::getTotalRent() const +{ + return (S32)floor(0.5f + (F32)mArea * (F32)mRentPricePerMeter * (1.0f - mDiscountRate)); +} + +F32 LLParcel::getAdjustedRentPerMeter() const +{ + return ((F32)mRentPricePerMeter * (1.0f - mDiscountRate)); +} + +LLVector3 LLParcel::getCenterpoint() const +{ + LLVector3 rv; + rv.mV[VX] = (getAABBMin().mV[VX] + getAABBMax().mV[VX]) * 0.5f; + rv.mV[VY] = (getAABBMin().mV[VY] + getAABBMax().mV[VY]) * 0.5f; + rv.mV[VZ] = 0.0f; + return rv; +} + +void LLParcel::extendAABB(const LLVector3& box_min, const LLVector3& box_max) +{ + // Patch up min corner of AABB + S32 i; + for (i=0; i<3; i++) + { + if (box_min.mV[i] < mAABBMin.mV[i]) + { + mAABBMin.mV[i] = box_min.mV[i]; + } + } + + // Patch up max corner of AABB + for (i=0; i<3; i++) + { + if (box_max.mV[i] > mAABBMax.mV[i]) + { + mAABBMax.mV[i] = box_max.mV[i]; + } + } +} + +bool LLParcel::addToAccessList(const LLUUID& agent_id, S32 time) +{ + if (mAccessList.size() >= (U32) PARCEL_MAX_ACCESS_LIST) + { + return false; + } + if (agent_id == getOwnerID()) + { + // Can't add owner to these lists + return false; + } + LLAccessEntry::map::iterator itor = mAccessList.begin(); + while (itor != mAccessList.end()) + { + const LLAccessEntry& entry = (*itor).second; + if (entry.mID == agent_id) + { + if (time == 0 || (entry.mTime != 0 && entry.mTime < time)) + { + mAccessList.erase(itor++); + } + else + { + // existing one expires later + return false; + } + } + else + { + ++itor; + } + } + + LLAccessEntry new_entry; + new_entry.mID = agent_id; + new_entry.mTime = time; + new_entry.mFlags = 0x0; + mAccessList[new_entry.mID] = new_entry; + return true; +} + +bool LLParcel::addToBanList(const LLUUID& agent_id, S32 time) +{ + if (mBanList.size() >= (U32) PARCEL_MAX_ACCESS_LIST) + { + // Not using ban list, so not a rational thing to do + return false; + } + if (agent_id == getOwnerID()) + { + // Can't add owner to these lists + return false; + } + + LLAccessEntry::map::iterator itor = mBanList.begin(); + while (itor != mBanList.end()) + { + const LLAccessEntry& entry = (*itor).second; + if (entry.mID == agent_id) + { + if (time == 0 || (entry.mTime != 0 && entry.mTime < time)) + { + mBanList.erase(itor++); + } + else + { + // existing one expires later + return false; + } + } + else + { + ++itor; + } + } + + LLAccessEntry new_entry; + new_entry.mID = agent_id; + new_entry.mTime = time; + new_entry.mFlags = 0x0; + mBanList[new_entry.mID] = new_entry; + return true; +} + +bool remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list, + const LLUUID& agent_id) +{ + bool removed = false; + LLAccessEntry::map::iterator itor = list->begin(); + while (itor != list->end()) + { + const LLAccessEntry& entry = (*itor).second; + if (entry.mID == agent_id) + { + list->erase(itor++); + removed = true; + } + else + { + ++itor; + } + } + return removed; +} + +bool LLParcel::removeFromAccessList(const LLUUID& agent_id) +{ + return remove_from_access_array(&mAccessList, agent_id); +} + +bool LLParcel::removeFromBanList(const LLUUID& agent_id) +{ + return remove_from_access_array(&mBanList, agent_id); +} + +// static +const std::string& LLParcel::getOwnershipStatusString(EOwnershipStatus status) +{ + return ownership_status_to_string(status); +} + +// static +const std::string& LLParcel::getCategoryString(ECategory category) +{ + return category_to_string(category); +} + +// static +const std::string& LLParcel::getCategoryUIString(ECategory category) +{ + return category_to_ui_string(category); +} + +// static +LLParcel::ECategory LLParcel::getCategoryFromString(const std::string& string) +{ + return category_string_to_category(string); +} + +// static +LLParcel::ECategory LLParcel::getCategoryFromUIString(const std::string& string) +{ + return category_ui_string_to_category(string); +} + +// static +const std::string& LLParcel::getActionString(LLParcel::EAction action) +{ + S32 index = 0; + if((action >= 0) && (action < LLParcel::A_COUNT)) + { + index = action; + } + else + { + index = A_COUNT; + } + return PARCEL_ACTION_STRING[index]; +} + +bool LLParcel::isSaleTimerExpired(const U64& time) +{ + if (!mSaleTimerExpires.getStarted()) + { + return false; + } + bool expired = mSaleTimerExpires.checkExpirationAndReset(0.0); + if (expired) + { + mSaleTimerExpires.stop(); + } + return expired; +} + +bool LLParcel::isMediaResetTimerExpired(const U64& time) +{ + if (!mMediaResetTimer.getStarted()) + { + return false; + } + bool expired = mMediaResetTimer.checkExpirationAndReset(0.0); + if (expired) + { + mMediaResetTimer.stop(); + } + return expired; +} + + +void LLParcel::startSale(const LLUUID& buyer_id, bool is_buyer_group) +{ + // TODO -- this and all Sale related methods need to move out of the LLParcel + // base class and into server-side-only LLSimParcel class + setPreviousOwnerID(mOwnerID); + setPreviouslyGroupOwned(mGroupOwned); + + mOwnerID = buyer_id; + mGroupOwned = is_buyer_group; + if(mGroupOwned) + { + mGroupID = mOwnerID; + } + else + { + mGroupID.setNull(); + } + mSaleTimerExpires.start(); + mSaleTimerExpires.setTimerExpirySec(U64Microseconds(DEFAULT_USEC_SALE_TIMEOUT)); + mStatus = OS_LEASE_PENDING; + mClaimDate = time(NULL); + setAuctionID(0); + // clear the autoreturn whenever land changes hands + setCleanOtherTime(0); +} + +void LLParcel::expireSale( + U32& type, + U8& flags, + LLUUID& from_id, + LLUUID& to_id) +{ + mSaleTimerExpires.setTimerExpirySec(0.0); + mSaleTimerExpires.stop(); + setPreviousOwnerID(LLUUID::null); + setPreviouslyGroupOwned(false); + setSellWithObjects(false); + type = TRANS_LAND_RELEASE; + mStatus = OS_NONE; + flags = pack_transaction_flags(mGroupOwned, false); + mAuthBuyerID.setNull(); + from_id = mOwnerID; + mOwnerID.setNull(); + to_id.setNull(); +} + +void LLParcel::completeSale( + U32& type, + U8& flags, + LLUUID& to_id) +{ + mSaleTimerExpires.setTimerExpirySec(0.0); + mSaleTimerExpires.stop(); + mStatus = OS_LEASED; + type = TRANS_LAND_SALE; + flags = pack_transaction_flags(mGroupOwned, mGroupOwned); + to_id = mOwnerID; + mAuthBuyerID.setNull(); + + // Purchased parcels are assumed to no longer be for sale. + // Otherwise someone can snipe the sale. + setForSale(false); + setAuctionID(0); + + // Turn off show directory, since it's a recurring fee that + // the buyer may not want. + setParcelFlag(PF_SHOW_DIRECTORY, false); + + //should be cleared on sale. + mAccessList.clear(); + mBanList.clear(); +} + +void LLParcel::clearSale() +{ + mSaleTimerExpires.setTimerExpirySec(0.0); + mSaleTimerExpires.stop(); + if(isPublic()) + { + mStatus = OS_NONE; + } + else + { + mStatus = OS_LEASED; + } + mAuthBuyerID.setNull(); + setForSale(false); + setAuctionID(0); + setPreviousOwnerID(LLUUID::null); + setPreviouslyGroupOwned(false); + setSellWithObjects(false); +} + +bool LLParcel::isPublic() const +{ + return (mOwnerID.isNull()); +} + +bool LLParcel::isBuyerAuthorized(const LLUUID& buyer_id) const +{ + if(mAuthBuyerID.isNull()) + { + return true; + } + return (mAuthBuyerID == buyer_id); +} + +void LLParcel::clearParcel() +{ + overrideParcelFlags(PF_DEFAULT); + setName(LLStringUtil::null); + setDesc(LLStringUtil::null); + setMediaURL(LLStringUtil::null); + setMediaType(LLStringUtil::null); + setMediaID(LLUUID::null); + setMediaDesc(LLStringUtil::null); + setMediaAutoScale(0); + setMediaLoop(1); + mMediaWidth = 0; + mMediaHeight = 0; + setMediaCurrentURL(LLStringUtil::null); + setMediaAllowNavigate(1); + setMediaPreventCameraZoom(0); + setMediaURLTimeout(0.0f); + setMusicURL(LLStringUtil::null); + setInEscrow(false); + setAuthorizedBuyerID(LLUUID::null); + setCategory(C_NONE); + setSnapshotID(LLUUID::null); + setUserLocation(LLVector3::zero); + setUserLookAt(LLVector3::x_axis); + setLandingType(L_LANDING_POINT); + setAuctionID(0); + setGroupID(LLUUID::null); + setPassPrice(0); + setPassHours(0.f); + mAccessList.clear(); + mBanList.clear(); + //mRenterList.reset(); +} + +void LLParcel::dump() +{ + LL_INFOS() << "parcel " << mLocalID << " area " << mArea << LL_ENDL; + LL_INFOS() << " name <" << mName << ">" << LL_ENDL; + LL_INFOS() << " desc <" << mDesc << ">" << LL_ENDL; +} + +const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status) +{ + if(status >= 0 && status < LLParcel::OS_COUNT) + { + return PARCEL_OWNERSHIP_STATUS_STRING[status]; + } + return PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT]; +} + +LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s) +{ + for(S32 i = 0; i < LLParcel::OS_COUNT; ++i) + { + if(s == PARCEL_OWNERSHIP_STATUS_STRING[i]) + { + return (LLParcel::EOwnershipStatus)i; + } + } + return LLParcel::OS_NONE; +} + +//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action) +//{ +// S32 index = 0; +// if(action >= 0 && action < LLParcel::STEA_COUNT) +// { +// index = action; +// } +// return PARCEL_SALE_TIMER_ACTION[index]; +//} + +//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s) +//{ +// for(S32 i = 0; i < LLParcel::STEA_COUNT; ++i) +// { +// if(0 == strcmp(s, PARCEL_SALE_TIMER_ACTION[i])) +// { +// return (LLParcel::ESaleTimerExpireAction)i; +// } +// } +// return LLParcel::STEA_REVERT; +//} + +const std::string& category_to_string(LLParcel::ECategory category) +{ + S32 index = 0; + if((category >= 0) && (category < LLParcel::C_COUNT)) + { + index = category; + } + return PARCEL_CATEGORY_STRING[index]; +} + +const std::string& category_to_ui_string(LLParcel::ECategory category) +{ + S32 index = 0; + if((category >= 0) && (category < LLParcel::C_COUNT)) + { + index = category; + } + else + { + // C_ANY = -1 , but the "Any" string is at the end of the list + index = ((S32) LLParcel::C_COUNT); + } + return PARCEL_CATEGORY_UI_STRING[index]; +} + +LLParcel::ECategory category_string_to_category(const std::string& s) +{ + for(S32 i = 0; i < LLParcel::C_COUNT; ++i) + { + if(s == PARCEL_CATEGORY_STRING[i]) + { + return (LLParcel::ECategory)i; + } + } + LL_WARNS() << "Parcel category outside of possibilities " << s << LL_ENDL; + return LLParcel::C_NONE; +} + +LLParcel::ECategory category_ui_string_to_category(const std::string& s) +{ + for(S32 i = 0; i < LLParcel::C_COUNT; ++i) + { + if(s == PARCEL_CATEGORY_UI_STRING[i]) + { + return (LLParcel::ECategory)i; + } + } + // "Any" is a valid category for searches, and + // is a distinct option from "None" and "Other" + return LLParcel::C_ANY; +} + +LLAccessEntry::map LLParcel::getExperienceKeysByType( U32 type ) const +{ + LLAccessEntry::map access; + LLAccessEntry entry; + xp_type_map_t::const_iterator it = mExperienceKeys.begin(); + for(/**/; it != mExperienceKeys.end(); ++it) + { + if(it->second == type) + { + entry.mID = it->first; + access[entry.mID] = entry; + } + } + return access; +} + +void LLParcel::clearExperienceKeysByType( U32 type ) +{ + xp_type_map_t::iterator it = mExperienceKeys.begin(); + while(it != mExperienceKeys.end()) + { + if(it->second == type) + { + mExperienceKeys.erase(it++); + } + else + { + ++it; + } + } +} + +void LLParcel::setExperienceKeyType( const LLUUID& experience_key, U32 type ) +{ + if(type == EXPERIENCE_KEY_TYPE_NONE) + { + mExperienceKeys.erase(experience_key); + } + else + { + if(countExperienceKeyType(type) < PARCEL_MAX_EXPERIENCE_LIST) + { + mExperienceKeys[experience_key] = type; + } + } +} + +U32 LLParcel::countExperienceKeyType( U32 type ) +{ + return std::count_if( + boost::begin(mExperienceKeys | boost::adaptors::map_values), + boost::end(mExperienceKeys | boost::adaptors::map_values), + [type](U32 key){ return (key == type); }); +} diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 06232f3d47..67d713db1f 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -1,677 +1,677 @@ -/**
- * @file llparcel.h
- *
- * $LicenseInfo:firstyear=2002&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$
- */
-
-#ifndef LL_LLPARCEL_H
-#define LL_LLPARCEL_H
-
-#include <time.h>
-#include <iostream>
-
-#include "lluuid.h"
-#include "llparcelflags.h"
-#include "llpermissions.h"
-#include "lltimer.h"
-#include "v3math.h"
-#include "llsettingsdaycycle.h"
-
-// Grid out of which parcels taken is stepped every 4 meters.
-const F32 PARCEL_GRID_STEP_METERS = 4.f;
-
-// Area of one "square" of parcel
-const S32 PARCEL_UNIT_AREA = 16;
-
-// Height _above_ground_ that parcel boundary ends
-const F32 PARCEL_HEIGHT = 50.f;
-
-//Height above ground which parcel boundries exist for explicitly banned avatars
-const F32 BAN_HEIGHT = 5000.f;
-
-// Maximum number of entries in an access list
-const S32 PARCEL_MAX_ACCESS_LIST = 300;
-//Maximum number of entires in an update packet
-//for access/ban lists.
-const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
-
-// Maximum number of experiences
-const S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
-
-// Weekly charge for listing a parcel in the directory
-const S32 PARCEL_DIRECTORY_FEE = 30;
-
-const S32 PARCEL_PASS_PRICE_DEFAULT = 10;
-const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
-
-// Number of "chunks" in which parcel overlay data is sent
-// Chunk 0 = southern rows, entire width
-const S32 PARCEL_OVERLAY_CHUNKS = 4;
-
-// Bottom three bits are a color index for the land overlay
-const U8 PARCEL_COLOR_MASK = 0x07;
-const U8 PARCEL_PUBLIC = 0x00;
-const U8 PARCEL_OWNED = 0x01;
-const U8 PARCEL_GROUP = 0x02;
-const U8 PARCEL_SELF = 0x03;
-const U8 PARCEL_FOR_SALE = 0x04;
-const U8 PARCEL_AUCTION = 0x05;
-// unused 0x06
-// unused 0x07
-// flag, unused 0x08
-const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
-const U8 PARCEL_SOUND_LOCAL = 0x20;
-const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
-const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
-
-// Transmission results for parcel properties
-const S32 PARCEL_RESULT_NO_DATA = -1;
-const S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel
-const S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels
-
-const S32 SELECTED_PARCEL_SEQ_ID = -10000;
-const S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000;
-const S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
-const S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000;
-const S32 HOVERED_PARCEL_SEQ_ID = -50000;
-
-const U32 RT_NONE = 0x1 << 0;
-const U32 RT_OWNER = 0x1 << 1;
-const U32 RT_GROUP = 0x1 << 2;
-const U32 RT_OTHER = 0x1 << 3;
-const U32 RT_LIST = 0x1 << 4;
-const U32 RT_SELL = 0x1 << 5;
-
-const S32 INVALID_PARCEL_ID = -1;
-
-const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
-// if Region settings are used, parcel env. version is -1
-const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
-
-// Timeouts for parcels
-// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
-const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
-// ***** TESTING is 10 minutes
-//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
-
-// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
-const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
-// ***** TESTING is 10 minutes
-//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
-
-// default sale timeout is 2 days -> 172800000000
-const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
-// ***** TESTING is 10 minutes
-//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
-
-// more grace period extensions.
-const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
-
-// if more than 100,000s before sale revert, and no extra extension
-// has been given, go ahead and extend it more. That's about 1.2 days.
-const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
-
-
-
-class LLMessageSystem;
-class LLSD;
-
-class LLAccessEntry
-{
-public:
-
- typedef std::map<LLUUID,LLAccessEntry> map;
-
- LLAccessEntry()
- : mTime(0),
- mFlags(0)
- {}
-
- LLUUID mID; // Agent ID
- S32 mTime; // Time (unix seconds) when entry expires
- U32 mFlags; // Not used - currently should always be zero
-};
-
-
-class LLParcel
-{
-public:
- enum EOwnershipStatus
- {
- OS_LEASED = 0,
- OS_LEASE_PENDING = 1,
- OS_ABANDONED = 2,
- OS_COUNT = 3,
- OS_NONE = -1
- };
- enum ECategory
- {
- C_NONE = 0,
- C_LINDEN,
- C_ADULT,
- C_ARTS, // "arts & culture"
- C_BUSINESS, // was "store"
- C_EDUCATIONAL,
- C_GAMING, // was "game"
- C_HANGOUT, // was "gathering place"
- C_NEWCOMER,
- C_PARK, // "parks & nature"
- C_RESIDENTIAL, // was "homestead"
- C_SHOPPING,
- C_STAGE,
- C_OTHER,
- C_RENTAL,
- C_COUNT,
- C_ANY = -1 // only useful in queries
- };
- enum EAction
- {
- A_CREATE = 0,
- A_RELEASE = 1,
- A_ABSORB = 2,
- A_ABSORBED = 3,
- A_DIVIDE = 4,
- A_DIVISION = 5,
- A_ACQUIRE = 6,
- A_RELINQUISH = 7,
- A_CONFIRM = 8,
- A_COUNT = 9,
- A_UNKNOWN = -1
- };
-
- enum ELandingType
- {
- L_NONE = 0,
- L_LANDING_POINT = 1,
- L_DIRECT = 2
- };
-
- // CREATORS
- LLParcel();
- LLParcel(
- const LLUUID &owner_id,
- bool modify,
- bool terraform,
- bool damage,
- time_t claim_date,
- S32 claim_price,
- S32 rent_price,
- S32 area,
- S32 sim_object_limit,
- F32 parcel_object_bonus,
- bool is_group_owned = false);
- virtual ~LLParcel();
-
- void init(
- const LLUUID &owner_id,
- bool modify,
- bool terraform,
- bool damage,
- time_t claim_date,
- S32 claim_price,
- S32 rent_price,
- S32 area,
- S32 sim_object_limit,
- F32 parcel_object_bonus,
- bool is_group_owned = false);
-
- // TODO: make an actual copy constructor for this
- void overrideParcelFlags(U32 flags);
- // if you specify an agent id here, the group id will be zeroed
- void overrideOwner(
- const LLUUID& owner_id,
- bool is_group_owned = false);
- void overrideSaleTimerExpires(F32 secs_left) { mSaleTimerExpires.setTimerExpirySec(secs_left); }
-
- // MANIPULATORS
- void generateNewID() { mID.generate(); }
- void setName(const std::string& name);
- void setDesc(const std::string& desc);
- void setMusicURL(const std::string& url);
- void setMediaURL(const std::string& url);
- void setMediaType(const std::string& type);
- void setMediaDesc(const std::string& desc);
- void setMediaID(const LLUUID& id) { mMediaID = id; }
- void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
- void setMediaLoop (U8 loop) { mMediaLoop = loop; }
- void setMediaWidth(S32 width);
- void setMediaHeight(S32 height);
- void setMediaCurrentURL(const std::string& url);
- void setMediaAllowNavigate(U8 enable) { mMediaAllowNavigate = enable; }
- void setMediaURLTimeout(F32 timeout) { mMediaURLTimeout = timeout; }
- void setMediaPreventCameraZoom(U8 enable) { mMediaPreventCameraZoom = enable; }
-
- void setMediaURLResetTimer(F32 time);
- virtual void setLocalID(S32 local_id);
-
- // blow away all the extra stuff lurking in parcels, including urls, access lists, etc
- void clearParcel();
-
- // This value is not persisted out to the parcel file, it is only
- // a per-process blocker for attempts to purchase.
- void setInEscrow(bool in_escrow) { mInEscrow = in_escrow; }
-
- void setAuthorizedBuyerID(const LLUUID& id) { mAuthBuyerID = id; }
- //void overrideBuyerID(const LLUUID& id) { mBuyerID = id; }
- void setCategory(ECategory category) { mCategory = category; }
- void setSnapshotID(const LLUUID& id) { mSnapshotID = id; }
- void setUserLocation(const LLVector3& pos) { mUserLocation = pos; }
- void setUserLookAt(const LLVector3& rot) { mUserLookAt = rot; }
- void setLandingType(const ELandingType type) { mLandingType = type; }
- void setSeeAVs(bool see_avs) { mSeeAVs = see_avs; }
- void setHaveNewParcelLimitData(bool have_new_parcel_data) { mHaveNewParcelLimitData = have_new_parcel_data; } // Remove this once hidden AV feature is fully available grid-wide
-
- void setAuctionID(U32 auction_id) { mAuctionID = auction_id;}
-
- void setAllParcelFlags(U32 flags);
- void setParcelFlag(U32 flag, bool b);
-
- virtual void setArea(S32 area, S32 sim_object_limit);
- void setDiscountRate(F32 rate);
-
- void setAllowModify(bool b) { setParcelFlag(PF_CREATE_OBJECTS, b); }
- void setAllowGroupModify(bool b) { setParcelFlag(PF_CREATE_GROUP_OBJECTS, b); }
- void setAllowAllObjectEntry(bool b) { setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, b); }
- void setAllowGroupObjectEntry(bool b) { setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, b); }
- void setAllowTerraform(bool b){setParcelFlag(PF_ALLOW_TERRAFORM, b); }
- void setAllowDamage(bool b) { setParcelFlag(PF_ALLOW_DAMAGE, b); }
- void setAllowFly(bool b) { setParcelFlag(PF_ALLOW_FLY, b); }
- void setAllowGroupScripts(bool b) { setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, b); }
- void setAllowOtherScripts(bool b) { setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, b); }
- void setAllowDeedToGroup(bool b) { setParcelFlag(PF_ALLOW_DEED_TO_GROUP, b); }
- void setContributeWithDeed(bool b) { setParcelFlag(PF_CONTRIBUTE_WITH_DEED, b); }
- void setForSale(bool b) { setParcelFlag(PF_FOR_SALE, b); }
- void setSoundOnly(bool b) { setParcelFlag(PF_SOUND_LOCAL, b); }
- void setDenyAnonymous(bool b) { setParcelFlag(PF_DENY_ANONYMOUS, b); }
- void setDenyAgeUnverified(bool b) { setParcelFlag(PF_DENY_AGEUNVERIFIED, b); }
- void setRestrictPushObject(bool b) { setParcelFlag(PF_RESTRICT_PUSHOBJECT, b); }
- void setAllowGroupAVSounds(bool b) { mAllowGroupAVSounds = b; }
- void setAllowAnyAVSounds(bool b) { mAllowAnyAVSounds = b; }
- void setObscureMOAP(bool b) { mObscureMOAP = b; }
-
- void setDrawDistance(F32 dist) { mDrawDistance = dist; }
- void setSalePrice(S32 price) { mSalePrice = price; }
- void setGroupID(const LLUUID& id) { mGroupID = id; }
- //void setGroupName(const std::string& s) { mGroupName.assign(s); }
- void setPassPrice(S32 price) { mPassPrice = price; }
- void setPassHours(F32 hours) { mPassHours = hours; }
-
-// bool importStream(std::istream& input_stream);
- bool importAccessEntry(std::istream& input_stream, LLAccessEntry* entry);
- // bool exportStream(std::ostream& output_stream);
-
- void packMessage(LLMessageSystem* msg);
- void packMessage(LLSD& msg);
- void unpackMessage(LLMessageSystem* msg);
-
- void packAccessEntries(LLMessageSystem* msg,
- const std::map<LLUUID,LLAccessEntry>& list);
- void unpackAccessEntries(LLMessageSystem* msg,
- std::map<LLUUID,LLAccessEntry>* list);
-
- void unpackExperienceEntries(LLMessageSystem* msg, U32 type);
-
-
- void setAABBMin(const LLVector3& min) { mAABBMin = min; }
- void setAABBMax(const LLVector3& max) { mAABBMax = max; }
-
- // Extend AABB to include rectangle from min to max.
- void extendAABB(const LLVector3& box_min, const LLVector3& box_max);
-
- void dump();
-
- // Scans the pass list and removes any items with an expiration
- // time earlier than "now".
- void expirePasses(S32 now);
-
- // Add to list, suppressing duplicates. Returns true if added.
- bool addToAccessList(const LLUUID& agent_id, S32 time);
- bool addToBanList(const LLUUID& agent_id, S32 time);
- bool removeFromAccessList(const LLUUID& agent_id);
- bool removeFromBanList(const LLUUID& agent_id);
-
- // ACCESSORS
- const LLUUID& getID() const { return mID; }
- const std::string& getName() const { return mName; }
- const std::string& getDesc() const { return mDesc; }
- const std::string& getMusicURL() const { return mMusicURL; }
- const std::string& getMediaURL() const { return mMediaURL; }
- const std::string& getMediaDesc() const { return mMediaDesc; }
- const std::string& getMediaType() const { return mMediaType; }
- const LLUUID& getMediaID() const { return mMediaID; }
- S32 getMediaWidth() const { return mMediaWidth; }
- S32 getMediaHeight() const { return mMediaHeight; }
- U8 getMediaAutoScale() const { return mMediaAutoScale; }
- U8 getMediaLoop() const { return mMediaLoop; }
- const std::string& getMediaCurrentURL() const { return mMediaCurrentURL; }
- U8 getMediaAllowNavigate() const { return mMediaAllowNavigate; }
- F32 getMediaURLTimeout() const { return mMediaURLTimeout; }
- U8 getMediaPreventCameraZoom() const { return mMediaPreventCameraZoom; }
-
- S32 getLocalID() const { return mLocalID; }
- const LLUUID& getOwnerID() const { return mOwnerID; }
- const LLUUID& getGroupID() const { return mGroupID; }
- S32 getPassPrice() const { return mPassPrice; }
- F32 getPassHours() const { return mPassHours; }
- bool getIsGroupOwned() const { return mGroupOwned; }
-
- U32 getAuctionID() const { return mAuctionID; }
- bool isInEscrow() const { return mInEscrow; }
-
- bool isPublic() const;
-
- // Region-local user-specified position
- const LLVector3& getUserLocation() const { return mUserLocation; }
- const LLVector3& getUserLookAt() const { return mUserLookAt; }
- ELandingType getLandingType() const { return mLandingType; }
- bool getSeeAVs() const { return mSeeAVs; }
- bool getHaveNewParcelLimitData() const { return mHaveNewParcelLimitData; }
-
- // User-specified snapshot
- const LLUUID& getSnapshotID() const { return mSnapshotID; }
-
- // the authorized buyer id is the person who is the only
- // agent/group that has authority to purchase. (ie, ui specified a
- // particular agent could buy the plot).
- const LLUUID& getAuthorizedBuyerID() const { return mAuthBuyerID; }
-
- // helper function
- bool isBuyerAuthorized(const LLUUID& buyer_id) const;
-
- // The buyer of a plot is set when someone indicates they want to
- // buy the plot, and the system is simply waiting for tier-up
- // approval
- //const LLUUID& getBuyerID() const { return mBuyerID; }
-
- // functions to deal with ownership status.
- EOwnershipStatus getOwnershipStatus() const { return mStatus; }
- static const std::string& getOwnershipStatusString(EOwnershipStatus status);
- void setOwnershipStatus(EOwnershipStatus status) { mStatus = status; }
-
- // dealing with parcel category information
- ECategory getCategory() const {return mCategory; }
- static const std::string& getCategoryString(ECategory category);
- static const std::string& getCategoryUIString(ECategory category);
- static ECategory getCategoryFromString(const std::string& string);
- static ECategory getCategoryFromUIString(const std::string& string);
-
- // functions for parcel action (used for logging)
- static const std::string& getActionString(EAction action);
-
- // dealing with sales and parcel conversion.
- //
- // the isSaleTimerExpired will trivially return false if there is
- // no sale going on. Pass in the current time in usec which will
- // be used for comparison.
- bool isSaleTimerExpired(const U64& time);
-
- F32 getSaleTimerExpires() { return mSaleTimerExpires.getRemainingTimeF32(); }
-
- // should the parcel join on complete?
- //U32 getJoinNeighbors() const { return mJoinNeighbors; }
-
- // need to record a few things with the parcel when a sale
- // starts.
- void startSale(const LLUUID& buyer_id, bool is_buyer_group);
-
- // do the expiration logic, which needs to return values usable in
- // a L$ transaction.
- void expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id);
- void completeSale(U32& type, U8& flags, LLUUID& to_id);
- void clearSale();
-
-
- bool isMediaResetTimerExpired(const U64& time);
-
-
- // more accessors
- U32 getParcelFlags() const { return mParcelFlags; }
-
- bool getParcelFlag(U32 flag) const { return (mParcelFlags & flag) != 0; }
-
- // objects can be added or modified by anyone (only parcel owner if disabled)
- bool getAllowModify() const { return getParcelFlag(PF_CREATE_OBJECTS); }
-
- // objects can be added or modified by group members
- bool getAllowGroupModify() const { return getParcelFlag(PF_CREATE_GROUP_OBJECTS); }
-
- // the parcel can be deeded to the group
- bool getAllowDeedToGroup() const { return getParcelFlag(PF_ALLOW_DEED_TO_GROUP); }
-
- // Does the owner want to make a contribution along with the deed.
- bool getContributeWithDeed() const { return getParcelFlag(PF_CONTRIBUTE_WITH_DEED); }
-
- // heightfield can be modified
- bool getAllowTerraform() const { return getParcelFlag(PF_ALLOW_TERRAFORM); }
-
- // avatars can be hurt here
- bool getAllowDamage() const { return getParcelFlag(PF_ALLOW_DAMAGE); }
-
- bool getAllowFly() const { return getParcelFlag(PF_ALLOW_FLY); }
- bool getAllowGroupScripts() const { return getParcelFlag(PF_ALLOW_GROUP_SCRIPTS); }
- bool getAllowOtherScripts() const { return getParcelFlag(PF_ALLOW_OTHER_SCRIPTS); }
- bool getAllowAllObjectEntry() const { return getParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY); }
- bool getAllowGroupObjectEntry() const { return getParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY); }
- bool getForSale() const { return getParcelFlag(PF_FOR_SALE); }
- bool getSoundLocal() const { return getParcelFlag(PF_SOUND_LOCAL); }
- bool getParcelFlagAllowVoice() const { return getParcelFlag(PF_ALLOW_VOICE_CHAT); }
- bool getParcelFlagUseEstateVoiceChannel() const { return getParcelFlag(PF_USE_ESTATE_VOICE_CHAN); }
- bool getAllowPublish() const { return getParcelFlag(PF_ALLOW_PUBLISH); }
- bool getMaturePublish() const { return getParcelFlag(PF_MATURE_PUBLISH); }
- bool getRestrictPushObject() const { return getParcelFlag(PF_RESTRICT_PUSHOBJECT); }
-
- bool getRegionPushOverride() const { return mRegionPushOverride; }
- bool getRegionDenyAnonymousOverride() const { return mRegionDenyAnonymousOverride; }
- bool getRegionDenyAgeUnverifiedOverride() const { return mRegionDenyAgeUnverifiedOverride; }
- bool getRegionAllowAccessOverride() const { return mRegionAllowAccessoverride; }
- bool getRegionAllowEnvironmentOverride() const { return mRegionAllowEnvironmentOverride; }
- S32 getParcelEnvironmentVersion() const { return mCurrentEnvironmentVersion; }
- bool getAllowGroupAVSounds() const { return mAllowGroupAVSounds; }
- bool getAllowAnyAVSounds() const { return mAllowAnyAVSounds; }
- bool getObscureMOAP() const { return mObscureMOAP; }
-
- F32 getDrawDistance() const { return mDrawDistance; }
- S32 getSalePrice() const { return mSalePrice; }
- time_t getClaimDate() const { return mClaimDate; }
- S32 getClaimPricePerMeter() const { return mClaimPricePerMeter; }
- S32 getRentPricePerMeter() const { return mRentPricePerMeter; }
-
- // Area is NOT automatically calculated. You must calculate it
- // and store it with setArea.
- S32 getArea() const { return mArea; }
-
- // deprecated 12/11/2003
- //F32 getDiscountRate() const { return mDiscountRate; }
-
- S32 getClaimPrice() const { return mClaimPricePerMeter * mArea; }
-
- // Can this agent create objects here?
- bool allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const;
-
- // Can this agent change the shape of the land?
- bool allowTerraformBy(const LLUUID &agent_id) const;
-
- bool operator==(const LLParcel &rhs) const;
-
- // Calculate rent - area * rent * discount rate
- S32 getTotalRent() const;
- F32 getAdjustedRentPerMeter() const;
-
- const LLVector3& getAABBMin() const { return mAABBMin; }
- const LLVector3& getAABBMax() const { return mAABBMax; }
- LLVector3 getCenterpoint() const;
-
- // simwide
- S32 getSimWideMaxPrimCapacity() const { return mSimWideMaxPrimCapacity; }
- S32 getSimWidePrimCount() const { return mSimWidePrimCount; }
-
- // this parcel only (not simwide)
- S32 getMaxPrimCapacity() const { return mMaxPrimCapacity; } // Does not include prim bonus
- S32 getPrimCount() const { return mOwnerPrimCount + mGroupPrimCount + mOtherPrimCount + mSelectedPrimCount; }
- S32 getOwnerPrimCount() const { return mOwnerPrimCount; }
- S32 getGroupPrimCount() const { return mGroupPrimCount; }
- S32 getOtherPrimCount() const { return mOtherPrimCount; }
- S32 getSelectedPrimCount() const{ return mSelectedPrimCount; }
- S32 getTempPrimCount() const { return mTempPrimCount; }
- F32 getParcelPrimBonus() const { return mParcelPrimBonus; }
-
- S32 getCleanOtherTime() const { return mCleanOtherTime; }
-
- void setMaxPrimCapacity(S32 max) { mMaxPrimCapacity = max; } // Does not include prim bonus
- // simwide
- void setSimWideMaxPrimCapacity(S32 current) { mSimWideMaxPrimCapacity = current; }
- void setSimWidePrimCount(S32 current) { mSimWidePrimCount = current; }
-
- // this parcel only (not simwide)
- void setOwnerPrimCount(S32 current) { mOwnerPrimCount = current; }
- void setGroupPrimCount(S32 current) { mGroupPrimCount = current; }
- void setOtherPrimCount(S32 current) { mOtherPrimCount = current; }
- void setSelectedPrimCount(S32 current) { mSelectedPrimCount = current; }
- void setTempPrimCount(S32 current) { mTempPrimCount = current; }
- void setParcelPrimBonus(F32 bonus) { mParcelPrimBonus = bonus; }
-
- void setCleanOtherTime(S32 time) { mCleanOtherTime = time; }
- void setRegionPushOverride(bool override) {mRegionPushOverride = override; }
- void setRegionDenyAnonymousOverride(bool override) { mRegionDenyAnonymousOverride = override; }
- void setRegionDenyAgeUnverifiedOverride(bool override) { mRegionDenyAgeUnverifiedOverride = override; }
- void setRegionAllowAccessOverride(bool override) { mRegionAllowAccessoverride = override; }
- void setRegionAllowEnvironmentOverride(bool override) { mRegionAllowEnvironmentOverride = override; }
-
- void setParcelEnvironmentVersion(S32 version) { mCurrentEnvironmentVersion = version; }
-
- // Accessors for parcel sellWithObjects
- void setPreviousOwnerID(LLUUID prev_owner) { mPreviousOwnerID = prev_owner; }
- void setPreviouslyGroupOwned(bool b) { mPreviouslyGroupOwned = b; }
- void setSellWithObjects(bool b) { setParcelFlag(PF_SELL_PARCEL_OBJECTS, b); }
-
- LLUUID getPreviousOwnerID() const { return mPreviousOwnerID; }
- bool getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; }
- bool getSellWithObjects() const { return getParcelFlag(PF_SELL_PARCEL_OBJECTS); }
-
-protected:
- LLUUID mID;
- LLUUID mOwnerID;
- LLUUID mGroupID;
- bool mGroupOwned; // true if mOwnerID is a group_id
- LLUUID mPreviousOwnerID;
- bool mPreviouslyGroupOwned;
-
- EOwnershipStatus mStatus;
- ECategory mCategory;
- LLUUID mAuthBuyerID;
- LLUUID mSnapshotID;
- LLVector3 mUserLocation;
- LLVector3 mUserLookAt;
- ELandingType mLandingType;
- bool mSeeAVs; // Avatars on this parcel are visible from outside it
- bool mHaveNewParcelLimitData; // Remove once hidden AV feature is grid-wide
- LLTimer mSaleTimerExpires;
- LLTimer mMediaResetTimer;
-
- S32 mGraceExtension;
-
- // This value is non-zero if there is an auction associated with
- // the parcel.
- U32 mAuctionID;
-
- // value used to temporarily lock attempts to purchase the parcel.
- bool mInEscrow;
-
- time_t mClaimDate; // UTC Unix-format time
- S32 mClaimPricePerMeter; // meter squared
- S32 mRentPricePerMeter; // meter squared
- S32 mArea; // meter squared
- F32 mDiscountRate; // 0.0-1.0
- F32 mDrawDistance;
- U32 mParcelFlags;
- S32 mSalePrice; // linden dollars
- std::string mName;
- std::string mDesc;
- std::string mMusicURL;
- std::string mMediaURL;
- std::string mMediaDesc;
- std::string mMediaType;
- S32 mMediaWidth;
- S32 mMediaHeight;
- U8 mMediaAutoScale;
- U8 mMediaLoop;
- std::string mMediaCurrentURL;
- LLUUID mMediaID;
- U8 mMediaAllowNavigate;
- U8 mMediaPreventCameraZoom;
- F32 mMediaURLTimeout;
- S32 mPassPrice;
- F32 mPassHours;
- LLVector3 mAABBMin;
- LLVector3 mAABBMax;
- S32 mMaxPrimCapacity; // Prims allowed on parcel, does not include prim bonus
- S32 mSimWidePrimCount;
- S32 mSimWideMaxPrimCapacity;
- //S32 mSimWidePrimCorrection;
- S32 mOwnerPrimCount;
- S32 mGroupPrimCount;
- S32 mOtherPrimCount;
- S32 mSelectedPrimCount;
- S32 mTempPrimCount;
- F32 mParcelPrimBonus;
- S32 mCleanOtherTime;
- bool mRegionPushOverride;
- bool mRegionDenyAnonymousOverride;
- bool mRegionDenyAgeUnverifiedOverride;
- bool mRegionAllowAccessoverride;
- bool mRegionAllowEnvironmentOverride;
- bool mAllowGroupAVSounds;
- bool mAllowAnyAVSounds;
- bool mObscureMOAP;
- S32 mCurrentEnvironmentVersion;
-
- bool mIsDefaultDayCycle;
-
-public:
- // HACK, make private
- S32 mLocalID;
- LLUUID mBanListTransactionID;
- LLUUID mAccessListTransactionID;
- std::map<LLUUID,LLAccessEntry> mAccessList;
- std::map<LLUUID,LLAccessEntry> mBanList;
- std::map<LLUUID,LLAccessEntry> mTempBanList;
- std::map<LLUUID,LLAccessEntry> mTempAccessList;
-
- typedef std::map<LLUUID, U32> xp_type_map_t;
-
- void setExperienceKeyType(const LLUUID& experience_key, U32 type);
- U32 countExperienceKeyType(U32 type);
- LLAccessEntry::map getExperienceKeysByType(U32 type)const;
- void clearExperienceKeysByType(U32 type);
-
-private:
- xp_type_map_t mExperienceKeys;
-};
-
-
-const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status);
-LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s);
-LLParcel::ECategory category_string_to_category(const std::string& s);
-const std::string& category_to_string(LLParcel::ECategory category);
-
-
-#endif
+/** + * @file llparcel.h + * + * $LicenseInfo:firstyear=2002&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$ + */ + +#ifndef LL_LLPARCEL_H +#define LL_LLPARCEL_H + +#include <time.h> +#include <iostream> + +#include "lluuid.h" +#include "llparcelflags.h" +#include "llpermissions.h" +#include "lltimer.h" +#include "v3math.h" +#include "llsettingsdaycycle.h" + +// Grid out of which parcels taken is stepped every 4 meters. +const F32 PARCEL_GRID_STEP_METERS = 4.f; + +// Area of one "square" of parcel +const S32 PARCEL_UNIT_AREA = 16; + +// Height _above_ground_ that parcel boundary ends +const F32 PARCEL_HEIGHT = 50.f; + +//Height above ground which parcel boundries exist for explicitly banned avatars +const F32 BAN_HEIGHT = 5000.f; + +// Maximum number of entries in an access list +const S32 PARCEL_MAX_ACCESS_LIST = 300; +//Maximum number of entires in an update packet +//for access/ban lists. +const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f; + +// Maximum number of experiences +const S32 PARCEL_MAX_EXPERIENCE_LIST = 24; + +// Weekly charge for listing a parcel in the directory +const S32 PARCEL_DIRECTORY_FEE = 30; + +const S32 PARCEL_PASS_PRICE_DEFAULT = 10; +const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f; + +// Number of "chunks" in which parcel overlay data is sent +// Chunk 0 = southern rows, entire width +const S32 PARCEL_OVERLAY_CHUNKS = 4; + +// Bottom three bits are a color index for the land overlay +const U8 PARCEL_COLOR_MASK = 0x07; +const U8 PARCEL_PUBLIC = 0x00; +const U8 PARCEL_OWNED = 0x01; +const U8 PARCEL_GROUP = 0x02; +const U8 PARCEL_SELF = 0x03; +const U8 PARCEL_FOR_SALE = 0x04; +const U8 PARCEL_AUCTION = 0x05; +// unused 0x06 +// unused 0x07 +// flag, unused 0x08 +const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility +const U8 PARCEL_SOUND_LOCAL = 0x20; +const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge +const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge + +// Transmission results for parcel properties +const S32 PARCEL_RESULT_NO_DATA = -1; +const S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel +const S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels + +const S32 SELECTED_PARCEL_SEQ_ID = -10000; +const S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000; +const S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000; +const S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000; +const S32 HOVERED_PARCEL_SEQ_ID = -50000; + +const U32 RT_NONE = 0x1 << 0; +const U32 RT_OWNER = 0x1 << 1; +const U32 RT_GROUP = 0x1 << 2; +const U32 RT_OTHER = 0x1 << 3; +const U32 RT_LIST = 0x1 << 4; +const U32 RT_SELL = 0x1 << 5; + +const S32 INVALID_PARCEL_ID = -1; + +const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2; +// if Region settings are used, parcel env. version is -1 +const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1; + +// Timeouts for parcels +// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000 +const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000); +// ***** TESTING is 10 minutes +//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000); + +// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000 +const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000); +// ***** TESTING is 10 minutes +//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000); + +// default sale timeout is 2 days -> 172800000000 +const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000); +// ***** TESTING is 10 minutes +//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000); + +// more grace period extensions. +const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000); + +// if more than 100,000s before sale revert, and no extra extension +// has been given, go ahead and extend it more. That's about 1.2 days. +const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000; + + + +class LLMessageSystem; +class LLSD; + +class LLAccessEntry +{ +public: + + typedef std::map<LLUUID,LLAccessEntry> map; + + LLAccessEntry() + : mTime(0), + mFlags(0) + {} + + LLUUID mID; // Agent ID + S32 mTime; // Time (unix seconds) when entry expires + U32 mFlags; // Not used - currently should always be zero +}; + + +class LLParcel +{ +public: + enum EOwnershipStatus + { + OS_LEASED = 0, + OS_LEASE_PENDING = 1, + OS_ABANDONED = 2, + OS_COUNT = 3, + OS_NONE = -1 + }; + enum ECategory + { + C_NONE = 0, + C_LINDEN, + C_ADULT, + C_ARTS, // "arts & culture" + C_BUSINESS, // was "store" + C_EDUCATIONAL, + C_GAMING, // was "game" + C_HANGOUT, // was "gathering place" + C_NEWCOMER, + C_PARK, // "parks & nature" + C_RESIDENTIAL, // was "homestead" + C_SHOPPING, + C_STAGE, + C_OTHER, + C_RENTAL, + C_COUNT, + C_ANY = -1 // only useful in queries + }; + enum EAction + { + A_CREATE = 0, + A_RELEASE = 1, + A_ABSORB = 2, + A_ABSORBED = 3, + A_DIVIDE = 4, + A_DIVISION = 5, + A_ACQUIRE = 6, + A_RELINQUISH = 7, + A_CONFIRM = 8, + A_COUNT = 9, + A_UNKNOWN = -1 + }; + + enum ELandingType + { + L_NONE = 0, + L_LANDING_POINT = 1, + L_DIRECT = 2 + }; + + // CREATORS + LLParcel(); + LLParcel( + const LLUUID &owner_id, + bool modify, + bool terraform, + bool damage, + time_t claim_date, + S32 claim_price, + S32 rent_price, + S32 area, + S32 sim_object_limit, + F32 parcel_object_bonus, + bool is_group_owned = false); + virtual ~LLParcel(); + + void init( + const LLUUID &owner_id, + bool modify, + bool terraform, + bool damage, + time_t claim_date, + S32 claim_price, + S32 rent_price, + S32 area, + S32 sim_object_limit, + F32 parcel_object_bonus, + bool is_group_owned = false); + + // TODO: make an actual copy constructor for this + void overrideParcelFlags(U32 flags); + // if you specify an agent id here, the group id will be zeroed + void overrideOwner( + const LLUUID& owner_id, + bool is_group_owned = false); + void overrideSaleTimerExpires(F32 secs_left) { mSaleTimerExpires.setTimerExpirySec(secs_left); } + + // MANIPULATORS + void generateNewID() { mID.generate(); } + void setName(const std::string& name); + void setDesc(const std::string& desc); + void setMusicURL(const std::string& url); + void setMediaURL(const std::string& url); + void setMediaType(const std::string& type); + void setMediaDesc(const std::string& desc); + void setMediaID(const LLUUID& id) { mMediaID = id; } + void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; } + void setMediaLoop (U8 loop) { mMediaLoop = loop; } + void setMediaWidth(S32 width); + void setMediaHeight(S32 height); + void setMediaCurrentURL(const std::string& url); + void setMediaAllowNavigate(U8 enable) { mMediaAllowNavigate = enable; } + void setMediaURLTimeout(F32 timeout) { mMediaURLTimeout = timeout; } + void setMediaPreventCameraZoom(U8 enable) { mMediaPreventCameraZoom = enable; } + + void setMediaURLResetTimer(F32 time); + virtual void setLocalID(S32 local_id); + + // blow away all the extra stuff lurking in parcels, including urls, access lists, etc + void clearParcel(); + + // This value is not persisted out to the parcel file, it is only + // a per-process blocker for attempts to purchase. + void setInEscrow(bool in_escrow) { mInEscrow = in_escrow; } + + void setAuthorizedBuyerID(const LLUUID& id) { mAuthBuyerID = id; } + //void overrideBuyerID(const LLUUID& id) { mBuyerID = id; } + void setCategory(ECategory category) { mCategory = category; } + void setSnapshotID(const LLUUID& id) { mSnapshotID = id; } + void setUserLocation(const LLVector3& pos) { mUserLocation = pos; } + void setUserLookAt(const LLVector3& rot) { mUserLookAt = rot; } + void setLandingType(const ELandingType type) { mLandingType = type; } + void setSeeAVs(bool see_avs) { mSeeAVs = see_avs; } + void setHaveNewParcelLimitData(bool have_new_parcel_data) { mHaveNewParcelLimitData = have_new_parcel_data; } // Remove this once hidden AV feature is fully available grid-wide + + void setAuctionID(U32 auction_id) { mAuctionID = auction_id;} + + void setAllParcelFlags(U32 flags); + void setParcelFlag(U32 flag, bool b); + + virtual void setArea(S32 area, S32 sim_object_limit); + void setDiscountRate(F32 rate); + + void setAllowModify(bool b) { setParcelFlag(PF_CREATE_OBJECTS, b); } + void setAllowGroupModify(bool b) { setParcelFlag(PF_CREATE_GROUP_OBJECTS, b); } + void setAllowAllObjectEntry(bool b) { setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, b); } + void setAllowGroupObjectEntry(bool b) { setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, b); } + void setAllowTerraform(bool b){setParcelFlag(PF_ALLOW_TERRAFORM, b); } + void setAllowDamage(bool b) { setParcelFlag(PF_ALLOW_DAMAGE, b); } + void setAllowFly(bool b) { setParcelFlag(PF_ALLOW_FLY, b); } + void setAllowGroupScripts(bool b) { setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, b); } + void setAllowOtherScripts(bool b) { setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, b); } + void setAllowDeedToGroup(bool b) { setParcelFlag(PF_ALLOW_DEED_TO_GROUP, b); } + void setContributeWithDeed(bool b) { setParcelFlag(PF_CONTRIBUTE_WITH_DEED, b); } + void setForSale(bool b) { setParcelFlag(PF_FOR_SALE, b); } + void setSoundOnly(bool b) { setParcelFlag(PF_SOUND_LOCAL, b); } + void setDenyAnonymous(bool b) { setParcelFlag(PF_DENY_ANONYMOUS, b); } + void setDenyAgeUnverified(bool b) { setParcelFlag(PF_DENY_AGEUNVERIFIED, b); } + void setRestrictPushObject(bool b) { setParcelFlag(PF_RESTRICT_PUSHOBJECT, b); } + void setAllowGroupAVSounds(bool b) { mAllowGroupAVSounds = b; } + void setAllowAnyAVSounds(bool b) { mAllowAnyAVSounds = b; } + void setObscureMOAP(bool b) { mObscureMOAP = b; } + + void setDrawDistance(F32 dist) { mDrawDistance = dist; } + void setSalePrice(S32 price) { mSalePrice = price; } + void setGroupID(const LLUUID& id) { mGroupID = id; } + //void setGroupName(const std::string& s) { mGroupName.assign(s); } + void setPassPrice(S32 price) { mPassPrice = price; } + void setPassHours(F32 hours) { mPassHours = hours; } + +// bool importStream(std::istream& input_stream); + bool importAccessEntry(std::istream& input_stream, LLAccessEntry* entry); + // bool exportStream(std::ostream& output_stream); + + void packMessage(LLMessageSystem* msg); + void packMessage(LLSD& msg); + void unpackMessage(LLMessageSystem* msg); + + void packAccessEntries(LLMessageSystem* msg, + const std::map<LLUUID,LLAccessEntry>& list); + void unpackAccessEntries(LLMessageSystem* msg, + std::map<LLUUID,LLAccessEntry>* list); + + void unpackExperienceEntries(LLMessageSystem* msg, U32 type); + + + void setAABBMin(const LLVector3& min) { mAABBMin = min; } + void setAABBMax(const LLVector3& max) { mAABBMax = max; } + + // Extend AABB to include rectangle from min to max. + void extendAABB(const LLVector3& box_min, const LLVector3& box_max); + + void dump(); + + // Scans the pass list and removes any items with an expiration + // time earlier than "now". + void expirePasses(S32 now); + + // Add to list, suppressing duplicates. Returns true if added. + bool addToAccessList(const LLUUID& agent_id, S32 time); + bool addToBanList(const LLUUID& agent_id, S32 time); + bool removeFromAccessList(const LLUUID& agent_id); + bool removeFromBanList(const LLUUID& agent_id); + + // ACCESSORS + const LLUUID& getID() const { return mID; } + const std::string& getName() const { return mName; } + const std::string& getDesc() const { return mDesc; } + const std::string& getMusicURL() const { return mMusicURL; } + const std::string& getMediaURL() const { return mMediaURL; } + const std::string& getMediaDesc() const { return mMediaDesc; } + const std::string& getMediaType() const { return mMediaType; } + const LLUUID& getMediaID() const { return mMediaID; } + S32 getMediaWidth() const { return mMediaWidth; } + S32 getMediaHeight() const { return mMediaHeight; } + U8 getMediaAutoScale() const { return mMediaAutoScale; } + U8 getMediaLoop() const { return mMediaLoop; } + const std::string& getMediaCurrentURL() const { return mMediaCurrentURL; } + U8 getMediaAllowNavigate() const { return mMediaAllowNavigate; } + F32 getMediaURLTimeout() const { return mMediaURLTimeout; } + U8 getMediaPreventCameraZoom() const { return mMediaPreventCameraZoom; } + + S32 getLocalID() const { return mLocalID; } + const LLUUID& getOwnerID() const { return mOwnerID; } + const LLUUID& getGroupID() const { return mGroupID; } + S32 getPassPrice() const { return mPassPrice; } + F32 getPassHours() const { return mPassHours; } + bool getIsGroupOwned() const { return mGroupOwned; } + + U32 getAuctionID() const { return mAuctionID; } + bool isInEscrow() const { return mInEscrow; } + + bool isPublic() const; + + // Region-local user-specified position + const LLVector3& getUserLocation() const { return mUserLocation; } + const LLVector3& getUserLookAt() const { return mUserLookAt; } + ELandingType getLandingType() const { return mLandingType; } + bool getSeeAVs() const { return mSeeAVs; } + bool getHaveNewParcelLimitData() const { return mHaveNewParcelLimitData; } + + // User-specified snapshot + const LLUUID& getSnapshotID() const { return mSnapshotID; } + + // the authorized buyer id is the person who is the only + // agent/group that has authority to purchase. (ie, ui specified a + // particular agent could buy the plot). + const LLUUID& getAuthorizedBuyerID() const { return mAuthBuyerID; } + + // helper function + bool isBuyerAuthorized(const LLUUID& buyer_id) const; + + // The buyer of a plot is set when someone indicates they want to + // buy the plot, and the system is simply waiting for tier-up + // approval + //const LLUUID& getBuyerID() const { return mBuyerID; } + + // functions to deal with ownership status. + EOwnershipStatus getOwnershipStatus() const { return mStatus; } + static const std::string& getOwnershipStatusString(EOwnershipStatus status); + void setOwnershipStatus(EOwnershipStatus status) { mStatus = status; } + + // dealing with parcel category information + ECategory getCategory() const {return mCategory; } + static const std::string& getCategoryString(ECategory category); + static const std::string& getCategoryUIString(ECategory category); + static ECategory getCategoryFromString(const std::string& string); + static ECategory getCategoryFromUIString(const std::string& string); + + // functions for parcel action (used for logging) + static const std::string& getActionString(EAction action); + + // dealing with sales and parcel conversion. + // + // the isSaleTimerExpired will trivially return false if there is + // no sale going on. Pass in the current time in usec which will + // be used for comparison. + bool isSaleTimerExpired(const U64& time); + + F32 getSaleTimerExpires() { return mSaleTimerExpires.getRemainingTimeF32(); } + + // should the parcel join on complete? + //U32 getJoinNeighbors() const { return mJoinNeighbors; } + + // need to record a few things with the parcel when a sale + // starts. + void startSale(const LLUUID& buyer_id, bool is_buyer_group); + + // do the expiration logic, which needs to return values usable in + // a L$ transaction. + void expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id); + void completeSale(U32& type, U8& flags, LLUUID& to_id); + void clearSale(); + + + bool isMediaResetTimerExpired(const U64& time); + + + // more accessors + U32 getParcelFlags() const { return mParcelFlags; } + + bool getParcelFlag(U32 flag) const { return (mParcelFlags & flag) != 0; } + + // objects can be added or modified by anyone (only parcel owner if disabled) + bool getAllowModify() const { return getParcelFlag(PF_CREATE_OBJECTS); } + + // objects can be added or modified by group members + bool getAllowGroupModify() const { return getParcelFlag(PF_CREATE_GROUP_OBJECTS); } + + // the parcel can be deeded to the group + bool getAllowDeedToGroup() const { return getParcelFlag(PF_ALLOW_DEED_TO_GROUP); } + + // Does the owner want to make a contribution along with the deed. + bool getContributeWithDeed() const { return getParcelFlag(PF_CONTRIBUTE_WITH_DEED); } + + // heightfield can be modified + bool getAllowTerraform() const { return getParcelFlag(PF_ALLOW_TERRAFORM); } + + // avatars can be hurt here + bool getAllowDamage() const { return getParcelFlag(PF_ALLOW_DAMAGE); } + + bool getAllowFly() const { return getParcelFlag(PF_ALLOW_FLY); } + bool getAllowGroupScripts() const { return getParcelFlag(PF_ALLOW_GROUP_SCRIPTS); } + bool getAllowOtherScripts() const { return getParcelFlag(PF_ALLOW_OTHER_SCRIPTS); } + bool getAllowAllObjectEntry() const { return getParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY); } + bool getAllowGroupObjectEntry() const { return getParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY); } + bool getForSale() const { return getParcelFlag(PF_FOR_SALE); } + bool getSoundLocal() const { return getParcelFlag(PF_SOUND_LOCAL); } + bool getParcelFlagAllowVoice() const { return getParcelFlag(PF_ALLOW_VOICE_CHAT); } + bool getParcelFlagUseEstateVoiceChannel() const { return getParcelFlag(PF_USE_ESTATE_VOICE_CHAN); } + bool getAllowPublish() const { return getParcelFlag(PF_ALLOW_PUBLISH); } + bool getMaturePublish() const { return getParcelFlag(PF_MATURE_PUBLISH); } + bool getRestrictPushObject() const { return getParcelFlag(PF_RESTRICT_PUSHOBJECT); } + + bool getRegionPushOverride() const { return mRegionPushOverride; } + bool getRegionDenyAnonymousOverride() const { return mRegionDenyAnonymousOverride; } + bool getRegionDenyAgeUnverifiedOverride() const { return mRegionDenyAgeUnverifiedOverride; } + bool getRegionAllowAccessOverride() const { return mRegionAllowAccessoverride; } + bool getRegionAllowEnvironmentOverride() const { return mRegionAllowEnvironmentOverride; } + S32 getParcelEnvironmentVersion() const { return mCurrentEnvironmentVersion; } + bool getAllowGroupAVSounds() const { return mAllowGroupAVSounds; } + bool getAllowAnyAVSounds() const { return mAllowAnyAVSounds; } + bool getObscureMOAP() const { return mObscureMOAP; } + + F32 getDrawDistance() const { return mDrawDistance; } + S32 getSalePrice() const { return mSalePrice; } + time_t getClaimDate() const { return mClaimDate; } + S32 getClaimPricePerMeter() const { return mClaimPricePerMeter; } + S32 getRentPricePerMeter() const { return mRentPricePerMeter; } + + // Area is NOT automatically calculated. You must calculate it + // and store it with setArea. + S32 getArea() const { return mArea; } + + // deprecated 12/11/2003 + //F32 getDiscountRate() const { return mDiscountRate; } + + S32 getClaimPrice() const { return mClaimPricePerMeter * mArea; } + + // Can this agent create objects here? + bool allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const; + + // Can this agent change the shape of the land? + bool allowTerraformBy(const LLUUID &agent_id) const; + + bool operator==(const LLParcel &rhs) const; + + // Calculate rent - area * rent * discount rate + S32 getTotalRent() const; + F32 getAdjustedRentPerMeter() const; + + const LLVector3& getAABBMin() const { return mAABBMin; } + const LLVector3& getAABBMax() const { return mAABBMax; } + LLVector3 getCenterpoint() const; + + // simwide + S32 getSimWideMaxPrimCapacity() const { return mSimWideMaxPrimCapacity; } + S32 getSimWidePrimCount() const { return mSimWidePrimCount; } + + // this parcel only (not simwide) + S32 getMaxPrimCapacity() const { return mMaxPrimCapacity; } // Does not include prim bonus + S32 getPrimCount() const { return mOwnerPrimCount + mGroupPrimCount + mOtherPrimCount + mSelectedPrimCount; } + S32 getOwnerPrimCount() const { return mOwnerPrimCount; } + S32 getGroupPrimCount() const { return mGroupPrimCount; } + S32 getOtherPrimCount() const { return mOtherPrimCount; } + S32 getSelectedPrimCount() const{ return mSelectedPrimCount; } + S32 getTempPrimCount() const { return mTempPrimCount; } + F32 getParcelPrimBonus() const { return mParcelPrimBonus; } + + S32 getCleanOtherTime() const { return mCleanOtherTime; } + + void setMaxPrimCapacity(S32 max) { mMaxPrimCapacity = max; } // Does not include prim bonus + // simwide + void setSimWideMaxPrimCapacity(S32 current) { mSimWideMaxPrimCapacity = current; } + void setSimWidePrimCount(S32 current) { mSimWidePrimCount = current; } + + // this parcel only (not simwide) + void setOwnerPrimCount(S32 current) { mOwnerPrimCount = current; } + void setGroupPrimCount(S32 current) { mGroupPrimCount = current; } + void setOtherPrimCount(S32 current) { mOtherPrimCount = current; } + void setSelectedPrimCount(S32 current) { mSelectedPrimCount = current; } + void setTempPrimCount(S32 current) { mTempPrimCount = current; } + void setParcelPrimBonus(F32 bonus) { mParcelPrimBonus = bonus; } + + void setCleanOtherTime(S32 time) { mCleanOtherTime = time; } + void setRegionPushOverride(bool override) {mRegionPushOverride = override; } + void setRegionDenyAnonymousOverride(bool override) { mRegionDenyAnonymousOverride = override; } + void setRegionDenyAgeUnverifiedOverride(bool override) { mRegionDenyAgeUnverifiedOverride = override; } + void setRegionAllowAccessOverride(bool override) { mRegionAllowAccessoverride = override; } + void setRegionAllowEnvironmentOverride(bool override) { mRegionAllowEnvironmentOverride = override; } + + void setParcelEnvironmentVersion(S32 version) { mCurrentEnvironmentVersion = version; } + + // Accessors for parcel sellWithObjects + void setPreviousOwnerID(LLUUID prev_owner) { mPreviousOwnerID = prev_owner; } + void setPreviouslyGroupOwned(bool b) { mPreviouslyGroupOwned = b; } + void setSellWithObjects(bool b) { setParcelFlag(PF_SELL_PARCEL_OBJECTS, b); } + + LLUUID getPreviousOwnerID() const { return mPreviousOwnerID; } + bool getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; } + bool getSellWithObjects() const { return getParcelFlag(PF_SELL_PARCEL_OBJECTS); } + +protected: + LLUUID mID; + LLUUID mOwnerID; + LLUUID mGroupID; + bool mGroupOwned; // true if mOwnerID is a group_id + LLUUID mPreviousOwnerID; + bool mPreviouslyGroupOwned; + + EOwnershipStatus mStatus; + ECategory mCategory; + LLUUID mAuthBuyerID; + LLUUID mSnapshotID; + LLVector3 mUserLocation; + LLVector3 mUserLookAt; + ELandingType mLandingType; + bool mSeeAVs; // Avatars on this parcel are visible from outside it + bool mHaveNewParcelLimitData; // Remove once hidden AV feature is grid-wide + LLTimer mSaleTimerExpires; + LLTimer mMediaResetTimer; + + S32 mGraceExtension; + + // This value is non-zero if there is an auction associated with + // the parcel. + U32 mAuctionID; + + // value used to temporarily lock attempts to purchase the parcel. + bool mInEscrow; + + time_t mClaimDate; // UTC Unix-format time + S32 mClaimPricePerMeter; // meter squared + S32 mRentPricePerMeter; // meter squared + S32 mArea; // meter squared + F32 mDiscountRate; // 0.0-1.0 + F32 mDrawDistance; + U32 mParcelFlags; + S32 mSalePrice; // linden dollars + std::string mName; + std::string mDesc; + std::string mMusicURL; + std::string mMediaURL; + std::string mMediaDesc; + std::string mMediaType; + S32 mMediaWidth; + S32 mMediaHeight; + U8 mMediaAutoScale; + U8 mMediaLoop; + std::string mMediaCurrentURL; + LLUUID mMediaID; + U8 mMediaAllowNavigate; + U8 mMediaPreventCameraZoom; + F32 mMediaURLTimeout; + S32 mPassPrice; + F32 mPassHours; + LLVector3 mAABBMin; + LLVector3 mAABBMax; + S32 mMaxPrimCapacity; // Prims allowed on parcel, does not include prim bonus + S32 mSimWidePrimCount; + S32 mSimWideMaxPrimCapacity; + //S32 mSimWidePrimCorrection; + S32 mOwnerPrimCount; + S32 mGroupPrimCount; + S32 mOtherPrimCount; + S32 mSelectedPrimCount; + S32 mTempPrimCount; + F32 mParcelPrimBonus; + S32 mCleanOtherTime; + bool mRegionPushOverride; + bool mRegionDenyAnonymousOverride; + bool mRegionDenyAgeUnverifiedOverride; + bool mRegionAllowAccessoverride; + bool mRegionAllowEnvironmentOverride; + bool mAllowGroupAVSounds; + bool mAllowAnyAVSounds; + bool mObscureMOAP; + S32 mCurrentEnvironmentVersion; + + bool mIsDefaultDayCycle; + +public: + // HACK, make private + S32 mLocalID; + LLUUID mBanListTransactionID; + LLUUID mAccessListTransactionID; + std::map<LLUUID,LLAccessEntry> mAccessList; + std::map<LLUUID,LLAccessEntry> mBanList; + std::map<LLUUID,LLAccessEntry> mTempBanList; + std::map<LLUUID,LLAccessEntry> mTempAccessList; + + typedef std::map<LLUUID, U32> xp_type_map_t; + + void setExperienceKeyType(const LLUUID& experience_key, U32 type); + U32 countExperienceKeyType(U32 type); + LLAccessEntry::map getExperienceKeysByType(U32 type)const; + void clearExperienceKeysByType(U32 type); + +private: + xp_type_map_t mExperienceKeys; +}; + + +const std::string& ownership_status_to_string(LLParcel::EOwnershipStatus status); +LLParcel::EOwnershipStatus ownership_string_to_status(const std::string& s); +LLParcel::ECategory category_string_to_category(const std::string& s); +const std::string& category_to_string(LLParcel::ECategory category); + + +#endif diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 4bac324527..c8963881df 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -1,1052 +1,1052 @@ -/**
- * @file llpermissions.cpp
- * @author Phoenix
- * @brief Permissions for objects and inventory.
- *
- * $LicenseInfo:firstyear=2002&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 "llpermissions.h"
-
-// library includes
-#include "message.h"
-#include "llsd.h"
-
-///----------------------------------------------------------------------------
-/// Class LLPermissions
-///----------------------------------------------------------------------------
-
-const LLPermissions LLPermissions::DEFAULT;
-
-// No creator = created by system
-LLPermissions::LLPermissions()
-{
- init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
-}
-
-
-// Default to created by system
-void LLPermissions::init(const LLUUID& creator, const LLUUID& owner, const LLUUID& last_owner, const LLUUID& group)
-{
- mCreator = creator;
- mOwner = owner;
- mLastOwner = last_owner;
- mGroup = group;
-
- mMaskBase = PERM_ALL;
- mMaskOwner = PERM_ALL;
- mMaskEveryone = PERM_ALL;
- mMaskGroup = PERM_ALL;
- mMaskNextOwner = PERM_ALL;
- fixOwnership();
-}
-
-
-void LLPermissions::initMasks(PermissionMask base, PermissionMask owner,
- PermissionMask everyone, PermissionMask group,
- PermissionMask next)
-{
- mMaskBase = base;
- mMaskOwner = owner;
- mMaskEveryone = everyone;
- mMaskGroup = group;
- mMaskNextOwner = next;
- fixFairUse();
- fix();
-}
-
-// ! BACKWARDS COMPATIBILITY ! Override masks for inventory types that
-// no longer can have restricted permissions. This takes care of previous
-// version landmarks that could have had no copy/mod/transfer bits set.
-void LLPermissions::initMasks(LLInventoryType::EType type)
-{
- if (LLInventoryType::cannotRestrictPermissions(type))
- {
- initMasks(PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL);
- }
-}
-
-bool LLPermissions::getOwnership(LLUUID& owner_id, bool& is_group_owned) const
-{
- if(mOwner.notNull())
- {
- owner_id = mOwner;
- is_group_owned = false;
- return true;
- }
- else if(mIsGroupOwned)
- {
- owner_id = mGroup;
- is_group_owned = true;
- return true;
- }
- return false;
-}
-
-LLUUID LLPermissions::getSafeOwner() const
-{
- if(mOwner.notNull())
- {
- return mOwner;
- }
- else if(mIsGroupOwned)
- {
- return mGroup;
- }
- else
- {
- LL_WARNS() << "LLPermissions::getSafeOwner() called with no valid owner!" << LL_ENDL;
- LLUUID unused_uuid;
- unused_uuid.generate();
-
- return unused_uuid;
- }
-}
-
-U32 LLPermissions::getCRC32() const
-{
- U32 rv = mCreator.getCRC32();
- rv += mOwner.getCRC32();
- rv += mLastOwner.getCRC32();
- rv += mGroup.getCRC32();
- rv += mMaskBase + mMaskOwner + mMaskEveryone + mMaskGroup;
- return rv;
-}
-
-void LLPermissions::set(const LLPermissions& from)
-{
- mCreator = from.mCreator;
- mOwner = from.mOwner;
- mLastOwner = from.mLastOwner;
- mGroup = from.mGroup;
-
- mMaskBase = from.mMaskBase;
- mMaskOwner = from.mMaskOwner;
- mMaskEveryone = from.mMaskEveryone;
- mMaskGroup = from.mMaskGroup;
- mMaskNextOwner = from.mMaskNextOwner;
- mIsGroupOwned = from.mIsGroupOwned;
-}
-
-// Fix hierarchy of permissions.
-void LLPermissions::fix()
-{
- mMaskOwner &= mMaskBase;
- mMaskGroup &= mMaskOwner;
- // next owner uses base, since you may want to sell locked objects.
- mMaskNextOwner &= mMaskBase;
- mMaskEveryone &= mMaskOwner;
- mMaskEveryone &= ~PERM_MODIFY;
- if(!(mMaskBase & PERM_TRANSFER) && !mIsGroupOwned)
- {
- mMaskGroup &= ~PERM_COPY;
- mMaskEveryone &= ~PERM_COPY;
- // Do not set mask next owner to too restrictive because if we
- // rez an object, it may require an ownership transfer during
- // rez, which will note the overly restrictive perms, and then
- // fix them to allow fair use, which may be different than the
- // original intention.
- }
-}
-
-// Correct for fair use - you can never take away the right to move
-// stuff you own, and you can never take away the right to transfer
-// something you cannot otherwise copy.
-void LLPermissions::fixFairUse()
-{
- mMaskBase |= PERM_MOVE;
- if(!(mMaskBase & PERM_COPY))
- {
- mMaskBase |= PERM_TRANSFER;
- }
- // (mask next owner == PERM_NONE) iff mask base is no transfer
- if(mMaskNextOwner != PERM_NONE)
- {
- mMaskNextOwner |= PERM_MOVE;
- }
-}
-
-void LLPermissions::fixOwnership()
-{
- if(mOwner.isNull() && mGroup.notNull())
- {
- mIsGroupOwned = true;
- }
- else
- {
- mIsGroupOwned = false;
- }
-}
-
-// Allow accumulation of permissions. Results in the tightest
-// permissions possible. In the case of clashing UUIDs, it sets the ID
-// to LLUUID::null.
-void LLPermissions::accumulate(const LLPermissions& perm)
-{
- if(perm.mCreator != mCreator)
- {
- mCreator = LLUUID::null;
- }
- if(perm.mOwner != mOwner)
- {
- mOwner = LLUUID::null;
- }
- if(perm.mLastOwner != mLastOwner)
- {
- mLastOwner = LLUUID::null;
- }
- if(perm.mGroup != mGroup)
- {
- mGroup = LLUUID::null;
- }
-
- mMaskBase &= perm.mMaskBase;
- mMaskOwner &= perm.mMaskOwner;
- mMaskGroup &= perm.mMaskGroup;
- mMaskEveryone &= perm.mMaskEveryone;
- mMaskNextOwner &= perm.mMaskNextOwner;
- fix();
-}
-
-// saves last owner, sets current owner, and sets the group. note
-// that this function has to more cleverly apply the fair use
-// permissions.
-bool LLPermissions::setOwnerAndGroup(
- const LLUUID& agent,
- const LLUUID& owner,
- const LLUUID& group,
- bool is_atomic)
-{
- bool allowed = false;
-
- if( agent.isNull() || mOwner.isNull()
- || ((agent == mOwner) && ((owner == mOwner) || (mMaskOwner & PERM_TRANSFER)) ) )
- {
- // ...system can alway set owner
- // ...public objects can be claimed by anyone
- // ...otherwise, agent must own it and have transfer ability
- allowed = true;
- }
-
- if (allowed)
- {
- if(mLastOwner.isNull() || (!mOwner.isNull() && (owner != mLastOwner)))
- {
- mLastOwner = mOwner;
- }
- if((mOwner != owner)
- || (mOwner.isNull() && owner.isNull() && (mGroup != group)))
- {
- mMaskBase = mMaskNextOwner;
- mOwner = owner;
- // this is a selective use of fair use for atomic
- // permissions.
- if(is_atomic && !(mMaskBase & PERM_COPY))
- {
- mMaskBase |= PERM_TRANSFER;
- }
- }
- mGroup = group;
- fixOwnership();
- // if it's not atomic and we fix fair use, it blows away
- //objects as inventory items which have different permissions
- //than it's contents. :(
- // fixFairUse();
- mMaskBase |= PERM_MOVE;
- if(mMaskNextOwner != PERM_NONE) mMaskNextOwner |= PERM_MOVE;
- fix();
- }
-
- return allowed;
-}
-
-//Fix for DEV-33917, last owner isn't used much and has little impact on
-//permissions so it's reasonably safe to do this, however, for now,
-//limiting the functionality of this routine to objects which are
-//group owned.
-void LLPermissions::setLastOwner(const LLUUID& last_owner)
-{
- if (isGroupOwned())
- mLastOwner = last_owner;
-}
-
-
-// only call this if you know what you're doing
-// there are usually perm-bit consequences when the
-// ownerhsip changes
-void LLPermissions::yesReallySetOwner(const LLUUID& owner, bool group_owned)
-{
- mOwner = owner;
- mIsGroupOwned = group_owned;
-}
-
-bool LLPermissions::deedToGroup(const LLUUID& agent, const LLUUID& group)
-{
- if(group.notNull() && (agent.isNull() || ((group == mGroup)
- && (mMaskOwner & PERM_TRANSFER)
- && (mMaskGroup & PERM_MOVE))))
- {
- if(mOwner.notNull())
- {
- mLastOwner = mOwner;
- mOwner.setNull();
- }
- mMaskBase = mMaskNextOwner;
- mMaskGroup = PERM_NONE;
- mGroup = group;
- mIsGroupOwned = true;
- fixFairUse();
- fix();
- return true;
- }
- return false;
-}
-
-bool LLPermissions::setBaseBits(const LLUUID& agent, bool set, PermissionMask bits)
-{
- bool ownership = false;
- if(agent.isNull())
- {
- // only the system is always allowed to change base bits
- ownership = true;
- }
-
- if (ownership)
- {
- if (set)
- {
- mMaskBase |= bits; // turn on bits
- }
- else
- {
- mMaskBase &= ~bits; // turn off bits
- }
- fix();
- }
-
- return ownership;
-}
-
-
-// Note: If you attempt to set bits that the base bits doesn't allow,
-// the function will succeed, but those bits will not be set.
-bool LLPermissions::setOwnerBits(const LLUUID& agent, bool set, PermissionMask bits)
-{
- bool ownership = false;
-
- if(agent.isNull())
- {
- // ...system always allowed to change things
- ownership = true;
- }
- else if (agent == mOwner)
- {
- // ...owner bits can only be set by owner
- ownership = true;
- }
-
- // If we have correct ownership and
- if (ownership)
- {
- if (set)
- {
- mMaskOwner |= bits; // turn on bits
- }
- else
- {
- mMaskOwner &= ~bits; // turn off bits
- }
- fix();
- }
-
- return (ownership);
-}
-
-bool LLPermissions::setGroupBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits)
-{
- bool ownership = false;
- if((agent.isNull()) || (agent == mOwner)
- || ((group == mGroup) && (!mGroup.isNull())))
- {
- // The group bits can be set by the system, the owner, or a
- // group member.
- ownership = true;
- }
-
- if (ownership)
- {
- if (set)
- {
- mMaskGroup |= bits;
- }
- else
- {
- mMaskGroup &= ~bits;
- }
- fix();
- }
- return ownership;
-}
-
-
-// Note: If you attempt to set bits that the creator or owner doesn't allow,
-// the function will succeed, but those bits will not be set.
-bool LLPermissions::setEveryoneBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits)
-{
- bool ownership = false;
- if((agent.isNull()) || (agent == mOwner)
- || ((group == mGroup) && (!mGroup.isNull())))
- {
- // The everyone bits can be set by the system, the owner, or a
- // group member.
- ownership = true;
- }
- if (ownership)
- {
- if (set)
- {
- mMaskEveryone |= bits;
- }
- else
- {
- mMaskEveryone &= ~bits;
- }
-
- // Fix hierarchy of permissions
- fix();
- }
- return ownership;
-}
-
-// Note: If you attempt to set bits that the creator or owner doesn't allow,
-// the function will succeed, but those bits will not be set.
-bool LLPermissions::setNextOwnerBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits)
-{
- bool ownership = false;
- if((agent.isNull()) || (agent == mOwner)
- || ((group == mGroup) && (!mGroup.isNull())))
- {
- // The next owner bits can be set by the system, the owner, or
- // a group member.
- ownership = true;
- }
- if (ownership)
- {
- if (set)
- {
- mMaskNextOwner |= bits;
- }
- else
- {
- mMaskNextOwner &= ~bits;
- }
-
- // Fix-up permissions
- if(!(mMaskNextOwner & PERM_COPY))
- {
- mMaskNextOwner |= PERM_TRANSFER;
- }
- fix();
- }
- return ownership;
-}
-
-bool LLPermissions::allowOperationBy(PermissionBit op, const LLUUID& requester, const LLUUID& group) const
-{
- if(requester.isNull())
- {
- // ...system making request
- // ...not owned
- return true;
- }
- else if (mIsGroupOwned && (mGroup == requester))
- {
- // group checking ownership permissions
- return (mMaskOwner & op);
- }
- else if (!mIsGroupOwned && (mOwner == requester))
- {
- // ...owner making request
- return (mMaskOwner & op);
- }
- else if(mGroup.notNull() && (mGroup == group))
- {
- // group member making request
- return ((mMaskGroup & op) || (mMaskEveryone & op));
- }
- return (mMaskEveryone & op);
-}
-
-//
-// LLSD support for HTTP messages.
-//
-LLSD LLPermissions::packMessage() const
-{
- LLSD result;
- result["creator-id"] = mCreator;
- result["owner-id"] = mOwner;
- result["group-id"] = mGroup;
-
- result["base-mask"] = (S32)mMaskBase;
- result["owner-mask"] = (S32)mMaskOwner;
- result["group-mask"] = (S32)mMaskGroup;
- result["everyone-mask"] = (S32)mMaskEveryone;
- result["next-owner-mask"]= (S32)mMaskNextOwner;
- result["group-owned"] = (bool)mIsGroupOwned;
- return result;
-}
-
-//
-// Messaging support
-//
-void LLPermissions::packMessage(LLMessageSystem* msg) const
-{
- msg->addUUIDFast(_PREHASH_CreatorID, mCreator);
- msg->addUUIDFast(_PREHASH_OwnerID, mOwner);
- msg->addUUIDFast(_PREHASH_GroupID, mGroup);
-
- msg->addU32Fast(_PREHASH_BaseMask, mMaskBase );
- msg->addU32Fast(_PREHASH_OwnerMask, mMaskOwner );
- msg->addU32Fast(_PREHASH_GroupMask, mMaskGroup );
- msg->addU32Fast(_PREHASH_EveryoneMask, mMaskEveryone );
- msg->addU32Fast(_PREHASH_NextOwnerMask, mMaskNextOwner );
- msg->addBOOLFast(_PREHASH_GroupOwned, mIsGroupOwned);
-}
-
-void LLPermissions::unpackMessage(LLSD perms)
-{
- mCreator = perms["creator-id"];
- mOwner = perms["owner-id"];
- mGroup = perms["group-id"];
-
- mMaskBase = (U32)perms["base-mask"].asInteger();
- mMaskOwner = (U32)perms["owner-mask"].asInteger();
- mMaskGroup = (U32)perms["group-mask"].asInteger();
- mMaskEveryone = (U32)perms["everyone-mask"].asInteger();
- mMaskNextOwner = (U32)perms["next-owner-mask"].asInteger();
- mIsGroupOwned = perms["group-owned"].asBoolean();
-}
-
-void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
-{
- msg->getUUIDFast(block, _PREHASH_CreatorID, mCreator, block_num);
- msg->getUUIDFast(block, _PREHASH_OwnerID, mOwner, block_num);
- msg->getUUIDFast(block, _PREHASH_GroupID, mGroup, block_num);
-
- msg->getU32Fast(block, _PREHASH_BaseMask, mMaskBase, block_num );
- msg->getU32Fast(block, _PREHASH_OwnerMask, mMaskOwner, block_num );
- msg->getU32Fast(block, _PREHASH_GroupMask, mMaskGroup, block_num );
- msg->getU32Fast(block, _PREHASH_EveryoneMask, mMaskEveryone, block_num );
- msg->getU32Fast(block, _PREHASH_NextOwnerMask, mMaskNextOwner, block_num );
- bool tmp;
- msg->getBOOLFast(block, _PREHASH_GroupOwned, tmp, block_num);
- mIsGroupOwned = tmp;
-}
-
-
-bool LLPermissions::importLegacyStream(std::istream& input_stream)
-{
- init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
- const S32 BUFSIZE = 16384;
-
- // *NOTE: Changing the buffer size will require changing the scanf
- // calls below.
- char buffer[BUFSIZE]; /* Flawfinder: ignore */
- char keyword[256]; /* Flawfinder: ignore */
- char valuestr[256]; /* Flawfinder: ignore */
- char uuid_str[256]; /* Flawfinder: ignore */
- U32 mask;
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
-
- while (input_stream.good())
- {
- input_stream.getline(buffer, BUFSIZE);
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %255s %255s",
- keyword, valuestr);
- if (!strcmp("{", keyword))
- {
- continue;
- }
- if (!strcmp("}",keyword))
- {
- break;
- }
- else if (!strcmp("creator_mask", keyword))
- {
- // legacy support for "creator" masks
- sscanf(valuestr, "%x", &mask);
- mMaskBase = mask;
- fixFairUse();
- }
- else if (!strcmp("base_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskBase = mask;
- //fixFairUse();
- }
- else if (!strcmp("owner_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskOwner = mask;
- }
- else if (!strcmp("group_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskGroup = mask;
- }
- else if (!strcmp("everyone_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskEveryone = mask;
- }
- else if (!strcmp("next_owner_mask", keyword))
- {
- sscanf(valuestr, "%x", &mask);
- mMaskNextOwner = mask;
- }
- else if (!strcmp("creator_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mCreator.set(uuid_str);
- }
- else if (!strcmp("owner_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mOwner.set(uuid_str);
- }
- else if (!strcmp("last_owner_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mLastOwner.set(uuid_str);
- }
- else if (!strcmp("group_id", keyword))
- {
- sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */
- mGroup.set(uuid_str);
- }
- else if (!strcmp("group_owned", keyword))
- {
- sscanf(valuestr, "%d", &mask);
- if(mask) mIsGroupOwned = true;
- else mIsGroupOwned = false;
- }
- else
- {
- LL_INFOS() << "unknown keyword " << keyword << " in permissions import" << LL_ENDL;
- }
- }
- fix();
- return true;
-}
-
-
-bool LLPermissions::exportLegacyStream(std::ostream& output_stream) const
-{
- std::string uuid_str;
-
- output_stream << "\tpermissions 0\n";
- output_stream << "\t{\n";
-
- std::string buffer;
- buffer = llformat( "\t\tbase_mask\t%08x\n", mMaskBase);
- output_stream << buffer;
- buffer = llformat( "\t\towner_mask\t%08x\n", mMaskOwner);
- output_stream << buffer;
- buffer = llformat( "\t\tgroup_mask\t%08x\n", mMaskGroup);
- output_stream << buffer;
- buffer = llformat( "\t\teveryone_mask\t%08x\n", mMaskEveryone);
- output_stream << buffer;
- buffer = llformat( "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner);
- output_stream << buffer;
-
- mCreator.toString(uuid_str);
- output_stream << "\t\tcreator_id\t" << uuid_str << "\n";
-
- mOwner.toString(uuid_str);
- output_stream << "\t\towner_id\t" << uuid_str << "\n";
-
- mLastOwner.toString(uuid_str);
- output_stream << "\t\tlast_owner_id\t" << uuid_str << "\n";
-
- mGroup.toString(uuid_str);
- output_stream << "\t\tgroup_id\t" << uuid_str << "\n";
-
- if(mIsGroupOwned)
- {
- output_stream << "\t\tgroup_owned\t1\n";
- }
- output_stream << "\t}\n";
- return true;
-}
-
-bool LLPermissions::operator==(const LLPermissions &rhs) const
-{
- return
- (mCreator == rhs.mCreator) &&
- (mOwner == rhs.mOwner) &&
- (mLastOwner == rhs.mLastOwner ) &&
- (mGroup == rhs.mGroup ) &&
- (mMaskBase == rhs.mMaskBase ) &&
- (mMaskOwner == rhs.mMaskOwner ) &&
- (mMaskGroup == rhs.mMaskGroup ) &&
- (mMaskEveryone == rhs.mMaskEveryone ) &&
- (mMaskNextOwner == rhs.mMaskNextOwner ) &&
- (mIsGroupOwned == rhs.mIsGroupOwned);
-}
-
-
-bool LLPermissions::operator!=(const LLPermissions &rhs) const
-{
- return
- (mCreator != rhs.mCreator) ||
- (mOwner != rhs.mOwner) ||
- (mLastOwner != rhs.mLastOwner ) ||
- (mGroup != rhs.mGroup ) ||
- (mMaskBase != rhs.mMaskBase ) ||
- (mMaskOwner != rhs.mMaskOwner ) ||
- (mMaskGroup != rhs.mMaskGroup ) ||
- (mMaskEveryone != rhs.mMaskEveryone ) ||
- (mMaskNextOwner != rhs.mMaskNextOwner) ||
- (mIsGroupOwned != rhs.mIsGroupOwned);
-}
-
-std::ostream& operator<<(std::ostream &s, const LLPermissions &perm)
-{
- s << "{Creator=" << perm.getCreator();
- s << ", Owner=" << perm.getOwner();
- s << ", Group=" << perm.getGroup();
- s << std::hex << ", BaseMask=0x" << perm.getMaskBase();
- s << ", OwnerMask=0x" << perm.getMaskOwner();
- s << ", EveryoneMask=0x" << perm.getMaskEveryone();
- s << ", GroupMask=0x" << perm.getMaskGroup();
- s << ", NextOwnerMask=0x" << perm.getMaskNextOwner() << std::dec;
- s << "}";
- return s;
-}
-
-///----------------------------------------------------------------------------
-/// Class LLAggregatePermissions
-///----------------------------------------------------------------------------
-
-const LLAggregatePermissions LLAggregatePermissions::empty;
-
-
-LLAggregatePermissions::LLAggregatePermissions()
-{
- for(S32 i = 0; i < PI_COUNT; ++i)
- {
- mBits[i] = AP_EMPTY;
- }
-}
-
-LLAggregatePermissions::EValue LLAggregatePermissions::getValue(PermissionBit bit) const
-{
- EPermIndex idx = perm2PermIndex(bit);
- EValue rv = AP_EMPTY;
- if(idx != PI_END)
- {
- rv = (LLAggregatePermissions::EValue)(mBits[idx]);
- }
- return rv;
-}
-
-// returns the bits compressed into a single byte: 00TTMMCC
-// where TT = transfer, MM = modify, and CC = copy
-// LSB is to the right
-U8 LLAggregatePermissions::getU8() const
-{
- U8 byte = mBits[PI_TRANSFER];
- byte <<= 2;
- byte |= mBits[PI_MODIFY];
- byte <<= 2;
- byte |= mBits[PI_COPY];
- return byte;
-}
-
-bool LLAggregatePermissions::isEmpty() const
-{
- for(S32 i = 0; i < PI_END; ++i)
- {
- if(mBits[i] != AP_EMPTY)
- {
- return false;
- }
- }
- return true;
-}
-
-void LLAggregatePermissions::aggregate(PermissionMask mask)
-{
- bool is_allowed = mask & PERM_COPY;
- aggregateBit(PI_COPY, is_allowed);
- is_allowed = mask & PERM_MODIFY;
- aggregateBit(PI_MODIFY, is_allowed);
- is_allowed = mask & PERM_TRANSFER;
- aggregateBit(PI_TRANSFER, is_allowed);
-}
-
-void LLAggregatePermissions::aggregate(const LLAggregatePermissions& ag)
-{
- for(S32 idx = PI_COPY; idx != PI_END; ++idx)
- {
- aggregateIndex((EPermIndex)idx, ag.mBits[idx]);
- }
-}
-
-void LLAggregatePermissions::aggregateBit(EPermIndex idx, bool allowed)
-{
- //if(AP_SOME == mBits[idx]) return; // P4 branch prediction optimization
- switch(mBits[idx])
- {
- case AP_EMPTY:
- mBits[idx] = allowed ? AP_ALL : AP_NONE;
- break;
- case AP_NONE:
- mBits[idx] = allowed ? AP_SOME: AP_NONE;
- break;
- case AP_SOME:
- // no-op
- break;
- case AP_ALL:
- mBits[idx] = allowed ? AP_ALL : AP_SOME;
- break;
- default:
- LL_WARNS() << "Bad aggregateBit " << (S32)idx << " "
- << (allowed ? "true" : "false") << LL_ENDL;
- break;
- }
-}
-
-void LLAggregatePermissions::aggregateIndex(EPermIndex idx, U8 bits)
-{
- switch(mBits[idx])
- {
- case AP_EMPTY:
- mBits[idx] = bits;
- break;
- case AP_NONE:
- switch(bits)
- {
- case AP_SOME:
- case AP_ALL:
- mBits[idx] = AP_SOME;
- break;
- case AP_EMPTY:
- case AP_NONE:
- default:
- // no-op
- break;
- }
- break;
- case AP_SOME:
- // no-op
- break;
- case AP_ALL:
- switch(bits)
- {
- case AP_NONE:
- case AP_SOME:
- mBits[idx] = AP_SOME;
- break;
- case AP_EMPTY:
- case AP_ALL:
- default:
- // no-op
- break;
- }
- break;
- default:
- LL_WARNS() << "Bad aggregate index " << (S32)idx << " "
- << (S32)bits << LL_ENDL;
- break;
- }
-}
-
-// static
-LLAggregatePermissions::EPermIndex LLAggregatePermissions::perm2PermIndex(PermissionBit bit)
-{
- EPermIndex idx = PI_END; // past any good value.
- switch(bit)
- {
- case PERM_COPY:
- idx = PI_COPY;
- break;
- case PERM_MODIFY:
- idx = PI_MODIFY;
- break;
- case PERM_TRANSFER:
- idx = PI_TRANSFER;
- break;
- default:
- break;
- }
- return idx;
-}
-
-
-void LLAggregatePermissions::packMessage(LLMessageSystem* msg, const char* field) const
-{
- msg->addU8Fast(field, getU8());
-}
-
-void LLAggregatePermissions::unpackMessage(LLMessageSystem* msg, const char* block, const char* field, S32 block_num)
-{
- const U8 TWO_BITS = 0x3; // binary 00000011
- U8 bits = 0;
- msg->getU8Fast(block, field, bits, block_num);
- mBits[PI_COPY] = bits & TWO_BITS;
- bits >>= 2;
- mBits[PI_MODIFY] = bits & TWO_BITS;
- bits >>= 2;
- mBits[PI_TRANSFER] = bits & TWO_BITS;
-}
-
-const std::string AGGREGATE_VALUES[4] =
- {
- std::string( "Empty" ),
- std::string( "None" ),
- std::string( "Some" ),
- std::string( "All" )
- };
-
-std::ostream& operator<<(std::ostream &s, const LLAggregatePermissions &perm)
-{
- s << "{PI_COPY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_COPY]];
- s << ", PI_MODIFY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_MODIFY]];
- s << ", PI_TRANSFER=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_TRANSFER]];
- s << "}";
- return s;
-}
-
-// This converts a permissions mask into a string for debugging use.
-void mask_to_string(U32 mask, char* str)
-{
- if (mask & PERM_MOVE)
- {
- *str = 'V';
- }
- else
- {
- *str = ' ';
- }
- str++;
-
- if (mask & PERM_MODIFY)
- {
- *str = 'M';
- }
- else
- {
- *str = ' ';
- }
- str++;
-
- if (mask & PERM_COPY)
- {
- *str = 'C';
- }
- else
- {
- *str = ' ';
- }
- str++;
-
- if (mask & PERM_TRANSFER)
- {
- *str = 'T';
- }
- else
- {
- *str = ' ';
- }
- str++;
- *str = '\0';
-}
-
-std::string mask_to_string(U32 mask)
-{
- char str[16];
- mask_to_string(mask, str);
- return std::string(str);
-}
-
-///----------------------------------------------------------------------------
-/// exported functions
-///----------------------------------------------------------------------------
-static const std::string PERM_CREATOR_ID_LABEL("creator_id");
-static const std::string PERM_OWNER_ID_LABEL("owner_id");
-static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
-static const std::string PERM_GROUP_ID_LABEL("group_id");
-static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
-static const std::string PERM_BASE_MASK_LABEL("base_mask");
-static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
-static const std::string PERM_GROUP_MASK_LABEL("group_mask");
-static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
-static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
-
-LLSD ll_create_sd_from_permissions(const LLPermissions& perm)
-{
- LLSD rv;
- rv[PERM_CREATOR_ID_LABEL] = perm.getCreator();
- rv[PERM_OWNER_ID_LABEL] = perm.getOwner();
- rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner();
- rv[PERM_GROUP_ID_LABEL] = perm.getGroup();
- rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned();
- rv[PERM_BASE_MASK_LABEL] = (S32)perm.getMaskBase();
- rv[PERM_OWNER_MASK_LABEL] = (S32)perm.getMaskOwner();
- rv[PERM_GROUP_MASK_LABEL] = (S32)perm.getMaskGroup();
- rv[PERM_EVERYONE_MASK_LABEL] = (S32)perm.getMaskEveryone();
- rv[PERM_NEXT_OWNER_MASK_LABEL] = (S32)perm.getMaskNextOwner();
- return rv;
-}
-
-LLPermissions ll_permissions_from_sd(const LLSD& sd_perm)
-{
- LLPermissions rv;
- rv.init(
- sd_perm[PERM_CREATOR_ID_LABEL].asUUID(),
- sd_perm[PERM_OWNER_ID_LABEL].asUUID(),
- sd_perm[PERM_LAST_OWNER_ID_LABEL].asUUID(),
- sd_perm[PERM_GROUP_ID_LABEL].asUUID());
-
- // We do a cast to U32 here since LLSD does not attempt to
- // represent unsigned ints.
- PermissionMask mask;
- mask = (U32)(sd_perm[PERM_BASE_MASK_LABEL].asInteger());
- rv.setMaskBase(mask);
- mask = (U32)(sd_perm[PERM_OWNER_MASK_LABEL].asInteger());
- rv.setMaskOwner(mask);
- mask = (U32)(sd_perm[PERM_EVERYONE_MASK_LABEL].asInteger());
- rv.setMaskEveryone(mask);
- mask = (U32)(sd_perm[PERM_GROUP_MASK_LABEL].asInteger());
- rv.setMaskGroup(mask);
- mask = (U32)(sd_perm[PERM_NEXT_OWNER_MASK_LABEL].asInteger());
- rv.setMaskNext(mask);
- rv.fix();
- return rv;
-}
+/** + * @file llpermissions.cpp + * @author Phoenix + * @brief Permissions for objects and inventory. + * + * $LicenseInfo:firstyear=2002&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 "llpermissions.h" + +// library includes +#include "message.h" +#include "llsd.h" + +///---------------------------------------------------------------------------- +/// Class LLPermissions +///---------------------------------------------------------------------------- + +const LLPermissions LLPermissions::DEFAULT; + +// No creator = created by system +LLPermissions::LLPermissions() +{ + init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); +} + + +// Default to created by system +void LLPermissions::init(const LLUUID& creator, const LLUUID& owner, const LLUUID& last_owner, const LLUUID& group) +{ + mCreator = creator; + mOwner = owner; + mLastOwner = last_owner; + mGroup = group; + + mMaskBase = PERM_ALL; + mMaskOwner = PERM_ALL; + mMaskEveryone = PERM_ALL; + mMaskGroup = PERM_ALL; + mMaskNextOwner = PERM_ALL; + fixOwnership(); +} + + +void LLPermissions::initMasks(PermissionMask base, PermissionMask owner, + PermissionMask everyone, PermissionMask group, + PermissionMask next) +{ + mMaskBase = base; + mMaskOwner = owner; + mMaskEveryone = everyone; + mMaskGroup = group; + mMaskNextOwner = next; + fixFairUse(); + fix(); +} + +// ! BACKWARDS COMPATIBILITY ! Override masks for inventory types that +// no longer can have restricted permissions. This takes care of previous +// version landmarks that could have had no copy/mod/transfer bits set. +void LLPermissions::initMasks(LLInventoryType::EType type) +{ + if (LLInventoryType::cannotRestrictPermissions(type)) + { + initMasks(PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL); + } +} + +bool LLPermissions::getOwnership(LLUUID& owner_id, bool& is_group_owned) const +{ + if(mOwner.notNull()) + { + owner_id = mOwner; + is_group_owned = false; + return true; + } + else if(mIsGroupOwned) + { + owner_id = mGroup; + is_group_owned = true; + return true; + } + return false; +} + +LLUUID LLPermissions::getSafeOwner() const +{ + if(mOwner.notNull()) + { + return mOwner; + } + else if(mIsGroupOwned) + { + return mGroup; + } + else + { + LL_WARNS() << "LLPermissions::getSafeOwner() called with no valid owner!" << LL_ENDL; + LLUUID unused_uuid; + unused_uuid.generate(); + + return unused_uuid; + } +} + +U32 LLPermissions::getCRC32() const +{ + U32 rv = mCreator.getCRC32(); + rv += mOwner.getCRC32(); + rv += mLastOwner.getCRC32(); + rv += mGroup.getCRC32(); + rv += mMaskBase + mMaskOwner + mMaskEveryone + mMaskGroup; + return rv; +} + +void LLPermissions::set(const LLPermissions& from) +{ + mCreator = from.mCreator; + mOwner = from.mOwner; + mLastOwner = from.mLastOwner; + mGroup = from.mGroup; + + mMaskBase = from.mMaskBase; + mMaskOwner = from.mMaskOwner; + mMaskEveryone = from.mMaskEveryone; + mMaskGroup = from.mMaskGroup; + mMaskNextOwner = from.mMaskNextOwner; + mIsGroupOwned = from.mIsGroupOwned; +} + +// Fix hierarchy of permissions. +void LLPermissions::fix() +{ + mMaskOwner &= mMaskBase; + mMaskGroup &= mMaskOwner; + // next owner uses base, since you may want to sell locked objects. + mMaskNextOwner &= mMaskBase; + mMaskEveryone &= mMaskOwner; + mMaskEveryone &= ~PERM_MODIFY; + if(!(mMaskBase & PERM_TRANSFER) && !mIsGroupOwned) + { + mMaskGroup &= ~PERM_COPY; + mMaskEveryone &= ~PERM_COPY; + // Do not set mask next owner to too restrictive because if we + // rez an object, it may require an ownership transfer during + // rez, which will note the overly restrictive perms, and then + // fix them to allow fair use, which may be different than the + // original intention. + } +} + +// Correct for fair use - you can never take away the right to move +// stuff you own, and you can never take away the right to transfer +// something you cannot otherwise copy. +void LLPermissions::fixFairUse() +{ + mMaskBase |= PERM_MOVE; + if(!(mMaskBase & PERM_COPY)) + { + mMaskBase |= PERM_TRANSFER; + } + // (mask next owner == PERM_NONE) iff mask base is no transfer + if(mMaskNextOwner != PERM_NONE) + { + mMaskNextOwner |= PERM_MOVE; + } +} + +void LLPermissions::fixOwnership() +{ + if(mOwner.isNull() && mGroup.notNull()) + { + mIsGroupOwned = true; + } + else + { + mIsGroupOwned = false; + } +} + +// Allow accumulation of permissions. Results in the tightest +// permissions possible. In the case of clashing UUIDs, it sets the ID +// to LLUUID::null. +void LLPermissions::accumulate(const LLPermissions& perm) +{ + if(perm.mCreator != mCreator) + { + mCreator = LLUUID::null; + } + if(perm.mOwner != mOwner) + { + mOwner = LLUUID::null; + } + if(perm.mLastOwner != mLastOwner) + { + mLastOwner = LLUUID::null; + } + if(perm.mGroup != mGroup) + { + mGroup = LLUUID::null; + } + + mMaskBase &= perm.mMaskBase; + mMaskOwner &= perm.mMaskOwner; + mMaskGroup &= perm.mMaskGroup; + mMaskEveryone &= perm.mMaskEveryone; + mMaskNextOwner &= perm.mMaskNextOwner; + fix(); +} + +// saves last owner, sets current owner, and sets the group. note +// that this function has to more cleverly apply the fair use +// permissions. +bool LLPermissions::setOwnerAndGroup( + const LLUUID& agent, + const LLUUID& owner, + const LLUUID& group, + bool is_atomic) +{ + bool allowed = false; + + if( agent.isNull() || mOwner.isNull() + || ((agent == mOwner) && ((owner == mOwner) || (mMaskOwner & PERM_TRANSFER)) ) ) + { + // ...system can alway set owner + // ...public objects can be claimed by anyone + // ...otherwise, agent must own it and have transfer ability + allowed = true; + } + + if (allowed) + { + if(mLastOwner.isNull() || (!mOwner.isNull() && (owner != mLastOwner))) + { + mLastOwner = mOwner; + } + if((mOwner != owner) + || (mOwner.isNull() && owner.isNull() && (mGroup != group))) + { + mMaskBase = mMaskNextOwner; + mOwner = owner; + // this is a selective use of fair use for atomic + // permissions. + if(is_atomic && !(mMaskBase & PERM_COPY)) + { + mMaskBase |= PERM_TRANSFER; + } + } + mGroup = group; + fixOwnership(); + // if it's not atomic and we fix fair use, it blows away + //objects as inventory items which have different permissions + //than it's contents. :( + // fixFairUse(); + mMaskBase |= PERM_MOVE; + if(mMaskNextOwner != PERM_NONE) mMaskNextOwner |= PERM_MOVE; + fix(); + } + + return allowed; +} + +//Fix for DEV-33917, last owner isn't used much and has little impact on +//permissions so it's reasonably safe to do this, however, for now, +//limiting the functionality of this routine to objects which are +//group owned. +void LLPermissions::setLastOwner(const LLUUID& last_owner) +{ + if (isGroupOwned()) + mLastOwner = last_owner; +} + + +// only call this if you know what you're doing +// there are usually perm-bit consequences when the +// ownerhsip changes +void LLPermissions::yesReallySetOwner(const LLUUID& owner, bool group_owned) +{ + mOwner = owner; + mIsGroupOwned = group_owned; +} + +bool LLPermissions::deedToGroup(const LLUUID& agent, const LLUUID& group) +{ + if(group.notNull() && (agent.isNull() || ((group == mGroup) + && (mMaskOwner & PERM_TRANSFER) + && (mMaskGroup & PERM_MOVE)))) + { + if(mOwner.notNull()) + { + mLastOwner = mOwner; + mOwner.setNull(); + } + mMaskBase = mMaskNextOwner; + mMaskGroup = PERM_NONE; + mGroup = group; + mIsGroupOwned = true; + fixFairUse(); + fix(); + return true; + } + return false; +} + +bool LLPermissions::setBaseBits(const LLUUID& agent, bool set, PermissionMask bits) +{ + bool ownership = false; + if(agent.isNull()) + { + // only the system is always allowed to change base bits + ownership = true; + } + + if (ownership) + { + if (set) + { + mMaskBase |= bits; // turn on bits + } + else + { + mMaskBase &= ~bits; // turn off bits + } + fix(); + } + + return ownership; +} + + +// Note: If you attempt to set bits that the base bits doesn't allow, +// the function will succeed, but those bits will not be set. +bool LLPermissions::setOwnerBits(const LLUUID& agent, bool set, PermissionMask bits) +{ + bool ownership = false; + + if(agent.isNull()) + { + // ...system always allowed to change things + ownership = true; + } + else if (agent == mOwner) + { + // ...owner bits can only be set by owner + ownership = true; + } + + // If we have correct ownership and + if (ownership) + { + if (set) + { + mMaskOwner |= bits; // turn on bits + } + else + { + mMaskOwner &= ~bits; // turn off bits + } + fix(); + } + + return (ownership); +} + +bool LLPermissions::setGroupBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits) +{ + bool ownership = false; + if((agent.isNull()) || (agent == mOwner) + || ((group == mGroup) && (!mGroup.isNull()))) + { + // The group bits can be set by the system, the owner, or a + // group member. + ownership = true; + } + + if (ownership) + { + if (set) + { + mMaskGroup |= bits; + } + else + { + mMaskGroup &= ~bits; + } + fix(); + } + return ownership; +} + + +// Note: If you attempt to set bits that the creator or owner doesn't allow, +// the function will succeed, but those bits will not be set. +bool LLPermissions::setEveryoneBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits) +{ + bool ownership = false; + if((agent.isNull()) || (agent == mOwner) + || ((group == mGroup) && (!mGroup.isNull()))) + { + // The everyone bits can be set by the system, the owner, or a + // group member. + ownership = true; + } + if (ownership) + { + if (set) + { + mMaskEveryone |= bits; + } + else + { + mMaskEveryone &= ~bits; + } + + // Fix hierarchy of permissions + fix(); + } + return ownership; +} + +// Note: If you attempt to set bits that the creator or owner doesn't allow, +// the function will succeed, but those bits will not be set. +bool LLPermissions::setNextOwnerBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits) +{ + bool ownership = false; + if((agent.isNull()) || (agent == mOwner) + || ((group == mGroup) && (!mGroup.isNull()))) + { + // The next owner bits can be set by the system, the owner, or + // a group member. + ownership = true; + } + if (ownership) + { + if (set) + { + mMaskNextOwner |= bits; + } + else + { + mMaskNextOwner &= ~bits; + } + + // Fix-up permissions + if(!(mMaskNextOwner & PERM_COPY)) + { + mMaskNextOwner |= PERM_TRANSFER; + } + fix(); + } + return ownership; +} + +bool LLPermissions::allowOperationBy(PermissionBit op, const LLUUID& requester, const LLUUID& group) const +{ + if(requester.isNull()) + { + // ...system making request + // ...not owned + return true; + } + else if (mIsGroupOwned && (mGroup == requester)) + { + // group checking ownership permissions + return (mMaskOwner & op); + } + else if (!mIsGroupOwned && (mOwner == requester)) + { + // ...owner making request + return (mMaskOwner & op); + } + else if(mGroup.notNull() && (mGroup == group)) + { + // group member making request + return ((mMaskGroup & op) || (mMaskEveryone & op)); + } + return (mMaskEveryone & op); +} + +// +// LLSD support for HTTP messages. +// +LLSD LLPermissions::packMessage() const +{ + LLSD result; + result["creator-id"] = mCreator; + result["owner-id"] = mOwner; + result["group-id"] = mGroup; + + result["base-mask"] = (S32)mMaskBase; + result["owner-mask"] = (S32)mMaskOwner; + result["group-mask"] = (S32)mMaskGroup; + result["everyone-mask"] = (S32)mMaskEveryone; + result["next-owner-mask"]= (S32)mMaskNextOwner; + result["group-owned"] = (bool)mIsGroupOwned; + return result; +} + +// +// Messaging support +// +void LLPermissions::packMessage(LLMessageSystem* msg) const +{ + msg->addUUIDFast(_PREHASH_CreatorID, mCreator); + msg->addUUIDFast(_PREHASH_OwnerID, mOwner); + msg->addUUIDFast(_PREHASH_GroupID, mGroup); + + msg->addU32Fast(_PREHASH_BaseMask, mMaskBase ); + msg->addU32Fast(_PREHASH_OwnerMask, mMaskOwner ); + msg->addU32Fast(_PREHASH_GroupMask, mMaskGroup ); + msg->addU32Fast(_PREHASH_EveryoneMask, mMaskEveryone ); + msg->addU32Fast(_PREHASH_NextOwnerMask, mMaskNextOwner ); + msg->addBOOLFast(_PREHASH_GroupOwned, mIsGroupOwned); +} + +void LLPermissions::unpackMessage(LLSD perms) +{ + mCreator = perms["creator-id"]; + mOwner = perms["owner-id"]; + mGroup = perms["group-id"]; + + mMaskBase = (U32)perms["base-mask"].asInteger(); + mMaskOwner = (U32)perms["owner-mask"].asInteger(); + mMaskGroup = (U32)perms["group-mask"].asInteger(); + mMaskEveryone = (U32)perms["everyone-mask"].asInteger(); + mMaskNextOwner = (U32)perms["next-owner-mask"].asInteger(); + mIsGroupOwned = perms["group-owned"].asBoolean(); +} + +void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) +{ + msg->getUUIDFast(block, _PREHASH_CreatorID, mCreator, block_num); + msg->getUUIDFast(block, _PREHASH_OwnerID, mOwner, block_num); + msg->getUUIDFast(block, _PREHASH_GroupID, mGroup, block_num); + + msg->getU32Fast(block, _PREHASH_BaseMask, mMaskBase, block_num ); + msg->getU32Fast(block, _PREHASH_OwnerMask, mMaskOwner, block_num ); + msg->getU32Fast(block, _PREHASH_GroupMask, mMaskGroup, block_num ); + msg->getU32Fast(block, _PREHASH_EveryoneMask, mMaskEveryone, block_num ); + msg->getU32Fast(block, _PREHASH_NextOwnerMask, mMaskNextOwner, block_num ); + bool tmp; + msg->getBOOLFast(block, _PREHASH_GroupOwned, tmp, block_num); + mIsGroupOwned = tmp; +} + + +bool LLPermissions::importLegacyStream(std::istream& input_stream) +{ + init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); + const S32 BUFSIZE = 16384; + + // *NOTE: Changing the buffer size will require changing the scanf + // calls below. + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + char uuid_str[256]; /* Flawfinder: ignore */ + U32 mask; + + keyword[0] = '\0'; + valuestr[0] = '\0'; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("creator_mask", keyword)) + { + // legacy support for "creator" masks + sscanf(valuestr, "%x", &mask); + mMaskBase = mask; + fixFairUse(); + } + else if (!strcmp("base_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskBase = mask; + //fixFairUse(); + } + else if (!strcmp("owner_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskOwner = mask; + } + else if (!strcmp("group_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskGroup = mask; + } + else if (!strcmp("everyone_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskEveryone = mask; + } + else if (!strcmp("next_owner_mask", keyword)) + { + sscanf(valuestr, "%x", &mask); + mMaskNextOwner = mask; + } + else if (!strcmp("creator_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mCreator.set(uuid_str); + } + else if (!strcmp("owner_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mOwner.set(uuid_str); + } + else if (!strcmp("last_owner_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mLastOwner.set(uuid_str); + } + else if (!strcmp("group_id", keyword)) + { + sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ + mGroup.set(uuid_str); + } + else if (!strcmp("group_owned", keyword)) + { + sscanf(valuestr, "%d", &mask); + if(mask) mIsGroupOwned = true; + else mIsGroupOwned = false; + } + else + { + LL_INFOS() << "unknown keyword " << keyword << " in permissions import" << LL_ENDL; + } + } + fix(); + return true; +} + + +bool LLPermissions::exportLegacyStream(std::ostream& output_stream) const +{ + std::string uuid_str; + + output_stream << "\tpermissions 0\n"; + output_stream << "\t{\n"; + + std::string buffer; + buffer = llformat( "\t\tbase_mask\t%08x\n", mMaskBase); + output_stream << buffer; + buffer = llformat( "\t\towner_mask\t%08x\n", mMaskOwner); + output_stream << buffer; + buffer = llformat( "\t\tgroup_mask\t%08x\n", mMaskGroup); + output_stream << buffer; + buffer = llformat( "\t\teveryone_mask\t%08x\n", mMaskEveryone); + output_stream << buffer; + buffer = llformat( "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); + output_stream << buffer; + + mCreator.toString(uuid_str); + output_stream << "\t\tcreator_id\t" << uuid_str << "\n"; + + mOwner.toString(uuid_str); + output_stream << "\t\towner_id\t" << uuid_str << "\n"; + + mLastOwner.toString(uuid_str); + output_stream << "\t\tlast_owner_id\t" << uuid_str << "\n"; + + mGroup.toString(uuid_str); + output_stream << "\t\tgroup_id\t" << uuid_str << "\n"; + + if(mIsGroupOwned) + { + output_stream << "\t\tgroup_owned\t1\n"; + } + output_stream << "\t}\n"; + return true; +} + +bool LLPermissions::operator==(const LLPermissions &rhs) const +{ + return + (mCreator == rhs.mCreator) && + (mOwner == rhs.mOwner) && + (mLastOwner == rhs.mLastOwner ) && + (mGroup == rhs.mGroup ) && + (mMaskBase == rhs.mMaskBase ) && + (mMaskOwner == rhs.mMaskOwner ) && + (mMaskGroup == rhs.mMaskGroup ) && + (mMaskEveryone == rhs.mMaskEveryone ) && + (mMaskNextOwner == rhs.mMaskNextOwner ) && + (mIsGroupOwned == rhs.mIsGroupOwned); +} + + +bool LLPermissions::operator!=(const LLPermissions &rhs) const +{ + return + (mCreator != rhs.mCreator) || + (mOwner != rhs.mOwner) || + (mLastOwner != rhs.mLastOwner ) || + (mGroup != rhs.mGroup ) || + (mMaskBase != rhs.mMaskBase ) || + (mMaskOwner != rhs.mMaskOwner ) || + (mMaskGroup != rhs.mMaskGroup ) || + (mMaskEveryone != rhs.mMaskEveryone ) || + (mMaskNextOwner != rhs.mMaskNextOwner) || + (mIsGroupOwned != rhs.mIsGroupOwned); +} + +std::ostream& operator<<(std::ostream &s, const LLPermissions &perm) +{ + s << "{Creator=" << perm.getCreator(); + s << ", Owner=" << perm.getOwner(); + s << ", Group=" << perm.getGroup(); + s << std::hex << ", BaseMask=0x" << perm.getMaskBase(); + s << ", OwnerMask=0x" << perm.getMaskOwner(); + s << ", EveryoneMask=0x" << perm.getMaskEveryone(); + s << ", GroupMask=0x" << perm.getMaskGroup(); + s << ", NextOwnerMask=0x" << perm.getMaskNextOwner() << std::dec; + s << "}"; + return s; +} + +///---------------------------------------------------------------------------- +/// Class LLAggregatePermissions +///---------------------------------------------------------------------------- + +const LLAggregatePermissions LLAggregatePermissions::empty; + + +LLAggregatePermissions::LLAggregatePermissions() +{ + for(S32 i = 0; i < PI_COUNT; ++i) + { + mBits[i] = AP_EMPTY; + } +} + +LLAggregatePermissions::EValue LLAggregatePermissions::getValue(PermissionBit bit) const +{ + EPermIndex idx = perm2PermIndex(bit); + EValue rv = AP_EMPTY; + if(idx != PI_END) + { + rv = (LLAggregatePermissions::EValue)(mBits[idx]); + } + return rv; +} + +// returns the bits compressed into a single byte: 00TTMMCC +// where TT = transfer, MM = modify, and CC = copy +// LSB is to the right +U8 LLAggregatePermissions::getU8() const +{ + U8 byte = mBits[PI_TRANSFER]; + byte <<= 2; + byte |= mBits[PI_MODIFY]; + byte <<= 2; + byte |= mBits[PI_COPY]; + return byte; +} + +bool LLAggregatePermissions::isEmpty() const +{ + for(S32 i = 0; i < PI_END; ++i) + { + if(mBits[i] != AP_EMPTY) + { + return false; + } + } + return true; +} + +void LLAggregatePermissions::aggregate(PermissionMask mask) +{ + bool is_allowed = mask & PERM_COPY; + aggregateBit(PI_COPY, is_allowed); + is_allowed = mask & PERM_MODIFY; + aggregateBit(PI_MODIFY, is_allowed); + is_allowed = mask & PERM_TRANSFER; + aggregateBit(PI_TRANSFER, is_allowed); +} + +void LLAggregatePermissions::aggregate(const LLAggregatePermissions& ag) +{ + for(S32 idx = PI_COPY; idx != PI_END; ++idx) + { + aggregateIndex((EPermIndex)idx, ag.mBits[idx]); + } +} + +void LLAggregatePermissions::aggregateBit(EPermIndex idx, bool allowed) +{ + //if(AP_SOME == mBits[idx]) return; // P4 branch prediction optimization + switch(mBits[idx]) + { + case AP_EMPTY: + mBits[idx] = allowed ? AP_ALL : AP_NONE; + break; + case AP_NONE: + mBits[idx] = allowed ? AP_SOME: AP_NONE; + break; + case AP_SOME: + // no-op + break; + case AP_ALL: + mBits[idx] = allowed ? AP_ALL : AP_SOME; + break; + default: + LL_WARNS() << "Bad aggregateBit " << (S32)idx << " " + << (allowed ? "true" : "false") << LL_ENDL; + break; + } +} + +void LLAggregatePermissions::aggregateIndex(EPermIndex idx, U8 bits) +{ + switch(mBits[idx]) + { + case AP_EMPTY: + mBits[idx] = bits; + break; + case AP_NONE: + switch(bits) + { + case AP_SOME: + case AP_ALL: + mBits[idx] = AP_SOME; + break; + case AP_EMPTY: + case AP_NONE: + default: + // no-op + break; + } + break; + case AP_SOME: + // no-op + break; + case AP_ALL: + switch(bits) + { + case AP_NONE: + case AP_SOME: + mBits[idx] = AP_SOME; + break; + case AP_EMPTY: + case AP_ALL: + default: + // no-op + break; + } + break; + default: + LL_WARNS() << "Bad aggregate index " << (S32)idx << " " + << (S32)bits << LL_ENDL; + break; + } +} + +// static +LLAggregatePermissions::EPermIndex LLAggregatePermissions::perm2PermIndex(PermissionBit bit) +{ + EPermIndex idx = PI_END; // past any good value. + switch(bit) + { + case PERM_COPY: + idx = PI_COPY; + break; + case PERM_MODIFY: + idx = PI_MODIFY; + break; + case PERM_TRANSFER: + idx = PI_TRANSFER; + break; + default: + break; + } + return idx; +} + + +void LLAggregatePermissions::packMessage(LLMessageSystem* msg, const char* field) const +{ + msg->addU8Fast(field, getU8()); +} + +void LLAggregatePermissions::unpackMessage(LLMessageSystem* msg, const char* block, const char* field, S32 block_num) +{ + const U8 TWO_BITS = 0x3; // binary 00000011 + U8 bits = 0; + msg->getU8Fast(block, field, bits, block_num); + mBits[PI_COPY] = bits & TWO_BITS; + bits >>= 2; + mBits[PI_MODIFY] = bits & TWO_BITS; + bits >>= 2; + mBits[PI_TRANSFER] = bits & TWO_BITS; +} + +const std::string AGGREGATE_VALUES[4] = + { + std::string( "Empty" ), + std::string( "None" ), + std::string( "Some" ), + std::string( "All" ) + }; + +std::ostream& operator<<(std::ostream &s, const LLAggregatePermissions &perm) +{ + s << "{PI_COPY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_COPY]]; + s << ", PI_MODIFY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_MODIFY]]; + s << ", PI_TRANSFER=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_TRANSFER]]; + s << "}"; + return s; +} + +// This converts a permissions mask into a string for debugging use. +void mask_to_string(U32 mask, char* str) +{ + if (mask & PERM_MOVE) + { + *str = 'V'; + } + else + { + *str = ' '; + } + str++; + + if (mask & PERM_MODIFY) + { + *str = 'M'; + } + else + { + *str = ' '; + } + str++; + + if (mask & PERM_COPY) + { + *str = 'C'; + } + else + { + *str = ' '; + } + str++; + + if (mask & PERM_TRANSFER) + { + *str = 'T'; + } + else + { + *str = ' '; + } + str++; + *str = '\0'; +} + +std::string mask_to_string(U32 mask) +{ + char str[16]; + mask_to_string(mask, str); + return std::string(str); +} + +///---------------------------------------------------------------------------- +/// exported functions +///---------------------------------------------------------------------------- +static const std::string PERM_CREATOR_ID_LABEL("creator_id"); +static const std::string PERM_OWNER_ID_LABEL("owner_id"); +static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id"); +static const std::string PERM_GROUP_ID_LABEL("group_id"); +static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group"); +static const std::string PERM_BASE_MASK_LABEL("base_mask"); +static const std::string PERM_OWNER_MASK_LABEL("owner_mask"); +static const std::string PERM_GROUP_MASK_LABEL("group_mask"); +static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask"); +static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask"); + +LLSD ll_create_sd_from_permissions(const LLPermissions& perm) +{ + LLSD rv; + rv[PERM_CREATOR_ID_LABEL] = perm.getCreator(); + rv[PERM_OWNER_ID_LABEL] = perm.getOwner(); + rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner(); + rv[PERM_GROUP_ID_LABEL] = perm.getGroup(); + rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned(); + rv[PERM_BASE_MASK_LABEL] = (S32)perm.getMaskBase(); + rv[PERM_OWNER_MASK_LABEL] = (S32)perm.getMaskOwner(); + rv[PERM_GROUP_MASK_LABEL] = (S32)perm.getMaskGroup(); + rv[PERM_EVERYONE_MASK_LABEL] = (S32)perm.getMaskEveryone(); + rv[PERM_NEXT_OWNER_MASK_LABEL] = (S32)perm.getMaskNextOwner(); + return rv; +} + +LLPermissions ll_permissions_from_sd(const LLSD& sd_perm) +{ + LLPermissions rv; + rv.init( + sd_perm[PERM_CREATOR_ID_LABEL].asUUID(), + sd_perm[PERM_OWNER_ID_LABEL].asUUID(), + sd_perm[PERM_LAST_OWNER_ID_LABEL].asUUID(), + sd_perm[PERM_GROUP_ID_LABEL].asUUID()); + + // We do a cast to U32 here since LLSD does not attempt to + // represent unsigned ints. + PermissionMask mask; + mask = (U32)(sd_perm[PERM_BASE_MASK_LABEL].asInteger()); + rv.setMaskBase(mask); + mask = (U32)(sd_perm[PERM_OWNER_MASK_LABEL].asInteger()); + rv.setMaskOwner(mask); + mask = (U32)(sd_perm[PERM_EVERYONE_MASK_LABEL].asInteger()); + rv.setMaskEveryone(mask); + mask = (U32)(sd_perm[PERM_GROUP_MASK_LABEL].asInteger()); + rv.setMaskGroup(mask); + mask = (U32)(sd_perm[PERM_NEXT_OWNER_MASK_LABEL].asInteger()); + rv.setMaskNext(mask); + rv.fix(); + return rv; +} diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index e4baf2ff68..dfe527f314 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -1,450 +1,450 @@ -/**
- * @file llpermissions.h
- * @brief Permissions structures for objects.
- *
- * $LicenseInfo:firstyear=2002&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$
- */
-
-#ifndef LL_LLPERMISSIONS_H
-#define LL_LLPERMISSIONS_H
-
-#include "llpermissionsflags.h"
-#include "llsd.h"
-#include "lluuid.h"
-#include "llxmlnode.h"
-#include "llinventorytype.h"
-
-// prototypes
-class LLMessageSystem;
-extern void mask_to_string(U32 mask, char* str);
-extern std::string mask_to_string(U32 mask);
-template<class T> class LLMetaClassT;
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLPermissions
-//
-// Class which encapsulates object and inventory permissions/ownership/etc.
-//
-// Permissions where originally a static state creator/owner and set
-// of cap bits. Since then, it has grown to include group information,
-// last owner, masks for different people. The implementation has been
-// chosen such that a uuid is stored for each current/past owner, and
-// a bitmask is stored for the base permissions, owner permissions,
-// group permissions, and everyone else permissions.
-//
-// The base permissions represent the most permissive state that the
-// permissions can possibly be in. Thus, if the base permissions do
-// not allow copying, no one can ever copy the object. The permissions
-// also maintain a tree-like hierarchy of permissions, thus, if we
-// (for sake of discussions) denote more permissive as '>', then this
-// is invariant:
-//
-// base mask >= owner mask >= group mask
-// >= everyone mask
-// >= next owner mask
-// NOTE: the group mask does not effect everyone or next, everyone
-// does not effect group or next, etc.
-//
-// It is considered a fair use right to move or delete any object you
-// own. Another fair use right is the ability to give away anything
-// which you cannot copy. One way to look at that is that if you have
-// a unique item, you can always give that one copy you have to
-// someone else.
-//
-// Most of the bitmask is easy to understand, PERM_COPY means you can
-// copy !PERM_TRANSFER means you cannot transfer, etc. Given that we
-// now track the concept of 'next owner' inside of the permissions
-// object, we can describe some new meta-meaning to the PERM_MODIFY
-// flag. PERM_MODIFY is usually meant to note if you can change an
-// item, but since we record next owner permissions, we can interpret
-// a no-modify object as 'you cannot modify this object and you cannot
-// make derivative works.' When evaluating functionality, and
-// comparisons against permissions, keep this concept in mind for
-// logical consistency.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLPermissions
-{
-private:
- LLUUID mCreator; // null if object created by system
- LLUUID mOwner; // null if object "unowned" (owned by system)
- LLUUID mLastOwner; // object's last owner
- LLUUID mGroup; // The group association
-
- PermissionMask mMaskBase; // initially permissive, progressively AND restricted by each owner
-
- PermissionMask mMaskOwner; // set by owner, applies to owner only, restricts lower permissions
- PermissionMask mMaskEveryone; // set by owner, applies to everyone else
-
- PermissionMask mMaskGroup; // set by owner, applies to group that is associated with permissions
-
- PermissionMask mMaskNextOwner; // set by owner, applied to base on transfer.
-
- // Usually set in the fixOwnership() method based on current uuid
- // values.
- bool mIsGroupOwned;
-
- // Correct for fair use - you can never take away the right to
- // move stuff you own, and you can never take away the right to
- // transfer something you cannot otherwise copy.
- void fixFairUse();
-
- // Fix internal consistency for group/agent ownership
- void fixOwnership();
-
-public:
- static const LLPermissions DEFAULT;
-
- LLPermissions(); // defaults to created by system
- //~LLPermissions();
-
- // base initialization code
- void init(const LLUUID& creator, const LLUUID& owner,
- const LLUUID& last_owner, const LLUUID& group);
- void initMasks(PermissionMask base, PermissionMask owner,
- PermissionMask everyone, PermissionMask group,
- PermissionMask next);
- // adjust permissions based on inventory type.
- void initMasks(LLInventoryType::EType type);
-
- //
- // ACCESSORS
- //
-
- // return the agent_id of the agent that created the item
- const LLUUID& getCreator() const { return mCreator; }
-
- // return the agent_id of the owner. returns LLUUID::null if group
- // owned or public (a really big group).
- const LLUUID& getOwner() const { return mOwner; }
-
- // return the group_id of the group associated with the
- // object.
- const LLUUID& getGroup() const { return mGroup; }
-
- // return the agent_id of the last agent owner. Only returns
- // LLUUID::null if there has never been a previous owner (*note: this is apparently not true, say for textures in inventory, it may return LLUUID::null even if there was a previous owner).
- const LLUUID& getLastOwner() const { return mLastOwner; }
-
- U32 getMaskBase() const { return mMaskBase; }
- U32 getMaskOwner() const { return mMaskOwner; }
- U32 getMaskGroup() const { return mMaskGroup; }
- U32 getMaskEveryone() const { return mMaskEveryone; }
- U32 getMaskNextOwner() const { return mMaskNextOwner; }
-
- // return true if the object has any owner
- bool isOwned() const { return (mOwner.notNull() || mIsGroupOwned); }
-
- // return true if group_id is owner.
- bool isGroupOwned() const { return mIsGroupOwned; }
-
- // This API returns true if the object is owned at all, and false
- // otherwise. If it is owned at all, owner id is filled with
- // either the owner id or the group id, and the is_group_owned
- // parameter is appropriately filled. The values of owner_id and
- // is_group_owned are not changed if the object is not owned.
- bool getOwnership(LLUUID& owner_id, bool& is_group_owned) const;
-
- // Gets the 'safe' owner. This should never return LLUUID::null.
- // If no group owned, return the agent owner id normally.
- // If group owned, return the group id.
- // If not owned, return a random uuid which should have no power.
- LLUUID getSafeOwner() const;
-
- // return a cheap crc
- U32 getCRC32() const;
-
-
- //
- // MANIPULATORS
- //
-
- // Fix hierarchy of permissions, applies appropriate permissions
- // at each level to ensure that base permissions are respected,
- // and also ensures that if base cannot transfer, then group and
- // other cannot copy.
- void fix();
-
- // All of these methods just do exactly what they say. There is no
- // permissions checking to see if the operation is allowed, and do
- // not fix the permissions hierarchy. So please only use these
- // methods when you are know what you're doing and coding on
- // behalf of the system - ie, acting as god.
- void set(const LLPermissions& permissions);
- void setMaskBase(U32 mask) { mMaskBase = mask; }
- void setMaskOwner(U32 mask) { mMaskOwner = mask; }
- void setMaskEveryone(U32 mask) { mMaskEveryone = mask;}
- void setMaskGroup(U32 mask) { mMaskGroup = mask;}
- void setMaskNext(U32 mask) { mMaskNextOwner = mask; }
-
- // Allow accumulation of permissions. Results in the tightest
- // permissions possible. In the case of clashing UUIDs, it sets
- // the ID to LLUUID::null.
- void accumulate(const LLPermissions& perm);
-
- //
- // CHECKED MANIPULATORS
- //
-
- // These functions return true on success. They return false if
- // the given agent isn't allowed to make the change. You can pass
- // LLUUID::null as the agent id if the change is being made by the
- // simulator itself, not on behalf of any agent - this will always
- // succeed. Passing in group id of LLUUID:null means no group, and
- // does not offer special permission to do anything.
-
- // saves last owner, sets current owner, and sets the group.
- // set is_atomic = true means that this permission represents
- // an atomic permission and not a collection of permissions.
- // Currently, the only way to have a collection is when an object
- // has inventory and is then itself rolled up into an inventory
- // item.
- bool setOwnerAndGroup(const LLUUID& agent, const LLUUID& owner, const LLUUID& group, bool is_atomic);
-
- // only call this if you know what you're doing
- // there are usually perm-bit consequences when the
- // ownerhsip changes
- void yesReallySetOwner(const LLUUID& owner, bool group_owned);
-
- // Last owner doesn't have much in the way of permissions so it's
- //not too dangerous to do this.
- void setLastOwner(const LLUUID& last_owner);
-
- // saves last owner, sets owner to uuid null, sets group
- // owned. group_id must be the group of the object (that's who it
- // is being deeded to) and the object must be group
- // modify. Technically, the agent id and group id are not
- // necessary, but I wanted this function to look like the other
- // checked manipulators (since that is how it is used.) If the
- // agent is the system or (group == mGroup and group modify and
- // owner transfer) then this function will deed the permissions,
- // set the next owner mask, and return true. Otherwise, no change
- // is effected, and the function returns false.
- bool deedToGroup(const LLUUID& agent, const LLUUID& group);
- // Attempt to set or clear the given bitmask. Returns true if you
- // are allowed to modify the permissions. If you attempt to turn
- // on bits not allowed by the base bits, the function will return
- // true, but those bits will not be set.
- bool setBaseBits( const LLUUID& agent, bool set, PermissionMask bits);
- bool setOwnerBits( const LLUUID& agent, bool set, PermissionMask bits);
- bool setGroupBits( const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits);
- bool setEveryoneBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits);
- bool setNextOwnerBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits);
-
- // This is currently only used in the Viewer to handle calling cards
- // where the creator is actually used to store the target. Use with care.
- void setCreator(const LLUUID& creator) { mCreator = creator; }
-
- //
- // METHODS
- //
-
- // All the allow* functions return true if the given agent or
- // group can perform the function. Prefer using this set of
- // operations to check permissions on an object. These return
- // true if the given agent or group can perform the function.
- // They also return true if the object isn't owned, or the
- // requesting agent is a system agent. See llpermissionsflags.h
- // for bits.
- bool allowOperationBy(PermissionBit op, const LLUUID& agent, const LLUUID& group = LLUUID::null) const;
-
- inline bool allowModifyBy(const LLUUID &agent_id) const;
- inline bool allowCopyBy(const LLUUID& agent_id) const;
- inline bool allowMoveBy(const LLUUID& agent_id) const;
- inline bool allowModifyBy(const LLUUID &agent_id, const LLUUID& group) const;
- inline bool allowCopyBy(const LLUUID& agent_id, const LLUUID& group) const;
- inline bool allowMoveBy(const LLUUID &agent_id, const LLUUID &group) const;
-
- // This somewhat specialized function is meant for testing if the
- // current owner is allowed to transfer to the specified agent id.
- inline bool allowTransferTo(const LLUUID &agent_id) const;
-
- //
- // DEPRECATED.
- //
- // These return true if the given agent can perform the function.
- // They also return true if the object isn't owned, or the
- // requesting agent is a system agent. See llpermissionsflags.h
- // for bits.
- //bool allowDeleteBy(const LLUUID& agent_id) const { return allowModifyBy(agent_id); }
- //bool allowEditBy(const LLUUID& agent_id) const { return allowModifyBy(agent_id); }
- // saves last owner and sets current owner
- //bool setOwner(const LLUUID& agent, const LLUUID& owner);
- // This method saves the last owner, sets the current owner to the
- // one provided, and sets the base mask as indicated.
- //bool setOwner(const LLUUID& agent, const LLUUID& owner, U32 new_base_mask);
-
- // Attempt to set or clear the given bitmask. Returns true if you
- // are allowed to modify the permissions. If you attempt to turn
- // on bits not allowed by the base bits, the function will return
- // true, but those bits will not be set.
- //bool setGroupBits( const LLUUID& agent, bool set, PermissionMask bits);
- //bool setEveryoneBits(const LLUUID& agent, bool set, PermissionMask bits);
-
- //
- // MISC METHODS and OPERATORS
- //
-
- LLSD packMessage() const;
- void unpackMessage(LLSD perms);
-
- // For messaging system support
- void packMessage(LLMessageSystem* msg) const;
- void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0);
-
- bool importLegacyStream(std::istream& input_stream);
- bool exportLegacyStream(std::ostream& output_stream) const;
-
- bool operator==(const LLPermissions &rhs) const;
- bool operator!=(const LLPermissions &rhs) const;
-
- friend std::ostream& operator<<(std::ostream &s, const LLPermissions &perm);
-
-};
-
-// Inlines
-bool LLPermissions::allowModifyBy(const LLUUID& agent, const LLUUID& group) const
-{
- return allowOperationBy(PERM_MODIFY, agent, group);
-}
-
-bool LLPermissions::allowCopyBy(const LLUUID& agent, const LLUUID& group) const
-{
- return allowOperationBy(PERM_COPY, agent, group);
-}
-
-
-bool LLPermissions::allowMoveBy(const LLUUID& agent, const LLUUID& group) const
-{
- return allowOperationBy(PERM_MOVE, agent, group);
-}
-
-bool LLPermissions::allowModifyBy(const LLUUID& agent) const
-{
- return allowOperationBy(PERM_MODIFY, agent, LLUUID::null);
-}
-
-bool LLPermissions::allowCopyBy(const LLUUID& agent) const
-{
- return allowOperationBy(PERM_COPY, agent, LLUUID::null);
-}
-
-bool LLPermissions::allowMoveBy(const LLUUID& agent) const
-{
- return allowOperationBy(PERM_MOVE, agent, LLUUID::null);
-}
-
-bool LLPermissions::allowTransferTo(const LLUUID &agent_id) const
-{
- if (mIsGroupOwned)
- {
- return allowOperationBy(PERM_TRANSFER, mGroup, mGroup);
- }
- else
- {
- return ((mOwner == agent_id) ? true : allowOperationBy(PERM_TRANSFER, mOwner));
- }
-}
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLAggregatePermissions
-//
-// Class which encapsulates object and inventory permissions,
-// ownership, etc. Currently, it only aggregates PERM_COPY,
-// PERM_MODIFY, and PERM_TRANSFER.
-//
-// Usually you will construct an instance and hand the object several
-// permissions masks to aggregate the copy, modify, and
-// transferability into a nice trinary value.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLAggregatePermissions
-{
-public:
- enum EValue
- {
- AP_EMPTY = 0x00,
- AP_NONE = 0x01,
- AP_SOME = 0x02,
- AP_ALL = 0x03
- };
-
- // construct an empty aggregate permissions
- LLAggregatePermissions();
-
- // pass in a PERM_COPY, PERM_TRANSFER, etc, and get out a EValue
- // enumeration describing the current aggregate permissions.
- EValue getValue(PermissionBit bit) const;
-
- // returns the permissions packed into the 6 LSB of a U8:
- // 00TTMMCC
- // where TT = transfer, MM = modify, and CC = copy
- // LSB is to the right
- U8 getU8() const;
-
- // return true is the aggregate permissions are empty, otherwise false.
- bool isEmpty() const ;
-
- // pass in a PERM_COPY, PERM_TRANSFER, etc, and an EValue
- // enumeration to specifically set that value. Not implemented
- // because I'm not sure it's a useful api.
- //void setValue(PermissionBit bit, EValue);
-
- // Given a mask, aggregate the useful permissions.
- void aggregate(PermissionMask mask);
-
- // Aggregate aggregates
- void aggregate(const LLAggregatePermissions& ag);
-
- // message handling
- void packMessage(LLMessageSystem* msg, const char* field) const;
- void unpackMessage(LLMessageSystem* msg, const char* block, const char *field, S32 block_num = 0);
-
- static const LLAggregatePermissions empty;
-
- friend std::ostream& operator<<(std::ostream &s, const LLAggregatePermissions &perm);
-
-protected:
- enum EPermIndex
- {
- PI_COPY = 0,
- PI_MODIFY = 1,
- PI_TRANSFER = 2,
- PI_END = 3,
- PI_COUNT = 3
- };
- void aggregateBit(EPermIndex idx, bool allowed);
- void aggregateIndex(EPermIndex idx, U8 bits);
- static EPermIndex perm2PermIndex(PermissionBit bit);
-
- // structure used to store the aggregate so far.
- U8 mBits[PI_COUNT];
-};
-
-// These functions convert between structured data and permissions as
-// appropriate for serialization. The permissions are a map of things
-// like 'creator_id', 'owner_id', etc, with the value copied from the
-// permission object.
-LLSD ll_create_sd_from_permissions(const LLPermissions& perm);
-LLPermissions ll_permissions_from_sd(const LLSD& sd_perm);
-
-#endif
+/** + * @file llpermissions.h + * @brief Permissions structures for objects. + * + * $LicenseInfo:firstyear=2002&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$ + */ + +#ifndef LL_LLPERMISSIONS_H +#define LL_LLPERMISSIONS_H + +#include "llpermissionsflags.h" +#include "llsd.h" +#include "lluuid.h" +#include "llxmlnode.h" +#include "llinventorytype.h" + +// prototypes +class LLMessageSystem; +extern void mask_to_string(U32 mask, char* str); +extern std::string mask_to_string(U32 mask); +template<class T> class LLMetaClassT; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLPermissions +// +// Class which encapsulates object and inventory permissions/ownership/etc. +// +// Permissions where originally a static state creator/owner and set +// of cap bits. Since then, it has grown to include group information, +// last owner, masks for different people. The implementation has been +// chosen such that a uuid is stored for each current/past owner, and +// a bitmask is stored for the base permissions, owner permissions, +// group permissions, and everyone else permissions. +// +// The base permissions represent the most permissive state that the +// permissions can possibly be in. Thus, if the base permissions do +// not allow copying, no one can ever copy the object. The permissions +// also maintain a tree-like hierarchy of permissions, thus, if we +// (for sake of discussions) denote more permissive as '>', then this +// is invariant: +// +// base mask >= owner mask >= group mask +// >= everyone mask +// >= next owner mask +// NOTE: the group mask does not effect everyone or next, everyone +// does not effect group or next, etc. +// +// It is considered a fair use right to move or delete any object you +// own. Another fair use right is the ability to give away anything +// which you cannot copy. One way to look at that is that if you have +// a unique item, you can always give that one copy you have to +// someone else. +// +// Most of the bitmask is easy to understand, PERM_COPY means you can +// copy !PERM_TRANSFER means you cannot transfer, etc. Given that we +// now track the concept of 'next owner' inside of the permissions +// object, we can describe some new meta-meaning to the PERM_MODIFY +// flag. PERM_MODIFY is usually meant to note if you can change an +// item, but since we record next owner permissions, we can interpret +// a no-modify object as 'you cannot modify this object and you cannot +// make derivative works.' When evaluating functionality, and +// comparisons against permissions, keep this concept in mind for +// logical consistency. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLPermissions +{ +private: + LLUUID mCreator; // null if object created by system + LLUUID mOwner; // null if object "unowned" (owned by system) + LLUUID mLastOwner; // object's last owner + LLUUID mGroup; // The group association + + PermissionMask mMaskBase; // initially permissive, progressively AND restricted by each owner + + PermissionMask mMaskOwner; // set by owner, applies to owner only, restricts lower permissions + PermissionMask mMaskEveryone; // set by owner, applies to everyone else + + PermissionMask mMaskGroup; // set by owner, applies to group that is associated with permissions + + PermissionMask mMaskNextOwner; // set by owner, applied to base on transfer. + + // Usually set in the fixOwnership() method based on current uuid + // values. + bool mIsGroupOwned; + + // Correct for fair use - you can never take away the right to + // move stuff you own, and you can never take away the right to + // transfer something you cannot otherwise copy. + void fixFairUse(); + + // Fix internal consistency for group/agent ownership + void fixOwnership(); + +public: + static const LLPermissions DEFAULT; + + LLPermissions(); // defaults to created by system + //~LLPermissions(); + + // base initialization code + void init(const LLUUID& creator, const LLUUID& owner, + const LLUUID& last_owner, const LLUUID& group); + void initMasks(PermissionMask base, PermissionMask owner, + PermissionMask everyone, PermissionMask group, + PermissionMask next); + // adjust permissions based on inventory type. + void initMasks(LLInventoryType::EType type); + + // + // ACCESSORS + // + + // return the agent_id of the agent that created the item + const LLUUID& getCreator() const { return mCreator; } + + // return the agent_id of the owner. returns LLUUID::null if group + // owned or public (a really big group). + const LLUUID& getOwner() const { return mOwner; } + + // return the group_id of the group associated with the + // object. + const LLUUID& getGroup() const { return mGroup; } + + // return the agent_id of the last agent owner. Only returns + // LLUUID::null if there has never been a previous owner (*note: this is apparently not true, say for textures in inventory, it may return LLUUID::null even if there was a previous owner). + const LLUUID& getLastOwner() const { return mLastOwner; } + + U32 getMaskBase() const { return mMaskBase; } + U32 getMaskOwner() const { return mMaskOwner; } + U32 getMaskGroup() const { return mMaskGroup; } + U32 getMaskEveryone() const { return mMaskEveryone; } + U32 getMaskNextOwner() const { return mMaskNextOwner; } + + // return true if the object has any owner + bool isOwned() const { return (mOwner.notNull() || mIsGroupOwned); } + + // return true if group_id is owner. + bool isGroupOwned() const { return mIsGroupOwned; } + + // This API returns true if the object is owned at all, and false + // otherwise. If it is owned at all, owner id is filled with + // either the owner id or the group id, and the is_group_owned + // parameter is appropriately filled. The values of owner_id and + // is_group_owned are not changed if the object is not owned. + bool getOwnership(LLUUID& owner_id, bool& is_group_owned) const; + + // Gets the 'safe' owner. This should never return LLUUID::null. + // If no group owned, return the agent owner id normally. + // If group owned, return the group id. + // If not owned, return a random uuid which should have no power. + LLUUID getSafeOwner() const; + + // return a cheap crc + U32 getCRC32() const; + + + // + // MANIPULATORS + // + + // Fix hierarchy of permissions, applies appropriate permissions + // at each level to ensure that base permissions are respected, + // and also ensures that if base cannot transfer, then group and + // other cannot copy. + void fix(); + + // All of these methods just do exactly what they say. There is no + // permissions checking to see if the operation is allowed, and do + // not fix the permissions hierarchy. So please only use these + // methods when you are know what you're doing and coding on + // behalf of the system - ie, acting as god. + void set(const LLPermissions& permissions); + void setMaskBase(U32 mask) { mMaskBase = mask; } + void setMaskOwner(U32 mask) { mMaskOwner = mask; } + void setMaskEveryone(U32 mask) { mMaskEveryone = mask;} + void setMaskGroup(U32 mask) { mMaskGroup = mask;} + void setMaskNext(U32 mask) { mMaskNextOwner = mask; } + + // Allow accumulation of permissions. Results in the tightest + // permissions possible. In the case of clashing UUIDs, it sets + // the ID to LLUUID::null. + void accumulate(const LLPermissions& perm); + + // + // CHECKED MANIPULATORS + // + + // These functions return true on success. They return false if + // the given agent isn't allowed to make the change. You can pass + // LLUUID::null as the agent id if the change is being made by the + // simulator itself, not on behalf of any agent - this will always + // succeed. Passing in group id of LLUUID:null means no group, and + // does not offer special permission to do anything. + + // saves last owner, sets current owner, and sets the group. + // set is_atomic = true means that this permission represents + // an atomic permission and not a collection of permissions. + // Currently, the only way to have a collection is when an object + // has inventory and is then itself rolled up into an inventory + // item. + bool setOwnerAndGroup(const LLUUID& agent, const LLUUID& owner, const LLUUID& group, bool is_atomic); + + // only call this if you know what you're doing + // there are usually perm-bit consequences when the + // ownerhsip changes + void yesReallySetOwner(const LLUUID& owner, bool group_owned); + + // Last owner doesn't have much in the way of permissions so it's + //not too dangerous to do this. + void setLastOwner(const LLUUID& last_owner); + + // saves last owner, sets owner to uuid null, sets group + // owned. group_id must be the group of the object (that's who it + // is being deeded to) and the object must be group + // modify. Technically, the agent id and group id are not + // necessary, but I wanted this function to look like the other + // checked manipulators (since that is how it is used.) If the + // agent is the system or (group == mGroup and group modify and + // owner transfer) then this function will deed the permissions, + // set the next owner mask, and return true. Otherwise, no change + // is effected, and the function returns false. + bool deedToGroup(const LLUUID& agent, const LLUUID& group); + // Attempt to set or clear the given bitmask. Returns true if you + // are allowed to modify the permissions. If you attempt to turn + // on bits not allowed by the base bits, the function will return + // true, but those bits will not be set. + bool setBaseBits( const LLUUID& agent, bool set, PermissionMask bits); + bool setOwnerBits( const LLUUID& agent, bool set, PermissionMask bits); + bool setGroupBits( const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits); + bool setEveryoneBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits); + bool setNextOwnerBits(const LLUUID& agent, const LLUUID& group, bool set, PermissionMask bits); + + // This is currently only used in the Viewer to handle calling cards + // where the creator is actually used to store the target. Use with care. + void setCreator(const LLUUID& creator) { mCreator = creator; } + + // + // METHODS + // + + // All the allow* functions return true if the given agent or + // group can perform the function. Prefer using this set of + // operations to check permissions on an object. These return + // true if the given agent or group can perform the function. + // They also return true if the object isn't owned, or the + // requesting agent is a system agent. See llpermissionsflags.h + // for bits. + bool allowOperationBy(PermissionBit op, const LLUUID& agent, const LLUUID& group = LLUUID::null) const; + + inline bool allowModifyBy(const LLUUID &agent_id) const; + inline bool allowCopyBy(const LLUUID& agent_id) const; + inline bool allowMoveBy(const LLUUID& agent_id) const; + inline bool allowModifyBy(const LLUUID &agent_id, const LLUUID& group) const; + inline bool allowCopyBy(const LLUUID& agent_id, const LLUUID& group) const; + inline bool allowMoveBy(const LLUUID &agent_id, const LLUUID &group) const; + + // This somewhat specialized function is meant for testing if the + // current owner is allowed to transfer to the specified agent id. + inline bool allowTransferTo(const LLUUID &agent_id) const; + + // + // DEPRECATED. + // + // These return true if the given agent can perform the function. + // They also return true if the object isn't owned, or the + // requesting agent is a system agent. See llpermissionsflags.h + // for bits. + //bool allowDeleteBy(const LLUUID& agent_id) const { return allowModifyBy(agent_id); } + //bool allowEditBy(const LLUUID& agent_id) const { return allowModifyBy(agent_id); } + // saves last owner and sets current owner + //bool setOwner(const LLUUID& agent, const LLUUID& owner); + // This method saves the last owner, sets the current owner to the + // one provided, and sets the base mask as indicated. + //bool setOwner(const LLUUID& agent, const LLUUID& owner, U32 new_base_mask); + + // Attempt to set or clear the given bitmask. Returns true if you + // are allowed to modify the permissions. If you attempt to turn + // on bits not allowed by the base bits, the function will return + // true, but those bits will not be set. + //bool setGroupBits( const LLUUID& agent, bool set, PermissionMask bits); + //bool setEveryoneBits(const LLUUID& agent, bool set, PermissionMask bits); + + // + // MISC METHODS and OPERATORS + // + + LLSD packMessage() const; + void unpackMessage(LLSD perms); + + // For messaging system support + void packMessage(LLMessageSystem* msg) const; + void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); + + bool importLegacyStream(std::istream& input_stream); + bool exportLegacyStream(std::ostream& output_stream) const; + + bool operator==(const LLPermissions &rhs) const; + bool operator!=(const LLPermissions &rhs) const; + + friend std::ostream& operator<<(std::ostream &s, const LLPermissions &perm); + +}; + +// Inlines +bool LLPermissions::allowModifyBy(const LLUUID& agent, const LLUUID& group) const +{ + return allowOperationBy(PERM_MODIFY, agent, group); +} + +bool LLPermissions::allowCopyBy(const LLUUID& agent, const LLUUID& group) const +{ + return allowOperationBy(PERM_COPY, agent, group); +} + + +bool LLPermissions::allowMoveBy(const LLUUID& agent, const LLUUID& group) const +{ + return allowOperationBy(PERM_MOVE, agent, group); +} + +bool LLPermissions::allowModifyBy(const LLUUID& agent) const +{ + return allowOperationBy(PERM_MODIFY, agent, LLUUID::null); +} + +bool LLPermissions::allowCopyBy(const LLUUID& agent) const +{ + return allowOperationBy(PERM_COPY, agent, LLUUID::null); +} + +bool LLPermissions::allowMoveBy(const LLUUID& agent) const +{ + return allowOperationBy(PERM_MOVE, agent, LLUUID::null); +} + +bool LLPermissions::allowTransferTo(const LLUUID &agent_id) const +{ + if (mIsGroupOwned) + { + return allowOperationBy(PERM_TRANSFER, mGroup, mGroup); + } + else + { + return ((mOwner == agent_id) ? true : allowOperationBy(PERM_TRANSFER, mOwner)); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLAggregatePermissions +// +// Class which encapsulates object and inventory permissions, +// ownership, etc. Currently, it only aggregates PERM_COPY, +// PERM_MODIFY, and PERM_TRANSFER. +// +// Usually you will construct an instance and hand the object several +// permissions masks to aggregate the copy, modify, and +// transferability into a nice trinary value. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLAggregatePermissions +{ +public: + enum EValue + { + AP_EMPTY = 0x00, + AP_NONE = 0x01, + AP_SOME = 0x02, + AP_ALL = 0x03 + }; + + // construct an empty aggregate permissions + LLAggregatePermissions(); + + // pass in a PERM_COPY, PERM_TRANSFER, etc, and get out a EValue + // enumeration describing the current aggregate permissions. + EValue getValue(PermissionBit bit) const; + + // returns the permissions packed into the 6 LSB of a U8: + // 00TTMMCC + // where TT = transfer, MM = modify, and CC = copy + // LSB is to the right + U8 getU8() const; + + // return true is the aggregate permissions are empty, otherwise false. + bool isEmpty() const ; + + // pass in a PERM_COPY, PERM_TRANSFER, etc, and an EValue + // enumeration to specifically set that value. Not implemented + // because I'm not sure it's a useful api. + //void setValue(PermissionBit bit, EValue); + + // Given a mask, aggregate the useful permissions. + void aggregate(PermissionMask mask); + + // Aggregate aggregates + void aggregate(const LLAggregatePermissions& ag); + + // message handling + void packMessage(LLMessageSystem* msg, const char* field) const; + void unpackMessage(LLMessageSystem* msg, const char* block, const char *field, S32 block_num = 0); + + static const LLAggregatePermissions empty; + + friend std::ostream& operator<<(std::ostream &s, const LLAggregatePermissions &perm); + +protected: + enum EPermIndex + { + PI_COPY = 0, + PI_MODIFY = 1, + PI_TRANSFER = 2, + PI_END = 3, + PI_COUNT = 3 + }; + void aggregateBit(EPermIndex idx, bool allowed); + void aggregateIndex(EPermIndex idx, U8 bits); + static EPermIndex perm2PermIndex(PermissionBit bit); + + // structure used to store the aggregate so far. + U8 mBits[PI_COUNT]; +}; + +// These functions convert between structured data and permissions as +// appropriate for serialization. The permissions are a map of things +// like 'creator_id', 'owner_id', etc, with the value copied from the +// permission object. +LLSD ll_create_sd_from_permissions(const LLPermissions& perm); +LLPermissions ll_permissions_from_sd(const LLSD& sd_perm); + +#endif diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index 7bf14bc0d4..98836b178e 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -1,315 +1,315 @@ -/**
- * @file llsaleinfo.cpp
- * @brief
- *
- * $LicenseInfo:firstyear=2002&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 <iostream>
-#include "linden_common.h"
-
-#include "llsaleinfo.h"
-
-#include "llerror.h"
-#include "message.h"
-#include "llsdutil.h"
-
-// use this to avoid temporary object creation
-const LLSaleInfo LLSaleInfo::DEFAULT;
-
-///----------------------------------------------------------------------------
-/// Local function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-
-const char* FOR_SALE_NAMES[] =
-{
- "not",
- "orig",
- "copy",
- "cntn"
-};
-
-///----------------------------------------------------------------------------
-/// Class llsaleinfo
-///----------------------------------------------------------------------------
-
-// Default constructor
-LLSaleInfo::LLSaleInfo() :
- mSaleType(LLSaleInfo::FS_NOT),
- mSalePrice(DEFAULT_PRICE)
-{
-}
-
-LLSaleInfo::LLSaleInfo(EForSale sale_type, S32 sale_price) :
- mSaleType(sale_type),
- mSalePrice(sale_price)
-{
- mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
-}
-
-bool LLSaleInfo::isForSale() const
-{
- return (FS_NOT != mSaleType);
-}
-
-U32 LLSaleInfo::getCRC32() const
-{
- U32 rv = (U32)mSalePrice;
- rv += (mSaleType * 0x07073096);
- return rv;
-}
-
-bool LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
-{
- output_stream << "\tsale_info\t0\n\t{\n";
- output_stream << "\t\tsale_type\t" << lookup(mSaleType) << "\n";
- output_stream << "\t\tsale_price\t" << mSalePrice << "\n";
- output_stream <<"\t}\n";
- return true;
-}
-
-LLSD LLSaleInfo::asLLSD() const
-{
- LLSD sd = LLSD();
- sd["sale_type"] = lookup(mSaleType);
- sd["sale_price"] = mSalePrice;
- return sd;
-}
-
-bool LLSaleInfo::fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask)
-{
- const char *w;
-
- 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))
- {
- has_perm_mask = true;
- perm_mask = ll_U32_from_sd(sd[w]);
- }
- return true;
-}
-
-bool LLSaleInfo::importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask)
-{
- has_perm_mask = false;
-
- // *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 */
- bool success = true;
-
- keyword[0] = '\0';
- valuestr[0] = '\0';
- while(success && input_stream.good())
- {
- input_stream.getline(buffer, MAX_STRING);
- sscanf( /* Flawfinder: ignore */
- buffer,
- " %254s %254s",
- keyword, valuestr);
- if(!keyword[0])
- {
- continue;
- }
- if(0 == strcmp("{",keyword))
- {
- continue;
- }
- if(0 == strcmp("}", keyword))
- {
- break;
- }
- else if(0 == strcmp("sale_type", keyword))
- {
- mSaleType = lookup(valuestr);
- }
- else if(0 == strcmp("sale_price", keyword))
- {
- sscanf(valuestr, "%d", &mSalePrice);
- mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
- }
- else if (!strcmp("perm_mask", keyword))
- {
- //LL_INFOS() << "found deprecated keyword perm_mask" << LL_ENDL;
- has_perm_mask = true;
- sscanf(valuestr, "%x", &perm_mask);
- }
- else
- {
- LL_WARNS() << "unknown keyword '" << keyword
- << "' in sale info import" << LL_ENDL;
- }
- }
- return success;
-}
-
-void LLSaleInfo::setSalePrice(S32 price)
-{
- mSalePrice = price;
- mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
-}
-
-LLSD LLSaleInfo::packMessage() const
-{
- LLSD result;
-
- U8 sale_type = static_cast<U8>(mSaleType);
- result["sale-type"] = (U8)sale_type;
- result["sale-price"] = (S32)mSalePrice;
- //result[_PREHASH_NextOwnerMask] = mNextOwnerPermMask;
- return result;
-}
-
-void LLSaleInfo::packMessage(LLMessageSystem* msg) const
-{
- U8 sale_type = static_cast<U8>(mSaleType);
- msg->addU8Fast(_PREHASH_SaleType, sale_type);
- msg->addS32Fast(_PREHASH_SalePrice, mSalePrice);
- //msg->addU32Fast(_PREHASH_NextOwnerMask, mNextOwnerPermMask);
-}
-
-void LLSaleInfo::unpackMessage(LLSD sales)
-{
- U8 sale_type = (U8)sales["sale-type"].asInteger();
- mSaleType = static_cast<EForSale>(sale_type);
-
- mSalePrice = (S32)sales["sale-price"].asInteger();
- mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
- //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask);
-}
-
-void LLSaleInfo::unpackMessage(LLMessageSystem* msg, const char* block)
-{
- U8 sale_type;
- msg->getU8Fast(block, _PREHASH_SaleType, sale_type);
- mSaleType = static_cast<EForSale>(sale_type);
- msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice);
- mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
- //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask);
-}
-
-void LLSaleInfo::unpackMultiMessage(LLMessageSystem* msg, const char* block,
- S32 block_num)
-{
- U8 sale_type;
- msg->getU8Fast(block, _PREHASH_SaleType, sale_type, block_num);
- mSaleType = static_cast<EForSale>(sale_type);
- msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice, block_num);
- mSalePrice = llclamp(mSalePrice, 0, S32_MAX);
- //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask, block_num);
-}
-
-LLSaleInfo::EForSale LLSaleInfo::lookup(const char* name)
-{
- for(S32 i = 0; i < FS_COUNT; i++)
- {
- if(0 == strcmp(name, FOR_SALE_NAMES[i]))
- {
- // match
- return (EForSale)i;
- }
- }
- return FS_NOT;
-}
-
-const char* LLSaleInfo::lookup(EForSale type)
-{
- if((type >= 0) && (type < FS_COUNT))
- {
- return FOR_SALE_NAMES[S32(type)];
- }
- else
- {
- return NULL;
- }
-}
-
-// Allow accumulation of sale info. The price of each is added,
-// conflict in sale type results in FS_NOT, and the permissions are
-// tightened.
-void LLSaleInfo::accumulate(const LLSaleInfo& sale_info)
-{
- if(mSaleType != sale_info.mSaleType)
- {
- mSaleType = FS_NOT;
- }
- mSalePrice += sale_info.mSalePrice;
- //mNextOwnerPermMask &= sale_info.mNextOwnerPermMask;
-}
-
-bool LLSaleInfo::operator==(const LLSaleInfo &rhs) const
-{
- return (
- (mSaleType == rhs.mSaleType) &&
- (mSalePrice == rhs.mSalePrice)
- );
-}
-
-bool LLSaleInfo::operator!=(const LLSaleInfo &rhs) const
-{
- return (
- (mSaleType != rhs.mSaleType) ||
- (mSalePrice != rhs.mSalePrice)
- );
-}
-
-
-///----------------------------------------------------------------------------
-/// Local function definitions
-///----------------------------------------------------------------------------
-
-///----------------------------------------------------------------------------
-/// exported functions
-///----------------------------------------------------------------------------
-static const std::string ST_TYPE_LABEL("sale_type");
-static const std::string ST_PRICE_LABEL("sale_price");
-
-LLSD ll_create_sd_from_sale_info(const LLSaleInfo& sale)
-{
- LLSD rv;
- const char* type = LLSaleInfo::lookup(sale.getSaleType());
- if(!type) type = LLSaleInfo::lookup(LLSaleInfo::FS_NOT);
- rv[ST_TYPE_LABEL] = type;
- rv[ST_PRICE_LABEL] = sale.getSalePrice();
- return rv;
-}
-
-LLSaleInfo ll_sale_info_from_sd(const LLSD& sd)
-{
- LLSaleInfo rv;
- rv.setSaleType(LLSaleInfo::lookup(sd[ST_TYPE_LABEL].asString().c_str()));
- rv.setSalePrice(llclamp((S32)sd[ST_PRICE_LABEL], 0, S32_MAX));
- return rv;
-}
+/** + * @file llsaleinfo.cpp + * @brief + * + * $LicenseInfo:firstyear=2002&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 <iostream> +#include "linden_common.h" + +#include "llsaleinfo.h" + +#include "llerror.h" +#include "message.h" +#include "llsdutil.h" + +// use this to avoid temporary object creation +const LLSaleInfo LLSaleInfo::DEFAULT; + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +const char* FOR_SALE_NAMES[] = +{ + "not", + "orig", + "copy", + "cntn" +}; + +///---------------------------------------------------------------------------- +/// Class llsaleinfo +///---------------------------------------------------------------------------- + +// Default constructor +LLSaleInfo::LLSaleInfo() : + mSaleType(LLSaleInfo::FS_NOT), + mSalePrice(DEFAULT_PRICE) +{ +} + +LLSaleInfo::LLSaleInfo(EForSale sale_type, S32 sale_price) : + mSaleType(sale_type), + mSalePrice(sale_price) +{ + mSalePrice = llclamp(mSalePrice, 0, S32_MAX); +} + +bool LLSaleInfo::isForSale() const +{ + return (FS_NOT != mSaleType); +} + +U32 LLSaleInfo::getCRC32() const +{ + U32 rv = (U32)mSalePrice; + rv += (mSaleType * 0x07073096); + return rv; +} + +bool LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const +{ + output_stream << "\tsale_info\t0\n\t{\n"; + output_stream << "\t\tsale_type\t" << lookup(mSaleType) << "\n"; + output_stream << "\t\tsale_price\t" << mSalePrice << "\n"; + output_stream <<"\t}\n"; + return true; +} + +LLSD LLSaleInfo::asLLSD() const +{ + LLSD sd = LLSD(); + sd["sale_type"] = lookup(mSaleType); + sd["sale_price"] = mSalePrice; + return sd; +} + +bool LLSaleInfo::fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask) +{ + const char *w; + + 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)) + { + has_perm_mask = true; + perm_mask = ll_U32_from_sd(sd[w]); + } + return true; +} + +bool LLSaleInfo::importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask) +{ + has_perm_mask = false; + + // *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 */ + bool success = true; + + keyword[0] = '\0'; + valuestr[0] = '\0'; + while(success && input_stream.good()) + { + input_stream.getline(buffer, MAX_STRING); + sscanf( /* Flawfinder: ignore */ + buffer, + " %254s %254s", + keyword, valuestr); + if(!keyword[0]) + { + continue; + } + if(0 == strcmp("{",keyword)) + { + continue; + } + if(0 == strcmp("}", keyword)) + { + break; + } + else if(0 == strcmp("sale_type", keyword)) + { + mSaleType = lookup(valuestr); + } + else if(0 == strcmp("sale_price", keyword)) + { + sscanf(valuestr, "%d", &mSalePrice); + mSalePrice = llclamp(mSalePrice, 0, S32_MAX); + } + else if (!strcmp("perm_mask", keyword)) + { + //LL_INFOS() << "found deprecated keyword perm_mask" << LL_ENDL; + has_perm_mask = true; + sscanf(valuestr, "%x", &perm_mask); + } + else + { + LL_WARNS() << "unknown keyword '" << keyword + << "' in sale info import" << LL_ENDL; + } + } + return success; +} + +void LLSaleInfo::setSalePrice(S32 price) +{ + mSalePrice = price; + mSalePrice = llclamp(mSalePrice, 0, S32_MAX); +} + +LLSD LLSaleInfo::packMessage() const +{ + LLSD result; + + U8 sale_type = static_cast<U8>(mSaleType); + result["sale-type"] = (U8)sale_type; + result["sale-price"] = (S32)mSalePrice; + //result[_PREHASH_NextOwnerMask] = mNextOwnerPermMask; + return result; +} + +void LLSaleInfo::packMessage(LLMessageSystem* msg) const +{ + U8 sale_type = static_cast<U8>(mSaleType); + msg->addU8Fast(_PREHASH_SaleType, sale_type); + msg->addS32Fast(_PREHASH_SalePrice, mSalePrice); + //msg->addU32Fast(_PREHASH_NextOwnerMask, mNextOwnerPermMask); +} + +void LLSaleInfo::unpackMessage(LLSD sales) +{ + U8 sale_type = (U8)sales["sale-type"].asInteger(); + mSaleType = static_cast<EForSale>(sale_type); + + mSalePrice = (S32)sales["sale-price"].asInteger(); + mSalePrice = llclamp(mSalePrice, 0, S32_MAX); + //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask); +} + +void LLSaleInfo::unpackMessage(LLMessageSystem* msg, const char* block) +{ + U8 sale_type; + msg->getU8Fast(block, _PREHASH_SaleType, sale_type); + mSaleType = static_cast<EForSale>(sale_type); + msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice); + mSalePrice = llclamp(mSalePrice, 0, S32_MAX); + //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask); +} + +void LLSaleInfo::unpackMultiMessage(LLMessageSystem* msg, const char* block, + S32 block_num) +{ + U8 sale_type; + msg->getU8Fast(block, _PREHASH_SaleType, sale_type, block_num); + mSaleType = static_cast<EForSale>(sale_type); + msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice, block_num); + mSalePrice = llclamp(mSalePrice, 0, S32_MAX); + //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask, block_num); +} + +LLSaleInfo::EForSale LLSaleInfo::lookup(const char* name) +{ + for(S32 i = 0; i < FS_COUNT; i++) + { + if(0 == strcmp(name, FOR_SALE_NAMES[i])) + { + // match + return (EForSale)i; + } + } + return FS_NOT; +} + +const char* LLSaleInfo::lookup(EForSale type) +{ + if((type >= 0) && (type < FS_COUNT)) + { + return FOR_SALE_NAMES[S32(type)]; + } + else + { + return NULL; + } +} + +// Allow accumulation of sale info. The price of each is added, +// conflict in sale type results in FS_NOT, and the permissions are +// tightened. +void LLSaleInfo::accumulate(const LLSaleInfo& sale_info) +{ + if(mSaleType != sale_info.mSaleType) + { + mSaleType = FS_NOT; + } + mSalePrice += sale_info.mSalePrice; + //mNextOwnerPermMask &= sale_info.mNextOwnerPermMask; +} + +bool LLSaleInfo::operator==(const LLSaleInfo &rhs) const +{ + return ( + (mSaleType == rhs.mSaleType) && + (mSalePrice == rhs.mSalePrice) + ); +} + +bool LLSaleInfo::operator!=(const LLSaleInfo &rhs) const +{ + return ( + (mSaleType != rhs.mSaleType) || + (mSalePrice != rhs.mSalePrice) + ); +} + + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- + +///---------------------------------------------------------------------------- +/// exported functions +///---------------------------------------------------------------------------- +static const std::string ST_TYPE_LABEL("sale_type"); +static const std::string ST_PRICE_LABEL("sale_price"); + +LLSD ll_create_sd_from_sale_info(const LLSaleInfo& sale) +{ + LLSD rv; + const char* type = LLSaleInfo::lookup(sale.getSaleType()); + if(!type) type = LLSaleInfo::lookup(LLSaleInfo::FS_NOT); + rv[ST_TYPE_LABEL] = type; + rv[ST_PRICE_LABEL] = sale.getSalePrice(); + return rv; +} + +LLSaleInfo ll_sale_info_from_sd(const LLSD& sd) +{ + LLSaleInfo rv; + rv.setSaleType(LLSaleInfo::lookup(sd[ST_TYPE_LABEL].asString().c_str())); + rv.setSalePrice(llclamp((S32)sd[ST_PRICE_LABEL], 0, S32_MAX)); + return rv; +} diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h index ffece07f7c..44eb841641 100644 --- a/indra/llinventory/llsaleinfo.h +++ b/indra/llinventory/llsaleinfo.h @@ -1,120 +1,120 @@ -/**
- * @file llsaleinfo.h
- * @brief LLSaleInfo class header file.
- *
- * $LicenseInfo:firstyear=2002&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$
- */
-
-#ifndef LL_LLSALEINFO_H
-#define LL_LLSALEINFO_H
-
-#include "llpermissionsflags.h"
-#include "llsd.h"
-#include "llxmlnode.h"
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLSaleInfo
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-// L$ default price for objects
-const S32 DEFAULT_PRICE = 10;
-
-class LLMessageSystem;
-
-class LLSaleInfo
-{
-public:
- // use this to avoid temporary object creation
- static const LLSaleInfo DEFAULT;
-
- enum EForSale
- {
- // item is not to be considered for transactions
- FS_NOT = 0,
-
- // the origional is on sale
- FS_ORIGINAL = 1,
-
- // A copy is for sale
- FS_COPY = 2,
-
- // Valid only for tasks, the inventory is for sale
- // at the price in this structure.
- FS_CONTENTS = 3,
-
- FS_COUNT
- };
-
-protected:
- EForSale mSaleType;
- S32 mSalePrice;
-
-public:
- // default constructor is fine usually
- LLSaleInfo();
- LLSaleInfo(EForSale sale_type, S32 sale_price);
-
- // accessors
- bool isForSale() const;
- EForSale getSaleType() const { return mSaleType; }
- S32 getSalePrice() const { return mSalePrice; }
- U32 getCRC32() const;
-
- // mutators
- void setSaleType(EForSale type) { mSaleType = type; }
- void setSalePrice(S32 price);
- //void setNextOwnerPermMask(U32 mask) { mNextOwnerPermMask = mask; }
-
- bool exportLegacyStream(std::ostream& output_stream) const;
- LLSD asLLSD() const;
- operator LLSD() const { return asLLSD(); }
- bool fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask);
- bool importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask);
-
- LLSD packMessage() const;
- void unpackMessage(LLSD sales);
-
- // message serialization
- void packMessage(LLMessageSystem* msg) const;
- void unpackMessage(LLMessageSystem* msg, const char* block);
- void unpackMultiMessage(LLMessageSystem* msg, const char* block,
- S32 block_num);
-
- // static functionality for determine for sale status.
- static EForSale lookup(const char* name);
- static const char* lookup(EForSale type);
-
- // Allow accumulation of sale info. The price of each is added,
- // conflict in sale type results in FS_NOT, and the permissions
- // are tightened.
- void accumulate(const LLSaleInfo& sale_info);
-
- bool operator==(const LLSaleInfo &rhs) const;
- bool operator!=(const LLSaleInfo &rhs) const;
-};
-
-// These functions convert between structured data and sale info as
-// appropriate for serialization.
-LLSD ll_create_sd_from_sale_info(const LLSaleInfo& sale);
-LLSaleInfo ll_sale_info_from_sd(const LLSD& sd);
-
-#endif // LL_LLSALEINFO_H
+/** + * @file llsaleinfo.h + * @brief LLSaleInfo class header file. + * + * $LicenseInfo:firstyear=2002&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$ + */ + +#ifndef LL_LLSALEINFO_H +#define LL_LLSALEINFO_H + +#include "llpermissionsflags.h" +#include "llsd.h" +#include "llxmlnode.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLSaleInfo +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// L$ default price for objects +const S32 DEFAULT_PRICE = 10; + +class LLMessageSystem; + +class LLSaleInfo +{ +public: + // use this to avoid temporary object creation + static const LLSaleInfo DEFAULT; + + enum EForSale + { + // item is not to be considered for transactions + FS_NOT = 0, + + // the origional is on sale + FS_ORIGINAL = 1, + + // A copy is for sale + FS_COPY = 2, + + // Valid only for tasks, the inventory is for sale + // at the price in this structure. + FS_CONTENTS = 3, + + FS_COUNT + }; + +protected: + EForSale mSaleType; + S32 mSalePrice; + +public: + // default constructor is fine usually + LLSaleInfo(); + LLSaleInfo(EForSale sale_type, S32 sale_price); + + // accessors + bool isForSale() const; + EForSale getSaleType() const { return mSaleType; } + S32 getSalePrice() const { return mSalePrice; } + U32 getCRC32() const; + + // mutators + void setSaleType(EForSale type) { mSaleType = type; } + void setSalePrice(S32 price); + //void setNextOwnerPermMask(U32 mask) { mNextOwnerPermMask = mask; } + + bool exportLegacyStream(std::ostream& output_stream) const; + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask); + bool importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask); + + LLSD packMessage() const; + void unpackMessage(LLSD sales); + + // message serialization + void packMessage(LLMessageSystem* msg) const; + void unpackMessage(LLMessageSystem* msg, const char* block); + void unpackMultiMessage(LLMessageSystem* msg, const char* block, + S32 block_num); + + // static functionality for determine for sale status. + static EForSale lookup(const char* name); + static const char* lookup(EForSale type); + + // Allow accumulation of sale info. The price of each is added, + // conflict in sale type results in FS_NOT, and the permissions + // are tightened. + void accumulate(const LLSaleInfo& sale_info); + + bool operator==(const LLSaleInfo &rhs) const; + bool operator!=(const LLSaleInfo &rhs) const; +}; + +// These functions convert between structured data and sale info as +// appropriate for serialization. +LLSD ll_create_sd_from_sale_info(const LLSaleInfo& sale); +LLSaleInfo ll_sale_info_from_sd(const LLSD& sd); + +#endif // LL_LLSALEINFO_H diff --git a/indra/llinventory/lltransactionflags.cpp b/indra/llinventory/lltransactionflags.cpp index a1c632f63a..3719a295c3 100644 --- a/indra/llinventory/lltransactionflags.cpp +++ b/indra/llinventory/lltransactionflags.cpp @@ -1,168 +1,168 @@ -/**
- * @file lltransactionflags.cpp
- * @brief Some exported symbols and functions for dealing with
- * transaction flags.
- *
- * $LicenseInfo:firstyear=2003&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 "lluuid.h"
-#include "lltransactionflags.h"
-#include "lltransactiontypes.h"
-
-const U8 TRANSACTION_FLAGS_NONE = 0;
-const U8 TRANSACTION_FLAG_SOURCE_GROUP = 1;
-const U8 TRANSACTION_FLAG_DEST_GROUP = 2;
-const U8 TRANSACTION_FLAG_OWNER_GROUP = 4;
-const U8 TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION = 8;
-const U8 TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION_REMOVAL = 16;
-
-U8 pack_transaction_flags(bool is_source_group, bool is_dest_group)
-{
- U8 rv = 0;
- if(is_source_group) rv |= TRANSACTION_FLAG_SOURCE_GROUP;
- if(is_dest_group) rv |= TRANSACTION_FLAG_DEST_GROUP;
- return rv;
-}
-
-bool is_tf_source_group(TransactionFlags flags)
-{
- return ((flags & TRANSACTION_FLAG_SOURCE_GROUP) == TRANSACTION_FLAG_SOURCE_GROUP);
-}
-
-bool is_tf_dest_group(TransactionFlags flags)
-{
- return ((flags & TRANSACTION_FLAG_DEST_GROUP) == TRANSACTION_FLAG_DEST_GROUP);
-}
-
-bool is_tf_owner_group(TransactionFlags flags)
-{
- return ((flags & TRANSACTION_FLAG_OWNER_GROUP) == TRANSACTION_FLAG_OWNER_GROUP);
-}
-
-void append_reason(
- std::ostream& ostr,
- S32 transaction_type,
- const std::string& description)
-{
- switch( transaction_type )
- {
- case TRANS_OBJECT_SALE:
- ostr << " for " << (description.length() > 0 ? description : std::string("<unknown>"));
- break;
- case TRANS_LAND_SALE:
- ostr << " for a parcel of land";
- break;
- case TRANS_LAND_PASS_SALE:
- ostr << " for a land access pass";
- break;
- case TRANS_GROUP_LAND_DEED:
- ostr << " for deeding land";
- break;
- default:
- break;
- }
-}
-
-std::string build_transfer_message_to_source(
- S32 amount,
- const LLUUID& source_id,
- const LLUUID& dest_id,
- const std::string& dest_name,
- S32 transaction_type,
- const std::string& description)
-{
- LL_DEBUGS() << "build_transfer_message_to_source: " << amount << " "
- << source_id << " " << dest_id << " " << dest_name << " "
- << transaction_type << " "
- << (description.empty() ? "(no desc)" : description)
- << LL_ENDL;
- if(source_id.isNull())
- {
- return description;
- }
- if((0 == amount) && description.empty())
- {
- return description;
- }
- std::ostringstream ostr;
- if(dest_id.isNull())
- {
- // *NOTE: Do not change these strings! The viewer matches
- // them in llviewermessage.cpp to perform localization.
- // If you need to make changes, add a new, localizable message. JC
- ostr << "You paid L$" << amount;
- switch(transaction_type)
- {
- case TRANS_GROUP_CREATE:
- ostr << " to create a group";
- break;
- case TRANS_GROUP_JOIN:
- ostr << " to join a group";
- break;
- case TRANS_UPLOAD_CHARGE:
- ostr << " to upload";
- break;
- default:
- break;
- }
- }
- else
- {
- ostr << "You paid " << dest_name << " L$" << amount;
- append_reason(ostr, transaction_type, description);
- }
- ostr << ".";
- return ostr.str();
-}
-
-std::string build_transfer_message_to_destination(
- S32 amount,
- const LLUUID& dest_id,
- const LLUUID& source_id,
- const std::string& source_name,
- S32 transaction_type,
- const std::string& description)
-{
- LL_DEBUGS() << "build_transfer_message_to_dest: " << amount << " "
- << dest_id << " " << source_id << " " << source_name << " "
- << transaction_type << " " << (description.empty() ? "(no desc)" : description)
- << LL_ENDL;
- if(0 == amount)
- {
- return std::string();
- }
- if(dest_id.isNull())
- {
- return description;
- }
- std::ostringstream ostr;
- // *NOTE: Do not change these strings! The viewer matches
- // them in llviewermessage.cpp to perform localization.
- // If you need to make changes, add a new, localizable message. JC
- ostr << source_name << " paid you L$" << amount;
- append_reason(ostr, transaction_type, description);
- ostr << ".";
- return ostr.str();
-}
+/** + * @file lltransactionflags.cpp + * @brief Some exported symbols and functions for dealing with + * transaction flags. + * + * $LicenseInfo:firstyear=2003&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 "lluuid.h" +#include "lltransactionflags.h" +#include "lltransactiontypes.h" + +const U8 TRANSACTION_FLAGS_NONE = 0; +const U8 TRANSACTION_FLAG_SOURCE_GROUP = 1; +const U8 TRANSACTION_FLAG_DEST_GROUP = 2; +const U8 TRANSACTION_FLAG_OWNER_GROUP = 4; +const U8 TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION = 8; +const U8 TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION_REMOVAL = 16; + +U8 pack_transaction_flags(bool is_source_group, bool is_dest_group) +{ + U8 rv = 0; + if(is_source_group) rv |= TRANSACTION_FLAG_SOURCE_GROUP; + if(is_dest_group) rv |= TRANSACTION_FLAG_DEST_GROUP; + return rv; +} + +bool is_tf_source_group(TransactionFlags flags) +{ + return ((flags & TRANSACTION_FLAG_SOURCE_GROUP) == TRANSACTION_FLAG_SOURCE_GROUP); +} + +bool is_tf_dest_group(TransactionFlags flags) +{ + return ((flags & TRANSACTION_FLAG_DEST_GROUP) == TRANSACTION_FLAG_DEST_GROUP); +} + +bool is_tf_owner_group(TransactionFlags flags) +{ + return ((flags & TRANSACTION_FLAG_OWNER_GROUP) == TRANSACTION_FLAG_OWNER_GROUP); +} + +void append_reason( + std::ostream& ostr, + S32 transaction_type, + const std::string& description) +{ + switch( transaction_type ) + { + case TRANS_OBJECT_SALE: + ostr << " for " << (description.length() > 0 ? description : std::string("<unknown>")); + break; + case TRANS_LAND_SALE: + ostr << " for a parcel of land"; + break; + case TRANS_LAND_PASS_SALE: + ostr << " for a land access pass"; + break; + case TRANS_GROUP_LAND_DEED: + ostr << " for deeding land"; + break; + default: + break; + } +} + +std::string build_transfer_message_to_source( + S32 amount, + const LLUUID& source_id, + const LLUUID& dest_id, + const std::string& dest_name, + S32 transaction_type, + const std::string& description) +{ + LL_DEBUGS() << "build_transfer_message_to_source: " << amount << " " + << source_id << " " << dest_id << " " << dest_name << " " + << transaction_type << " " + << (description.empty() ? "(no desc)" : description) + << LL_ENDL; + if(source_id.isNull()) + { + return description; + } + if((0 == amount) && description.empty()) + { + return description; + } + std::ostringstream ostr; + if(dest_id.isNull()) + { + // *NOTE: Do not change these strings! The viewer matches + // them in llviewermessage.cpp to perform localization. + // If you need to make changes, add a new, localizable message. JC + ostr << "You paid L$" << amount; + switch(transaction_type) + { + case TRANS_GROUP_CREATE: + ostr << " to create a group"; + break; + case TRANS_GROUP_JOIN: + ostr << " to join a group"; + break; + case TRANS_UPLOAD_CHARGE: + ostr << " to upload"; + break; + default: + break; + } + } + else + { + ostr << "You paid " << dest_name << " L$" << amount; + append_reason(ostr, transaction_type, description); + } + ostr << "."; + return ostr.str(); +} + +std::string build_transfer_message_to_destination( + S32 amount, + const LLUUID& dest_id, + const LLUUID& source_id, + const std::string& source_name, + S32 transaction_type, + const std::string& description) +{ + LL_DEBUGS() << "build_transfer_message_to_dest: " << amount << " " + << dest_id << " " << source_id << " " << source_name << " " + << transaction_type << " " << (description.empty() ? "(no desc)" : description) + << LL_ENDL; + if(0 == amount) + { + return std::string(); + } + if(dest_id.isNull()) + { + return description; + } + std::ostringstream ostr; + // *NOTE: Do not change these strings! The viewer matches + // them in llviewermessage.cpp to perform localization. + // If you need to make changes, add a new, localizable message. JC + ostr << source_name << " paid you L$" << amount; + append_reason(ostr, transaction_type, description); + ostr << "."; + return ostr.str(); +} diff --git a/indra/llinventory/lltransactionflags.h b/indra/llinventory/lltransactionflags.h index c20adbebb2..3c61b785a3 100644 --- a/indra/llinventory/lltransactionflags.h +++ b/indra/llinventory/lltransactionflags.h @@ -1,65 +1,65 @@ -/**
- * @file lltransactionflags.h
- *
- * $LicenseInfo:firstyear=2003&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$
- */
-
-#ifndef LL_LLTRANSACTIONFLAGS_H
-#define LL_LLTRANSACTIONFLAGS_H
-
-class LLUUID;
-
-typedef U8 TransactionFlags;
-
-// defined in common/llinventory/lltransactionflags.cpp
-extern const TransactionFlags TRANSACTION_FLAGS_NONE;
-extern const TransactionFlags TRANSACTION_FLAG_SOURCE_GROUP;
-extern const TransactionFlags TRANSACTION_FLAG_DEST_GROUP;
-extern const TransactionFlags TRANSACTION_FLAG_OWNER_GROUP;
-extern const TransactionFlags TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION;
-extern const TransactionFlags TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION_REMOVAL;
-
-// very simple helper functions
-TransactionFlags pack_transaction_flags(bool is_source_group, bool is_dest_group);
-bool is_tf_source_group(TransactionFlags flags);
-bool is_tf_dest_group(TransactionFlags flags);
-bool is_tf_owner_group(TransactionFlags flags);
-
-// stupid helper functions which should be replaced with some kind of
-// internationalizeable message.
-std::string build_transfer_message_to_source(
- S32 amount,
- const LLUUID& source_id,
- const LLUUID& dest_id,
- const std::string& dest_name,
- S32 transaction_type,
- const std::string& description);
-
-std::string build_transfer_message_to_destination(
- S32 amount,
- const LLUUID& dest_id,
- const LLUUID& source_id,
- const std::string& source_name,
- S32 transaction_type,
- const std::string& description);
-
-#endif // LL_LLTRANSACTIONFLAGS_H
+/** + * @file lltransactionflags.h + * + * $LicenseInfo:firstyear=2003&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$ + */ + +#ifndef LL_LLTRANSACTIONFLAGS_H +#define LL_LLTRANSACTIONFLAGS_H + +class LLUUID; + +typedef U8 TransactionFlags; + +// defined in common/llinventory/lltransactionflags.cpp +extern const TransactionFlags TRANSACTION_FLAGS_NONE; +extern const TransactionFlags TRANSACTION_FLAG_SOURCE_GROUP; +extern const TransactionFlags TRANSACTION_FLAG_DEST_GROUP; +extern const TransactionFlags TRANSACTION_FLAG_OWNER_GROUP; +extern const TransactionFlags TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION; +extern const TransactionFlags TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION_REMOVAL; + +// very simple helper functions +TransactionFlags pack_transaction_flags(bool is_source_group, bool is_dest_group); +bool is_tf_source_group(TransactionFlags flags); +bool is_tf_dest_group(TransactionFlags flags); +bool is_tf_owner_group(TransactionFlags flags); + +// stupid helper functions which should be replaced with some kind of +// internationalizeable message. +std::string build_transfer_message_to_source( + S32 amount, + const LLUUID& source_id, + const LLUUID& dest_id, + const std::string& dest_name, + S32 transaction_type, + const std::string& description); + +std::string build_transfer_message_to_destination( + S32 amount, + const LLUUID& dest_id, + const LLUUID& source_id, + const std::string& source_name, + S32 transaction_type, + const std::string& description); + +#endif // LL_LLTRANSACTIONFLAGS_H diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp index e1eb3d89ea..bcf6131bd8 100644 --- a/indra/llinventory/tests/inventorymisc_test.cpp +++ b/indra/llinventory/tests/inventorymisc_test.cpp @@ -1,512 +1,512 @@ -/**
- * @file inventory.cpp
- * @author Phoenix
- * @date 2005-11-15
- * @brief Functions for inventory test framework
- *
- * $LicenseInfo:firstyear=2005&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 "llsd.h"
-#include "llsdserialize.h"
-
-#include "../llinventory.h"
-#include "../test/lltut.h"
-
-
-#if LL_WINDOWS
-// disable unreachable code warnings
-#pragma warning(disable: 4702)
-#endif
-
-LLPointer<LLInventoryItem> create_random_inventory_item()
-{
- LLUUID item_id;
- item_id.generate();
- LLUUID parent_id;
- parent_id.generate();
- LLPermissions perm;
- LLUUID creator_id;
- creator_id.generate();
- LLUUID owner_id;
- owner_id.generate();
- LLUUID last_owner_id;
- last_owner_id.generate();
- LLUUID group_id;
- group_id.generate();
- perm.init(creator_id, owner_id, last_owner_id, group_id);
- perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
- LLUUID asset_id;
- asset_id.generate();
- S32 price = rand();
- LLSaleInfo sale_info(LLSaleInfo::FS_COPY, price);
- U32 flags = rand();
- S32 creation = time(NULL);
-
- LLPointer<LLInventoryItem> item = new LLInventoryItem(
- item_id,
- parent_id,
- perm,
- asset_id,
- LLAssetType::AT_OBJECT,
- LLInventoryType::IT_ATTACHMENT,
- std::string("Sample Object"),
- std::string("Used for Testing"),
- sale_info,
- flags,
- creation);
- return item;
-}
-
-LLPointer<LLInventoryCategory> create_random_inventory_cat()
-{
- LLUUID item_id;
- item_id.generate();
- LLUUID parent_id;
- parent_id.generate();
-
- LLPointer<LLInventoryCategory> cat = new LLInventoryCategory(
- item_id,
- parent_id,
- LLFolderType::FT_NONE,
- std::string("Sample category"));
- return cat;
-}
-
-namespace tut
-{
- struct inventory_data
- {
- };
- typedef test_group<inventory_data> inventory_test;
- typedef inventory_test::object inventory_object;
- tut::inventory_test inv("LLInventory");
-
-//***class LLInventoryType***//
-
-
- template<> template<>
- void inventory_object::test<1>()
- {
- LLInventoryType::EType retType = LLInventoryType::lookup(std::string("sound"));
- ensure("1.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SOUND);
-
- retType = LLInventoryType::lookup(std::string("snapshot"));
- ensure("2.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SNAPSHOT);
- }
-
- template<> template<>
- void inventory_object::test<2>()
- {
- static std::string retType = LLInventoryType::lookup(LLInventoryType::IT_CALLINGCARD);
- ensure("1.LLInventoryType::lookup(EType) failed", (retType == "callcard"));
-
- retType = LLInventoryType::lookup(LLInventoryType::IT_LANDMARK);
- ensure("2.LLInventoryType::lookup(EType) failed", (retType == "landmark"));
-
- }
-
- template<> template<>
- void inventory_object::test<3>()
- {
- static std::string retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_CALLINGCARD);
- ensure("1.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "calling card"));
-
- retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_LANDMARK);
- ensure("2.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "landmark"));
- }
-
- template<> template<>
- void inventory_object::test<4>()
- {
- static LLInventoryType::EType retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_TEXTURE);
- ensure("1.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_TEXTURE);
-
- retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_LANDMARK);
- ensure("2.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_LANDMARK);
- }
-
-//*****class LLInventoryItem*****//
-
- template<> template<>
- void inventory_object::test<5>()
- {
- LLPointer<LLInventoryItem> src = create_random_inventory_item();
- LLSD sd = ll_create_sd_from_inventory_item(src);
- //LL_INFOS() << "sd: " << *sd << LL_ENDL;
- LLPointer<LLInventoryItem> dst = new LLInventoryItem;
- bool successful_parse = dst->fromLLSD(sd);
- ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true);
- ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
- ensure_equals("3.name::getName() failed", dst->getName(), src->getName());
- ensure_equals("4.type::getType() failed", dst->getType(), src->getType());
-
- ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions());
- ensure_equals("6.description::getDescription() failed", dst->getDescription(), src->getDescription());
- ensure_equals("7.sale type::getSaleType() failed", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType());
- ensure_equals("8.sale price::getSalePrice() failed", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice());
- ensure_equals("9.asset id::getAssetUUID() failed", dst->getAssetUUID(), src->getAssetUUID());
- ensure_equals("10.inventory type::getInventoryType() failed", dst->getInventoryType(), src->getInventoryType());
- ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src->getFlags());
- ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate());
-
- LLUUID new_item_id, new_parent_id;
- new_item_id.generate();
- src->setUUID(new_item_id);
-
- new_parent_id.generate();
- src->setParent(new_parent_id);
-
- std::string new_name = "LindenLab";
- src->rename(new_name);
-
- src->setType(LLAssetType::AT_SOUND);
-
- LLUUID new_asset_id;
- new_asset_id.generate();
-
- src->setAssetUUID(new_asset_id);
- std::string new_desc = "SecondLife Testing";
- src->setDescription(new_desc);
-
- S32 new_price = rand();
- LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price);
- src->setSaleInfo(new_sale_info);
-
- U32 new_flags = rand();
- S32 new_creation = time(NULL);
-
- LLPermissions new_perm;
-
- LLUUID new_creator_id;
- new_creator_id.generate();
-
- LLUUID new_owner_id;
- new_owner_id.generate();
-
- LLUUID last_owner_id;
- last_owner_id.generate();
-
- LLUUID new_group_id;
- new_group_id.generate();
- new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id);
- new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
- src->setPermissions(new_perm);
-
- src->setInventoryType(LLInventoryType::IT_SOUND);
- src->setFlags(new_flags);
- src->setCreationDate(new_creation);
-
- sd = ll_create_sd_from_inventory_item(src);
- //LL_INFOS() << "sd: " << *sd << LL_ENDL;
- successful_parse = dst->fromLLSD(sd);
- ensure_equals("13.item id::getUUID() failed", dst->getUUID(), src->getUUID());
- ensure_equals("14.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
- ensure_equals("15.name::getName() failed", dst->getName(), src->getName());
- ensure_equals("16.type::getType() failed", dst->getType(), src->getType());
-
- ensure_equals("17.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions());
- ensure_equals("18.description::getDescription() failed", dst->getDescription(), src->getDescription());
- ensure_equals("19.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType());
- ensure_equals("20.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice());
- ensure_equals("21.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src->getAssetUUID());
- ensure_equals("22.inventory type::getInventoryType() failed type", dst->getInventoryType(), src->getInventoryType());
- ensure_equals("23.flags::getFlags() failed", dst->getFlags(), src->getFlags());
- ensure_equals("24.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate());
-
- }
-
- template<> template<>
- void inventory_object::test<6>()
- {
- LLPointer<LLInventoryItem> src = create_random_inventory_item();
-
- LLUUID new_item_id, new_parent_id;
- new_item_id.generate();
- src->setUUID(new_item_id);
-
- new_parent_id.generate();
- src->setParent(new_parent_id);
-
- std::string new_name = "LindenLab";
- src->rename(new_name);
-
- src->setType(LLAssetType::AT_SOUND);
-
- LLUUID new_asset_id;
- new_asset_id.generate();
-
- src->setAssetUUID(new_asset_id);
- std::string new_desc = "SecondLife Testing";
- src->setDescription(new_desc);
-
- S32 new_price = rand();
- LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price);
- src->setSaleInfo(new_sale_info);
-
- U32 new_flags = rand();
- S32 new_creation = time(NULL);
-
- LLPermissions new_perm;
-
- LLUUID new_creator_id;
- new_creator_id.generate();
-
- LLUUID new_owner_id;
- new_owner_id.generate();
-
- LLUUID last_owner_id;
- last_owner_id.generate();
-
- LLUUID new_group_id;
- new_group_id.generate();
- new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id);
- new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY);
- src->setPermissions(new_perm);
-
- src->setInventoryType(LLInventoryType::IT_SOUND);
- src->setFlags(new_flags);
- src->setCreationDate(new_creation);
-
- // test a save/load cycle to LLSD and back again
- LLSD sd = ll_create_sd_from_inventory_item(src);
- LLPointer<LLInventoryItem> dst = new LLInventoryItem;
- bool successful_parse = dst->fromLLSD(sd);
- ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true);
-
- LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
- src1->copyItem(src);
-
- ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src1->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src1->getParentUUID());
- ensure_equals("3.name::getName() failed", dst->getName(), src1->getName());
- ensure_equals("4.type::getType() failed", dst->getType(), src1->getType());
-
- ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src1->getPermissions());
- ensure_equals("6.description::getDescription() failed", dst->getDescription(), src1->getDescription());
- ensure_equals("7.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src1->getSaleInfo().getSaleType());
- ensure_equals("8.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src1->getSaleInfo().getSalePrice());
- ensure_equals("9.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src1->getAssetUUID());
- ensure_equals("10.inventory type::getInventoryType() failed type", dst->getInventoryType(), src1->getInventoryType());
- ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src1->getFlags());
- ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src1->getCreationDate());
-
- // quick test to make sure generateUUID() really works
- src1->generateUUID();
- ensure_not_equals("13.item id::generateUUID() failed", src->getUUID(), src1->getUUID());
- }
-
- template<> template<>
- void inventory_object::test<7>()
- {
- std::string filename("linden_file.dat");
- llofstream fileXML(filename.c_str());
- if (!fileXML.is_open())
- {
- LL_ERRS() << "file could not be opened\n" << LL_ENDL;
- return;
- }
-
- LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
- fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->asLLSD()) << std::endl;
- fileXML.close();
-
-
- LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
- llifstream file(filename.c_str());
- if (!file.is_open())
- {
- LL_ERRS() << "file could not be opened\n" << LL_ENDL;
- return;
- }
- std::string line;
- LLPointer<LLSDParser> parser = new LLSDNotationParser();
- std::getline(file, line);
- LLSD s_item;
- std::istringstream iss(line);
- if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
- {
- LL_ERRS()<< "Parsing cache failed" << LL_ENDL;
- return;
- }
- src2->fromLLSD(s_item);
-
- file.close();
-
- ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
- ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
- ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
- ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
- ensure_equals("6.type::getType() failed", src1->getType(), src2->getType());
- ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
- ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
- ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
- ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
-
- }
-
- template<> template<>
- void inventory_object::test<8>()
- {
-
- LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
-
- std::ostringstream ostream;
- src1->exportLegacyStream(ostream, true);
-
- std::istringstream istream(ostream.str());
- LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
- src2->importLegacyStream(istream);
-
- ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
- ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
- ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
- ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
- ensure_equals("6.type::getType() failed", src1->getType(), src2->getType());
- ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
- ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
- ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
- ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
-
-
- }
-
- template<> template<>
- void inventory_object::test<9>()
- {
- // Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML()
- // because I can't find any non-test code references to it. 2009-05-04 JC
- }
-
- template<> template<>
- void inventory_object::test<11>()
- {
- LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
- LLSD retSd = src1->asLLSD();
- LLPointer<LLInventoryItem> src2 = new LLInventoryItem();
- src2->fromLLSD(retSd);
-
- ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
- ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions());
- ensure_equals("4.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID());
- ensure_equals("5.type::getType() failed", src1->getType(), src2->getType());
- ensure_equals("6.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType());
- ensure_equals("7.flags::getFlags() failed", src1->getFlags(), src2->getFlags());
- ensure_equals("8.sale type::getSaleType() failed type", src1->getSaleInfo().getSaleType(), src2->getSaleInfo().getSaleType());
- ensure_equals("9.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice());
- ensure_equals("10.name::getName() failed", src1->getName(), src2->getName());
- ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription());
- ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
- }
-
-//******class LLInventoryCategory*******//
-
- template<> template<>
- void inventory_object::test<12>()
- {
- LLPointer<LLInventoryCategory> src = create_random_inventory_cat();
- LLSD sd = ll_create_sd_from_inventory_category(src);
- LLPointer<LLInventoryCategory> dst = ll_create_category_from_sd(sd);
-
- ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID());
- ensure_equals("3.name::getName() failed", dst->getName(), src->getName());
- ensure_equals("4.type::getType() failed", dst->getType(), src->getType());
- ensure_equals("5.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType());
-
- src->setPreferredType( LLFolderType::FT_TEXTURE);
- sd = ll_create_sd_from_inventory_category(src);
- dst = ll_create_category_from_sd(sd);
- ensure_equals("6.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType());
-
-
- }
-
- template<> template<>
- void inventory_object::test<13>()
- {
- std::string filename("linden_file.dat");
- llofstream fileXML(filename.c_str());
- if (!fileXML.is_open())
- {
- LL_ERRS() << "file could not be opened\n" << LL_ENDL;
- return;
- }
-
- LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
- fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->exportLLSD()) << std::endl;
- fileXML.close();
-
- llifstream file(filename.c_str());
- if (!file.is_open())
- {
- LL_ERRS() << "file could not be opened\n" << LL_ENDL;
- return;
- }
- std::string line;
- LLPointer<LLSDParser> parser = new LLSDNotationParser();
- std::getline(file, line);
- LLSD s_item;
- std::istringstream iss(line);
- if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE)
- {
- LL_ERRS()<< "Parsing cache failed" << LL_ENDL;
- return;
- }
-
- file.close();
-
- LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
- src2->importLLSD(s_item);
-
- ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
- ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
- ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
- ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
- }
-
- template<> template<>
- void inventory_object::test<14>()
- {
- LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
-
- std::ostringstream ostream;
- src1->exportLegacyStream(ostream, true);
-
- std::istringstream istream(ostream.str());
- LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
- src2->importLegacyStream(istream);
-
- ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
- ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
- ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
- ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
- ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
-
- }
-}
+/** + * @file inventory.cpp + * @author Phoenix + * @date 2005-11-15 + * @brief Functions for inventory test framework + * + * $LicenseInfo:firstyear=2005&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 "llsd.h" +#include "llsdserialize.h" + +#include "../llinventory.h" +#include "../test/lltut.h" + + +#if LL_WINDOWS +// disable unreachable code warnings +#pragma warning(disable: 4702) +#endif + +LLPointer<LLInventoryItem> create_random_inventory_item() +{ + LLUUID item_id; + item_id.generate(); + LLUUID parent_id; + parent_id.generate(); + LLPermissions perm; + LLUUID creator_id; + creator_id.generate(); + LLUUID owner_id; + owner_id.generate(); + LLUUID last_owner_id; + last_owner_id.generate(); + LLUUID group_id; + group_id.generate(); + perm.init(creator_id, owner_id, last_owner_id, group_id); + perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY); + LLUUID asset_id; + asset_id.generate(); + S32 price = rand(); + LLSaleInfo sale_info(LLSaleInfo::FS_COPY, price); + U32 flags = rand(); + S32 creation = time(NULL); + + LLPointer<LLInventoryItem> item = new LLInventoryItem( + item_id, + parent_id, + perm, + asset_id, + LLAssetType::AT_OBJECT, + LLInventoryType::IT_ATTACHMENT, + std::string("Sample Object"), + std::string("Used for Testing"), + sale_info, + flags, + creation); + return item; +} + +LLPointer<LLInventoryCategory> create_random_inventory_cat() +{ + LLUUID item_id; + item_id.generate(); + LLUUID parent_id; + parent_id.generate(); + + LLPointer<LLInventoryCategory> cat = new LLInventoryCategory( + item_id, + parent_id, + LLFolderType::FT_NONE, + std::string("Sample category")); + return cat; +} + +namespace tut +{ + struct inventory_data + { + }; + typedef test_group<inventory_data> inventory_test; + typedef inventory_test::object inventory_object; + tut::inventory_test inv("LLInventory"); + +//***class LLInventoryType***// + + + template<> template<> + void inventory_object::test<1>() + { + LLInventoryType::EType retType = LLInventoryType::lookup(std::string("sound")); + ensure("1.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SOUND); + + retType = LLInventoryType::lookup(std::string("snapshot")); + ensure("2.LLInventoryType::lookup(char*) failed", retType == LLInventoryType::IT_SNAPSHOT); + } + + template<> template<> + void inventory_object::test<2>() + { + static std::string retType = LLInventoryType::lookup(LLInventoryType::IT_CALLINGCARD); + ensure("1.LLInventoryType::lookup(EType) failed", (retType == "callcard")); + + retType = LLInventoryType::lookup(LLInventoryType::IT_LANDMARK); + ensure("2.LLInventoryType::lookup(EType) failed", (retType == "landmark")); + + } + + template<> template<> + void inventory_object::test<3>() + { + static std::string retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_CALLINGCARD); + ensure("1.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "calling card")); + + retType = LLInventoryType::lookupHumanReadable(LLInventoryType::IT_LANDMARK); + ensure("2.LLInventoryType::lookupHumanReadable(EType) failed", (retType == "landmark")); + } + + template<> template<> + void inventory_object::test<4>() + { + static LLInventoryType::EType retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_TEXTURE); + ensure("1.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_TEXTURE); + + retType = LLInventoryType::defaultForAssetType(LLAssetType::AT_LANDMARK); + ensure("2.LLInventoryType::defaultForAssetType(LLAssetType EType) failed", retType == LLInventoryType::IT_LANDMARK); + } + +//*****class LLInventoryItem*****// + + template<> template<> + void inventory_object::test<5>() + { + LLPointer<LLInventoryItem> src = create_random_inventory_item(); + LLSD sd = ll_create_sd_from_inventory_item(src); + //LL_INFOS() << "sd: " << *sd << LL_ENDL; + LLPointer<LLInventoryItem> dst = new LLInventoryItem; + bool successful_parse = dst->fromLLSD(sd); + ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true); + ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID()); + ensure_equals("3.name::getName() failed", dst->getName(), src->getName()); + ensure_equals("4.type::getType() failed", dst->getType(), src->getType()); + + ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions()); + ensure_equals("6.description::getDescription() failed", dst->getDescription(), src->getDescription()); + ensure_equals("7.sale type::getSaleType() failed", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType()); + ensure_equals("8.sale price::getSalePrice() failed", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice()); + ensure_equals("9.asset id::getAssetUUID() failed", dst->getAssetUUID(), src->getAssetUUID()); + ensure_equals("10.inventory type::getInventoryType() failed", dst->getInventoryType(), src->getInventoryType()); + ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src->getFlags()); + ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate()); + + LLUUID new_item_id, new_parent_id; + new_item_id.generate(); + src->setUUID(new_item_id); + + new_parent_id.generate(); + src->setParent(new_parent_id); + + std::string new_name = "LindenLab"; + src->rename(new_name); + + src->setType(LLAssetType::AT_SOUND); + + LLUUID new_asset_id; + new_asset_id.generate(); + + src->setAssetUUID(new_asset_id); + std::string new_desc = "SecondLife Testing"; + src->setDescription(new_desc); + + S32 new_price = rand(); + LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price); + src->setSaleInfo(new_sale_info); + + U32 new_flags = rand(); + S32 new_creation = time(NULL); + + LLPermissions new_perm; + + LLUUID new_creator_id; + new_creator_id.generate(); + + LLUUID new_owner_id; + new_owner_id.generate(); + + LLUUID last_owner_id; + last_owner_id.generate(); + + LLUUID new_group_id; + new_group_id.generate(); + new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id); + new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY); + src->setPermissions(new_perm); + + src->setInventoryType(LLInventoryType::IT_SOUND); + src->setFlags(new_flags); + src->setCreationDate(new_creation); + + sd = ll_create_sd_from_inventory_item(src); + //LL_INFOS() << "sd: " << *sd << LL_ENDL; + successful_parse = dst->fromLLSD(sd); + ensure_equals("13.item id::getUUID() failed", dst->getUUID(), src->getUUID()); + ensure_equals("14.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID()); + ensure_equals("15.name::getName() failed", dst->getName(), src->getName()); + ensure_equals("16.type::getType() failed", dst->getType(), src->getType()); + + ensure_equals("17.permissions::getPermissions() failed", dst->getPermissions(), src->getPermissions()); + ensure_equals("18.description::getDescription() failed", dst->getDescription(), src->getDescription()); + ensure_equals("19.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src->getSaleInfo().getSaleType()); + ensure_equals("20.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src->getSaleInfo().getSalePrice()); + ensure_equals("21.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src->getAssetUUID()); + ensure_equals("22.inventory type::getInventoryType() failed type", dst->getInventoryType(), src->getInventoryType()); + ensure_equals("23.flags::getFlags() failed", dst->getFlags(), src->getFlags()); + ensure_equals("24.creation::getCreationDate() failed", dst->getCreationDate(), src->getCreationDate()); + + } + + template<> template<> + void inventory_object::test<6>() + { + LLPointer<LLInventoryItem> src = create_random_inventory_item(); + + LLUUID new_item_id, new_parent_id; + new_item_id.generate(); + src->setUUID(new_item_id); + + new_parent_id.generate(); + src->setParent(new_parent_id); + + std::string new_name = "LindenLab"; + src->rename(new_name); + + src->setType(LLAssetType::AT_SOUND); + + LLUUID new_asset_id; + new_asset_id.generate(); + + src->setAssetUUID(new_asset_id); + std::string new_desc = "SecondLife Testing"; + src->setDescription(new_desc); + + S32 new_price = rand(); + LLSaleInfo new_sale_info(LLSaleInfo::FS_COPY, new_price); + src->setSaleInfo(new_sale_info); + + U32 new_flags = rand(); + S32 new_creation = time(NULL); + + LLPermissions new_perm; + + LLUUID new_creator_id; + new_creator_id.generate(); + + LLUUID new_owner_id; + new_owner_id.generate(); + + LLUUID last_owner_id; + last_owner_id.generate(); + + LLUUID new_group_id; + new_group_id.generate(); + new_perm.init(new_creator_id, new_owner_id, last_owner_id, new_group_id); + new_perm.initMasks(PERM_ALL, PERM_ALL, PERM_COPY, PERM_COPY, PERM_MODIFY | PERM_COPY); + src->setPermissions(new_perm); + + src->setInventoryType(LLInventoryType::IT_SOUND); + src->setFlags(new_flags); + src->setCreationDate(new_creation); + + // test a save/load cycle to LLSD and back again + LLSD sd = ll_create_sd_from_inventory_item(src); + LLPointer<LLInventoryItem> dst = new LLInventoryItem; + bool successful_parse = dst->fromLLSD(sd); + ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true); + + LLPointer<LLInventoryItem> src1 = create_random_inventory_item(); + src1->copyItem(src); + + ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src1->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src1->getParentUUID()); + ensure_equals("3.name::getName() failed", dst->getName(), src1->getName()); + ensure_equals("4.type::getType() failed", dst->getType(), src1->getType()); + + ensure_equals("5.permissions::getPermissions() failed", dst->getPermissions(), src1->getPermissions()); + ensure_equals("6.description::getDescription() failed", dst->getDescription(), src1->getDescription()); + ensure_equals("7.sale type::getSaleType() failed type", dst->getSaleInfo().getSaleType(), src1->getSaleInfo().getSaleType()); + ensure_equals("8.sale price::getSalePrice() failed price", dst->getSaleInfo().getSalePrice(), src1->getSaleInfo().getSalePrice()); + ensure_equals("9.asset id::getAssetUUID() failed id", dst->getAssetUUID(), src1->getAssetUUID()); + ensure_equals("10.inventory type::getInventoryType() failed type", dst->getInventoryType(), src1->getInventoryType()); + ensure_equals("11.flags::getFlags() failed", dst->getFlags(), src1->getFlags()); + ensure_equals("12.creation::getCreationDate() failed", dst->getCreationDate(), src1->getCreationDate()); + + // quick test to make sure generateUUID() really works + src1->generateUUID(); + ensure_not_equals("13.item id::generateUUID() failed", src->getUUID(), src1->getUUID()); + } + + template<> template<> + void inventory_object::test<7>() + { + std::string filename("linden_file.dat"); + llofstream fileXML(filename.c_str()); + if (!fileXML.is_open()) + { + LL_ERRS() << "file could not be opened\n" << LL_ENDL; + return; + } + + LLPointer<LLInventoryItem> src1 = create_random_inventory_item(); + fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->asLLSD()) << std::endl; + fileXML.close(); + + + LLPointer<LLInventoryItem> src2 = new LLInventoryItem(); + llifstream file(filename.c_str()); + if (!file.is_open()) + { + LL_ERRS() << "file could not be opened\n" << LL_ENDL; + return; + } + std::string line; + LLPointer<LLSDParser> parser = new LLSDNotationParser(); + std::getline(file, line); + LLSD s_item; + std::istringstream iss(line); + if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) + { + LL_ERRS()<< "Parsing cache failed" << LL_ENDL; + return; + } + src2->fromLLSD(s_item); + + file.close(); + + ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); + ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions()); + ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice()); + ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID()); + ensure_equals("6.type::getType() failed", src1->getType(), src2->getType()); + ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType()); + ensure_equals("8.name::getName() failed", src1->getName(), src2->getName()); + ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription()); + ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate()); + + } + + template<> template<> + void inventory_object::test<8>() + { + + LLPointer<LLInventoryItem> src1 = create_random_inventory_item(); + + std::ostringstream ostream; + src1->exportLegacyStream(ostream, true); + + std::istringstream istream(ostream.str()); + LLPointer<LLInventoryItem> src2 = new LLInventoryItem(); + src2->importLegacyStream(istream); + + ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); + ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions()); + ensure_equals("4.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice()); + ensure_equals("5.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID()); + ensure_equals("6.type::getType() failed", src1->getType(), src2->getType()); + ensure_equals("7.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType()); + ensure_equals("8.name::getName() failed", src1->getName(), src2->getName()); + ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription()); + ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate()); + + + } + + template<> template<> + void inventory_object::test<9>() + { + // Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML() + // because I can't find any non-test code references to it. 2009-05-04 JC + } + + template<> template<> + void inventory_object::test<11>() + { + LLPointer<LLInventoryItem> src1 = create_random_inventory_item(); + LLSD retSd = src1->asLLSD(); + LLPointer<LLInventoryItem> src2 = new LLInventoryItem(); + src2->fromLLSD(retSd); + + ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); + ensure_equals("3.permissions::getPermissions() failed", src1->getPermissions(), src2->getPermissions()); + ensure_equals("4.asset id::getAssetUUID() failed id", src1->getAssetUUID(), src2->getAssetUUID()); + ensure_equals("5.type::getType() failed", src1->getType(), src2->getType()); + ensure_equals("6.inventory type::getInventoryType() failed type", src1->getInventoryType(), src2->getInventoryType()); + ensure_equals("7.flags::getFlags() failed", src1->getFlags(), src2->getFlags()); + ensure_equals("8.sale type::getSaleType() failed type", src1->getSaleInfo().getSaleType(), src2->getSaleInfo().getSaleType()); + ensure_equals("9.sale price::getSalePrice() failed price", src1->getSaleInfo().getSalePrice(), src2->getSaleInfo().getSalePrice()); + ensure_equals("10.name::getName() failed", src1->getName(), src2->getName()); + ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription()); + ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate()); + } + +//******class LLInventoryCategory*******// + + template<> template<> + void inventory_object::test<12>() + { + LLPointer<LLInventoryCategory> src = create_random_inventory_cat(); + LLSD sd = ll_create_sd_from_inventory_category(src); + LLPointer<LLInventoryCategory> dst = ll_create_category_from_sd(sd); + + ensure_equals("1.item id::getUUID() failed", dst->getUUID(), src->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", dst->getParentUUID(), src->getParentUUID()); + ensure_equals("3.name::getName() failed", dst->getName(), src->getName()); + ensure_equals("4.type::getType() failed", dst->getType(), src->getType()); + ensure_equals("5.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType()); + + src->setPreferredType( LLFolderType::FT_TEXTURE); + sd = ll_create_sd_from_inventory_category(src); + dst = ll_create_category_from_sd(sd); + ensure_equals("6.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType()); + + + } + + template<> template<> + void inventory_object::test<13>() + { + std::string filename("linden_file.dat"); + llofstream fileXML(filename.c_str()); + if (!fileXML.is_open()) + { + LL_ERRS() << "file could not be opened\n" << LL_ENDL; + return; + } + + LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat(); + fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->exportLLSD()) << std::endl; + fileXML.close(); + + llifstream file(filename.c_str()); + if (!file.is_open()) + { + LL_ERRS() << "file could not be opened\n" << LL_ENDL; + return; + } + std::string line; + LLPointer<LLSDParser> parser = new LLSDNotationParser(); + std::getline(file, line); + LLSD s_item; + std::istringstream iss(line); + if (parser->parse(iss, s_item, line.length()) == LLSDParser::PARSE_FAILURE) + { + LL_ERRS()<< "Parsing cache failed" << LL_ENDL; + return; + } + + file.close(); + + LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory(); + src2->importLLSD(s_item); + + ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); + ensure_equals("3.type::getType() failed", src1->getType(), src2->getType()); + ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType()); + ensure_equals("5.name::getName() failed", src1->getName(), src2->getName()); + } + + template<> template<> + void inventory_object::test<14>() + { + LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat(); + + std::ostringstream ostream; + src1->exportLegacyStream(ostream, true); + + std::istringstream istream(ostream.str()); + LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory(); + src2->importLegacyStream(istream); + + ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); + ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); + ensure_equals("3.type::getType() failed", src1->getType(), src2->getType()); + ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType()); + ensure_equals("5.name::getName() failed", src1->getName(), src2->getName()); + + } +} |