From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/llinventory/llfoldertype.cpp | 444 ++-- indra/llinventory/llinventory.cpp | 3034 ++++++++++++------------ indra/llinventory/llinventory.h | 586 ++--- indra/llinventory/llnotecard.cpp | 578 ++--- indra/llinventory/llparcel.cpp | 2550 ++++++++++---------- indra/llinventory/llparcel.h | 1354 +++++------ indra/llinventory/llpermissions.cpp | 2104 ++++++++-------- indra/llinventory/llpermissions.h | 900 +++---- indra/llinventory/llsaleinfo.cpp | 630 ++--- indra/llinventory/llsaleinfo.h | 240 +- indra/llinventory/lltransactionflags.cpp | 336 +-- indra/llinventory/lltransactionflags.h | 130 +- indra/llinventory/tests/inventorymisc_test.cpp | 1024 ++++---- 13 files changed, 6955 insertions(+), 6955 deletions(-) (limited to 'indra/llinventory') 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, - public LLDictionary -{ - 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, + public LLDictionary +{ + 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 - -#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("", 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(mType); - msg->addS8Fast(_PREHASH_Type, type); - type = static_cast(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(type); - msg->getS8(block, "InvType", type, block_num); - mInventoryType = static_cast(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("", 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: - asset_id - acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 - perms - 8 - service - 3 - version - 1 - */ - 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(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(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(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(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(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(type); - } - w = INV_ASSET_TYPE_LABEL_WS; - if (sd.has(w)) - { - S8 type = (U8)sd[w].asInteger(); - mPreferredType = static_cast(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(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("", 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 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 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 ll_create_category_from_sd(const LLSD& sd_cat) -{ - LLPointer 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 + +#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("", 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(mType); + msg->addS8Fast(_PREHASH_Type, type); + type = static_cast(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(type); + msg->getS8(block, "InvType", type, block_num); + mInventoryType = static_cast(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("", 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: + asset_id + acc0ec86 - 17f2 - 4b92 - ab41 - 6718b1f755f7 + perms + 8 + service + 3 + version + 1 + */ + 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(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(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(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(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(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(type); + } + w = INV_ASSET_TYPE_LABEL_WS; + if (sd.has(w)) + { + S8 type = (U8)sd[w].asInteger(); + mPreferredType = static_cast(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(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("", 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 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 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 ll_create_category_from_sd(const LLSD& sd_cat) +{ + LLPointer 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 > object_list_t; - typedef std::list > 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 > 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 > 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 item); -LLSD ll_create_sd_from_inventory_category(LLPointer cat); -LLPointer 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 > object_list_t; + typedef std::list > 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 > 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 > 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 item); +LLSD ll_create_sd_from_inventory_category(LLPointer cat); +LLPointer 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 - // { - // ext char index - // - // } - // } - - 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 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 - // { - // - // Text length - // - // } - - // Version 2 format: (NOTE: Imports identically to version 1) - // Linden text version 2 - // { - // - // Text length - // - // } - - 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 >::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 >& 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 + // { + // ext char index + // + // } + // } + + 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 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 + // { + // + // Text length + // + // } + + // Version 2 format: (NOTE: Imports identically to version 1) + // Linden text version 2 + // { + // + // Text length + // + // } + + 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 >::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 >& 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 - -#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 - -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& 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* 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* 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 + +#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 + +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& 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* 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* 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 -#include - -#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 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& list); - void unpackAccessEntries(LLMessageSystem* msg, - std::map* 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 mAccessList; - std::map mBanList; - std::map mTempBanList; - std::map mTempAccessList; - - typedef std::map 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 +#include + +#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 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& list); + void unpackAccessEntries(LLMessageSystem* msg, + std::map* 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 mAccessList; + std::map mBanList; + std::map mTempBanList; + std::map mTempAccessList; + + typedef std::map 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 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 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 -#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(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(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(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(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(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(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 +#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(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(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(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(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(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(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("")); - 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("")); + 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 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 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 create_random_inventory_cat() -{ - LLUUID item_id; - item_id.generate(); - LLUUID parent_id; - parent_id.generate(); - - LLPointer 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_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 src = create_random_inventory_item(); - LLSD sd = ll_create_sd_from_inventory_item(src); - //LL_INFOS() << "sd: " << *sd << LL_ENDL; - LLPointer 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 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 dst = new LLInventoryItem; - bool successful_parse = dst->fromLLSD(sd); - ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true); - - LLPointer 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 src1 = create_random_inventory_item(); - fileXML << LLSDOStreamer(src1->asLLSD()) << std::endl; - fileXML.close(); - - - LLPointer 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 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 src1 = create_random_inventory_item(); - - std::ostringstream ostream; - src1->exportLegacyStream(ostream, true); - - std::istringstream istream(ostream.str()); - LLPointer 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 src1 = create_random_inventory_item(); - LLSD retSd = src1->asLLSD(); - LLPointer 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 src = create_random_inventory_cat(); - LLSD sd = ll_create_sd_from_inventory_category(src); - LLPointer 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 src1 = create_random_inventory_cat(); - fileXML << LLSDOStreamer(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 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 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 src1 = create_random_inventory_cat(); - - std::ostringstream ostream; - src1->exportLegacyStream(ostream, true); - - std::istringstream istream(ostream.str()); - LLPointer 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 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 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 create_random_inventory_cat() +{ + LLUUID item_id; + item_id.generate(); + LLUUID parent_id; + parent_id.generate(); + + LLPointer 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_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 src = create_random_inventory_item(); + LLSD sd = ll_create_sd_from_inventory_item(src); + //LL_INFOS() << "sd: " << *sd << LL_ENDL; + LLPointer 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 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 dst = new LLInventoryItem; + bool successful_parse = dst->fromLLSD(sd); + ensure_equals("0.LLInventoryItem::fromLLSD()", successful_parse, true); + + LLPointer 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 src1 = create_random_inventory_item(); + fileXML << LLSDOStreamer(src1->asLLSD()) << std::endl; + fileXML.close(); + + + LLPointer 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 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 src1 = create_random_inventory_item(); + + std::ostringstream ostream; + src1->exportLegacyStream(ostream, true); + + std::istringstream istream(ostream.str()); + LLPointer 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 src1 = create_random_inventory_item(); + LLSD retSd = src1->asLLSD(); + LLPointer 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 src = create_random_inventory_cat(); + LLSD sd = ll_create_sd_from_inventory_category(src); + LLPointer 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 src1 = create_random_inventory_cat(); + fileXML << LLSDOStreamer(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 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 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 src1 = create_random_inventory_cat(); + + std::ostringstream ostream; + src1->exportLegacyStream(ostream, true); + + std::istringstream istream(ostream.str()); + LLPointer 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()); + + } +} -- cgit v1.2.3