From 5e4afb76af172af73620a3587271ac7474668ead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 9 Feb 2024 20:09:55 +0100 Subject: llinventory: BOOL (int) to real bool --- indra/newview/llviewerinventory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llviewerinventory.cpp') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 0a0a19d095..3b50dc354f 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -540,10 +540,10 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const } // virtual -BOOL LLViewerInventoryItem::importLegacyStream(std::istream& input_stream) +bool LLViewerInventoryItem::importLegacyStream(std::istream& input_stream) { - BOOL rv = LLInventoryItem::importLegacyStream(input_stream); - mIsComplete = TRUE; + bool rv = LLInventoryItem::importLegacyStream(input_stream); + mIsComplete = true; return rv; } -- cgit v1.2.3 From 2b31dad40026d8078ea30d0da0656a4078d0f5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 9 Feb 2024 22:26:02 +0100 Subject: miscellaneous: BOOL (int) to real bool --- indra/newview/llviewerinventory.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'indra/newview/llviewerinventory.cpp') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 3b50dc354f..eefe050d46 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -406,7 +406,7 @@ void LLViewerInventoryItem::cloneViewerItem(LLPointer& ne } } -void LLViewerInventoryItem::updateServer(BOOL is_new) const +void LLViewerInventoryItem::updateServer(bool is_new) const { if(!mIsComplete) { @@ -494,24 +494,24 @@ void LLViewerInventoryItem::fetchFromServer(void) const } // virtual -BOOL LLViewerInventoryItem::unpackMessage(const LLSD& item) +bool LLViewerInventoryItem::unpackMessage(const LLSD& item) { BOOL rv = LLInventoryItem::fromLLSD(item); LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); - mIsComplete = TRUE; + mIsComplete = true; return rv; } // virtual -BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) +bool LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) { BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num); LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); - mIsComplete = TRUE; + mIsComplete = true; return rv; } @@ -547,7 +547,7 @@ bool LLViewerInventoryItem::importLegacyStream(std::istream& input_stream) return rv; } -void LLViewerInventoryItem::updateParentOnServer(BOOL restamp) const +void LLViewerInventoryItem::updateParentOnServer(bool restamp) const { LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MoveInventoryItem); @@ -628,7 +628,7 @@ void LLViewerInventoryCategory::packMessage(LLMessageSystem* msg) const msg->addStringFast(_PREHASH_Name, mName); } -void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const +void LLViewerInventoryCategory::updateParentOnServer(bool restamp) const { LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MoveInventoryFolder); @@ -643,7 +643,7 @@ void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const gAgent.sendReliableMessage(); } -void LLViewerInventoryCategory::updateServer(BOOL is_new) const +void LLViewerInventoryCategory::updateServer(bool is_new) const { // communicate that change with the server. @@ -877,9 +877,9 @@ void LLViewerInventoryCategory::localizeName() } // virtual -BOOL LLViewerInventoryCategory::unpackMessage(const LLSD& category) +bool LLViewerInventoryCategory::unpackMessage(const LLSD& category) { - BOOL rv = LLInventoryCategory::fromLLSD(category); + bool rv = LLInventoryCategory::fromLLSD(category); localizeName(); return rv; } @@ -998,7 +998,7 @@ void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type) item->setPermissions(perm); - item->updateServer(FALSE); + item->updateServer(false); } } @@ -2141,7 +2141,7 @@ U32 LLViewerInventoryItem::getCRC32() const // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 static char getSeparator() { return '@'; } -BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) +bool LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) { using std::string; using std::stringstream; @@ -2149,7 +2149,7 @@ BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& na const char separator = getSeparator(); const string::size_type separatorPos = name.find(separator, 0); - BOOL result = FALSE; + BOOL result = false; if (separatorPos < string::npos) { @@ -2170,7 +2170,7 @@ BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& na *displayName = name.substr(separatorPos + 1, string::npos); } - result = TRUE; + result = true; } return result; @@ -2319,9 +2319,9 @@ BOOL LLViewerInventoryItem::regenerateLink() { LLViewerInventoryItem *item = (*item_iter); item->setAssetUUID(target_item_id); - item->updateServer(FALSE); + item->updateServer(false); gInventory.addChangedMask(LLInventoryObserver::REBUILD, item->getUUID()); } gInventory.notifyObservers(); - return TRUE; + return true; } -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llviewerinventory.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'indra/newview/llviewerinventory.cpp') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index eefe050d46..3082165538 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -298,7 +298,7 @@ public: return false; } LLUUID inventory_id; - if (!inventory_id.set(params[0], FALSE)) + if (!inventory_id.set(params[0], false)) { return false; } @@ -496,7 +496,7 @@ void LLViewerInventoryItem::fetchFromServer(void) const // virtual bool LLViewerInventoryItem::unpackMessage(const LLSD& item) { - BOOL rv = LLInventoryItem::fromLLSD(item); + bool rv = LLInventoryItem::fromLLSD(item); LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); @@ -507,7 +507,7 @@ bool LLViewerInventoryItem::unpackMessage(const LLSD& item) // virtual bool LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) { - BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num); + bool rv = LLInventoryItem::unpackMessage(msg, block, block_num); LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); @@ -802,7 +802,7 @@ bool LLViewerInventoryCategory::acceptItem(LLInventoryItem* inv_item) void LLViewerInventoryCategory::determineFolderType() { /* Do NOT uncomment this code. This is for future 2.1 support of ensembles. - llassert(FALSE); + llassert(false); LLFolderType::EType original_type = getPreferredType(); if (LLFolderType::lookupIsProtectedType(original_type)) return; @@ -811,7 +811,7 @@ void LLViewerInventoryCategory::determineFolderType() U64 folder_invalid = 0; LLInventoryModel::cat_array_t category_array; LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(getUUID(),category_array,item_array,FALSE); + gInventory.collectDescendents(getUUID(),category_array,item_array,false); // For ensembles if (category_array.empty()) @@ -846,7 +846,7 @@ void LLViewerInventoryCategory::determineFolderType() { changeType(LLFolderType::FT_NONE); } - llassert(FALSE); + llassert(false); */ } @@ -1034,7 +1034,7 @@ void create_gesture_cb(const LLUUID& inv_item) LLPreviewGesture* preview = LLPreviewGesture::show(inv_item, LLUUID::null); // Force to be entirely onscreen. - gFloaterView->adjustToFitScreen(preview, FALSE); + gFloaterView->adjustToFitScreen(preview, false); } } } @@ -1370,7 +1370,7 @@ void move_inventory_item( msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, agent_id); msg->addUUIDFast(_PREHASH_SessionID, session_id); - msg->addBOOLFast(_PREHASH_Stamp, FALSE); + msg->addBOOLFast(_PREHASH_Stamp, false); msg->nextBlockFast(_PREHASH_InventoryData); msg->addUUIDFast(_PREHASH_ItemID, item_id); msg->addUUIDFast(_PREHASH_FolderID, parent_id); @@ -1589,7 +1589,7 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) // Remove items from clipboard or it will remain active even if there is nothing to paste/copy LLInventoryModel::cat_array_t categories; LLInventoryModel::item_array_t items; - gInventory.collectDescendents(id, categories, items, TRUE); + gInventory.collectDescendents(id, categories, items, true); for (LLInventoryModel::cat_array_t::const_iterator it = categories.begin(); it != categories.end(); ++it) { @@ -1832,7 +1832,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLUUID dest_id, const L LLInventoryPanel* panel = static_cast(handle.get()); if (panel) { - panel->setSelectionByID(new_category_id, TRUE); + panel->setSelectionByID(new_category_id, true); } LL_DEBUGS(LOG_INV) << "Done creating inventory: " << new_category_id << LL_ENDL; }; @@ -1929,7 +1929,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLUUID dest_id, const L } if(panel) { - panel->getRootFolder()->setNeedsAutoRename(TRUE); + panel->getRootFolder()->setNeedsAutoRename(true); } } @@ -2149,7 +2149,7 @@ bool LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& na const char separator = getSeparator(); const string::size_type separatorPos = name.find(separator, 0); - BOOL result = false; + bool result = false; if (separatorPos < string::npos) { @@ -2235,9 +2235,9 @@ PermissionMask LLViewerInventoryItem::getPermissionMask() const { const LLPermissions& permissions = getPermissions(); - BOOL copy = permissions.allowCopyBy(gAgent.getID()); - BOOL mod = permissions.allowModifyBy(gAgent.getID()); - BOOL xfer = permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID()); + bool copy = permissions.allowCopyBy(gAgent.getID()); + bool mod = permissions.allowModifyBy(gAgent.getID()); + bool xfer = permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID()); PermissionMask perm_mask = 0; if (copy) perm_mask |= PERM_COPY; if (mod) perm_mask |= PERM_MODIFY; @@ -2300,11 +2300,11 @@ LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_i // This currently dosen't work, because the sim does not allow us // to change an item's assetID. -BOOL LLViewerInventoryItem::regenerateLink() +bool LLViewerInventoryItem::regenerateLink() { const LLUUID target_item_id = find_possible_item_for_regeneration(this); if (target_item_id.isNull()) - return FALSE; + return false; LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLAssetIDMatches asset_id_matches(getAssetUUID()); -- cgit v1.2.3 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/newview/llviewerinventory.cpp | 4664 +++++++++++++++++------------------ 1 file changed, 2332 insertions(+), 2332 deletions(-) (limited to 'indra/newview/llviewerinventory.cpp') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 33d31bf772..88f88d7436 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1,2332 +1,2332 @@ -/** - * @file llviewerinventory.cpp - * @brief Implementation of the viewer side inventory objects. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2014, 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 "llviewerprecompiledheaders.h" -#include "llviewerinventory.h" - -#include "llnotificationsutil.h" -#include "llsdserialize.h" -#include "message.h" - -#include "llaisapi.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "llagentwearables.h" -#include "llfloatersidepanelcontainer.h" -#include "llviewerfoldertype.h" -#include "llfloatersidepanelcontainer.h" -#include "llfolderview.h" -#include "llviewercontrol.h" -#include "llconsole.h" -#include "llinventorydefines.h" -#include "llinventoryfunctions.h" -#include "llinventorymodel.h" -#include "llinventorymodelbackgroundfetch.h" -#include "llgesturemgr.h" - -#include "llinventorybridge.h" -#include "llinventorypanel.h" -#include "lllandmarkactions.h" - -#include "llviewerassettype.h" -#include "llviewerregion.h" -#include "llviewerobjectlist.h" -#include "llpreviewgesture.h" -#include "llviewerwindow.h" -#include "lltrans.h" -#include "llappearancemgr.h" -#include "llcommandhandler.h" -#include "llviewermessage.h" -#include "llpanelmaininventory.h" -#include "llsidepanelappearance.h" -#include "llsidepanelinventory.h" -#include "llavatarnamecache.h" -#include "llavataractions.h" -#include "lllogininstance.h" -#include "llfavoritesbar.h" -#include "llfloaterperms.h" -#include "llclipboard.h" -#include "llhttpretrypolicy.h" -#include "llsettingsvo.h" - -// do-nothing ops for use in callbacks. -void no_op_inventory_func(const LLUUID&) {} -void no_op_llsd_func(const LLSD&) {} -void no_op() {} - -static const char * const LOG_INV("Inventory"); -static const char * const LOG_LOCAL("InventoryLocalize"); -static const char * const LOG_NOTECARD("copy_inventory_from_notecard"); - -static const std::string INV_OWNER_ID("owner_id"); -static const std::string INV_VERSION("version"); - -#if 1 -// *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model. -// temp code in transition -void doInventoryCb(LLPointer cb, LLUUID id) -{ - if (cb.notNull()) - cb->fire(id); -} -#endif - -///---------------------------------------------------------------------------- -/// Helper class to store special inventory item names and their localized values. -///---------------------------------------------------------------------------- -class LLLocalizedInventoryItemsDictionary : public LLSingleton -{ - LLSINGLETON(LLLocalizedInventoryItemsDictionary); -public: - std::map mInventoryItemsDict; - - /** - * Finds passed name in dictionary and replaces it with found localized value. - * - * @param object_name - string to be localized. - * @return true if passed name was found and localized, false otherwise. - */ - bool localizeInventoryObjectName(std::string& object_name) - { - LL_DEBUGS(LOG_LOCAL) << "Searching for localization: " << object_name << LL_ENDL; - - std::map::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name); - - bool found = dictionary_iter != mInventoryItemsDict.end(); - if(found) - { - object_name = dictionary_iter->second; - LL_DEBUGS(LOG_LOCAL) << "Found, new name is: " << object_name << LL_ENDL; - } - return found; - } -}; - -LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary() -{ - mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape"); - mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin"); - mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair"); - mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes"); - mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt"); - mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants"); - mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes"); - mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks"); - mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket"); - mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves"); - mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt"); - mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants"); - mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt"); - mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha"); - mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo"); - mInventoryItemsDict["New Universal"] = LLTrans::getString("New Universal"); - mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics"); - mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); - - mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture"); - mInventoryItemsDict["New Material"] = LLTrans::getString("New Material"); - mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); - mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); - mInventoryItemsDict["New Note"] = LLTrans::getString("New Note"); - mInventoryItemsDict["Contents"] = LLTrans::getString("Contents"); - - mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture"); - mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures"); - mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures"); - mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures"); - mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures"); - mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures"); - - //predefined gestures - - //male - mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me"); - mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319 - mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss"); - mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo"); - mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored"); - mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey"); - mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh"); - mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed"); - mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug"); - mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out"); - mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow"); - - //female - mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle"); - mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry"); - mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed"); - mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me"); - mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319 - mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss"); - mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo"); - mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored"); - mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey"); - mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby"); - mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh"); - mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good"); - mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here"); - mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please"); - mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed"); - mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug"); - mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); - mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow"); - - //common - mInventoryItemsDict["/bow"] = LLTrans::getString("/bow"); - mInventoryItemsDict["/clap"] = LLTrans::getString("/clap"); - mInventoryItemsDict["/count"] = LLTrans::getString("/count"); - mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish"); - mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb"); - mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle"); - mInventoryItemsDict["/no"] = LLTrans::getString("/no"); - mInventoryItemsDict["/no!"] = LLTrans::getString("/no!"); - mInventoryItemsDict["/paper"] = LLTrans::getString("/paper"); - mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme"); - mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou"); - mInventoryItemsDict["/rock"] = LLTrans::getString("/rock"); - mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor"); - mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke"); - mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch"); - mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle"); - mInventoryItemsDict["/yes"] = LLTrans::getString("/yes"); - mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!"); - mInventoryItemsDict["afk"] = LLTrans::getString("afk"); - mInventoryItemsDict["dance1"] = LLTrans::getString("dance1"); - mInventoryItemsDict["dance2"] = LLTrans::getString("dance2"); - mInventoryItemsDict["dance3"] = LLTrans::getString("dance3"); - mInventoryItemsDict["dance4"] = LLTrans::getString("dance4"); - mInventoryItemsDict["dance5"] = LLTrans::getString("dance5"); - mInventoryItemsDict["dance6"] = LLTrans::getString("dance6"); - mInventoryItemsDict["dance7"] = LLTrans::getString("dance7"); - mInventoryItemsDict["dance8"] = LLTrans::getString("dance8"); -} - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -class LLInventoryHandler : public LLCommandHandler -{ -public: - LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { } - - virtual bool canHandleUntrusted( - const LLSD& params, - const LLSD& query_map, - LLMediaCtrl* web, - const std::string& nav_type) - { - if (params.size() < 1) - { - return true; // don't block, will fail later - } - - if (nav_type == NAV_TYPE_CLICKED - || nav_type == NAV_TYPE_EXTERNAL) - { - // NAV_TYPE_EXTERNAL will be throttled - return true; - } - - return false; - } - - bool handle(const LLSD& params, - const LLSD& query_map, - const std::string& grid, - LLMediaCtrl* web) - { - if (params.size() < 1) - { - return false; - } - - if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableInventory")) - { - LLNotificationsUtil::add("NoInventory", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); - return true; - } - - // support secondlife:///app/inventory/show - if (params[0].asString() == "show") - { - LLFloaterSidePanelContainer::showPanel("inventory", LLSD()); - return true; - } - - if (params[0].asString() == "filters") - { - LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); - if (sidepanel_inventory) - { - LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); - if (main_inventory) - { - main_inventory->toggleFindOptions(); - } - } - return true; - } - - // otherwise, we need a UUID and a verb... - if (params.size() < 2) - { - return false; - } - LLUUID inventory_id; - if (!inventory_id.set(params[0], false)) - { - return false; - } - - const std::string verb = params[1].asString(); - if (verb == "select") - { - uuid_vec_t items_to_open; - items_to_open.push_back(inventory_id); - //inventory_handler is just a stub, because we don't know from who this offer - open_inventory_offer(items_to_open, "inventory_handler"); - return true; - } - - return false; - } -}; -LLInventoryHandler gInventoryHandler; - -///---------------------------------------------------------------------------- -/// Class LLViewerInventoryItem -///---------------------------------------------------------------------------- - -LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& uuid, - const LLUUID& parent_uuid, - const LLPermissions& perm, - 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, - time_t creation_date_utc) : - LLInventoryItem(uuid, parent_uuid, perm, asset_uuid, type, inv_type, - name, desc, sale_info, flags, creation_date_utc), - mIsComplete(true) -{ -} - -LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& item_id, - const LLUUID& parent_id, - const std::string& name, - LLInventoryType::EType inv_type) : - LLInventoryItem(), - mIsComplete(false) -{ - mUUID = item_id; - mParentUUID = parent_id; - mInventoryType = inv_type; - mName = name; -} - -LLViewerInventoryItem::LLViewerInventoryItem() : - LLInventoryItem(), - mIsComplete(false) -{ -} - -LLViewerInventoryItem::LLViewerInventoryItem(const LLViewerInventoryItem* other) : - LLInventoryItem() -{ - copyViewerItem(other); - if (!mIsComplete) - { - LL_WARNS(LOG_INV) << "LLViewerInventoryItem copy constructor for incomplete item" - << mUUID << LL_ENDL; - } -} - -LLViewerInventoryItem::LLViewerInventoryItem(const LLInventoryItem *other) : - LLInventoryItem(other), - mIsComplete(true) -{ -} - - -LLViewerInventoryItem::~LLViewerInventoryItem() -{ -} - -void LLViewerInventoryItem::copyViewerItem(const LLViewerInventoryItem* other) -{ - LLInventoryItem::copyItem(other); - mIsComplete = other->mIsComplete; - mTransactionID = other->mTransactionID; -} - -// virtual -void LLViewerInventoryItem::copyItem(const LLInventoryItem *other) -{ - LLInventoryItem::copyItem(other); - mIsComplete = true; - mTransactionID.setNull(); -} - -void LLViewerInventoryItem::cloneViewerItem(LLPointer& newitem) const -{ - newitem = new LLViewerInventoryItem(this); - if(newitem.notNull()) - { - LLUUID item_id; - item_id.generate(); - newitem->setUUID(item_id); - } -} - -void LLViewerInventoryItem::updateServer(bool is_new) const -{ - if(!mIsComplete) - { - // *FIX: deal with this better. - // If we're crashing here then the UI is incorrectly enabled. - LL_ERRS(LOG_INV) << "LLViewerInventoryItem::updateServer() - for incomplete item" - << LL_ENDL; - return; - } - if(gAgent.getID() != mPermissions.getOwner()) - { - // *FIX: deal with this better. - LL_WARNS(LOG_INV) << "LLViewerInventoryItem::updateServer() - for unowned item " - << ll_pretty_print_sd(this->asLLSD()) - << LL_ENDL; - return; - } - LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); - gInventory.accountForUpdate(up); - - LLSD updates = asLLSD(); - // Replace asset_id and/or shadow_id with transaction_id (hash_id) - if (updates.has("asset_id")) - { - updates.erase("asset_id"); - if(getTransactionID().notNull()) - { - updates["hash_id"] = getTransactionID(); - } - } - if (updates.has("shadow_id")) - { - updates.erase("shadow_id"); - if(getTransactionID().notNull()) - { - updates["hash_id"] = getTransactionID(); - } - } - AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer)NULL, _1); - AISAPI::UpdateItem(getUUID(), updates, cr); -} - -void LLViewerInventoryItem::fetchFromServer(void) const -{ - if(!mIsComplete) - { - if (AISAPI::isAvailable()) // AIS v 3 - { - LLInventoryModelBackgroundFetch::getInstance()->scheduleItemFetch(mUUID); - } - else - { - std::string url; - - LLViewerRegion* region = gAgent.getRegion(); - // we have to check region. It can be null after region was destroyed. See EXT-245 - if (region) - { - if (gAgent.getID() != mPermissions.getOwner()) - { - url = region->getCapability("FetchLib2"); - } - else - { - url = region->getCapability("FetchInventory2"); - } - } - else - { - LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL; - } - - if (!url.empty()) - { - LLSD body; - body["agent_id"] = gAgent.getID(); - body["items"][0]["owner_id"] = mPermissions.getOwner(); - body["items"][0]["item_id"] = mUUID; - - LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body)); - gInventory.requestPost(true, url, body, handler, "Inventory Item"); - } - } - } -} - -// virtual -bool LLViewerInventoryItem::unpackMessage(const LLSD& item) -{ - bool rv = LLInventoryItem::fromLLSD(item); - - LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); - - mIsComplete = true; - return rv; -} - -// virtual -bool LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) -{ - bool rv = LLInventoryItem::unpackMessage(msg, block, block_num); - - LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); - - mIsComplete = true; - return rv; -} - -void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_id) -{ - mTransactionID = transaction_id; -} - -void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const -{ - msg->addUUIDFast(_PREHASH_ItemID, mUUID); - msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); - mPermissions.packMessage(msg); - msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID); - 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, mCreationDate); - U32 crc = getCRC32(); - msg->addU32Fast(_PREHASH_CRC, crc); -} - -// virtual -bool LLViewerInventoryItem::importLegacyStream(std::istream& input_stream) -{ - bool rv = LLInventoryItem::importLegacyStream(input_stream); - mIsComplete = true; - return rv; -} - -void LLViewerInventoryItem::updateParentOnServer(bool restamp) const -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOLFast(_PREHASH_Stamp, restamp); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, mUUID); - msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); - msg->addString("NewName", NULL); - gAgent.sendReliableMessage(); -} - -//void LLViewerInventoryItem::setCloneCount(S32 clones) -//{ -// mClones = clones; -//} - -//S32 LLViewerInventoryItem::getCloneCount() const -//{ -// return mClones; -//} - -///---------------------------------------------------------------------------- -/// Class LLViewerInventoryCategory -///---------------------------------------------------------------------------- - -LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid, - const LLUUID& parent_uuid, - LLFolderType::EType pref, - const std::string& name, - const LLUUID& owner_id) : - LLInventoryCategory(uuid, parent_uuid, pref, name), - mOwnerID(owner_id), - mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), - mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN), - mFetching(FETCH_NONE) -{ - mDescendentsRequested.reset(); -} - -LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& owner_id) : - mOwnerID(owner_id), - mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), - mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN), - mFetching(FETCH_NONE) -{ - mDescendentsRequested.reset(); -} - -LLViewerInventoryCategory::LLViewerInventoryCategory(const LLViewerInventoryCategory* other) -{ - copyViewerCategory(other); - mFetching = FETCH_NONE; -} - -LLViewerInventoryCategory::~LLViewerInventoryCategory() -{ -} - -void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCategory* other) -{ - copyCategory(other); - mOwnerID = other->mOwnerID; - setVersion(other->getVersion()); - mDescendentCount = other->mDescendentCount; - mDescendentsRequested = other->mDescendentsRequested; -} - - -void LLViewerInventoryCategory::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); -} - -void LLViewerInventoryCategory::updateParentOnServer(bool restamp) const -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->addBOOL("Stamp", restamp); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_FolderID, mUUID); - msg->addUUIDFast(_PREHASH_ParentID, mParentUUID); - gAgent.sendReliableMessage(); -} - -void LLViewerInventoryCategory::updateServer(bool is_new) const -{ - // communicate that change with the server. - - if (LLFolderType::lookupIsProtectedType(mPreferredType)) - { - LLNotificationsUtil::add("CannotModifyProtectedCategories"); - return; - } - - LLSD new_llsd = asLLSD(); - AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer)NULL, _1); - AISAPI::UpdateCategory(getUUID(), new_llsd, cr); -} - -S32 LLViewerInventoryCategory::getVersion() const -{ - return mVersion; -} - -void LLViewerInventoryCategory::setVersion(S32 version) -{ - mVersion = version; -} - -bool LLViewerInventoryCategory::fetch(S32 expiry_seconds) -{ - if((VERSION_UNKNOWN == getVersion()) - && mDescendentsRequested.hasExpired()) //Expired check prevents multiple downloads. - { - LL_DEBUGS(LOG_INV) << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL; - mDescendentsRequested.reset(); - mDescendentsRequested.setTimerExpirySec(expiry_seconds); - - std::string url; - if (gAgent.getRegion()) - { - url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2"); - } - else - { - LL_WARNS_ONCE(LOG_INV) << "agent region is null" << LL_ENDL; - } - if (!url.empty() || AISAPI::isAvailable()) - { - LLInventoryModelBackgroundFetch::instance().start(mUUID, false); - } - return true; - } - return false; -} - -LLViewerInventoryCategory::EFetchType LLViewerInventoryCategory::getFetching() -{ - // if timer hasn't expired, request was scheduled, but not in progress - // if mFetching request was actually started - if (mDescendentsRequested.hasExpired()) - { - mFetching = FETCH_NONE; - } - return mFetching; -} - -void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchType fetching) -{ - if (fetching == FETCH_FAILED) - { - const F32 FETCH_FAILURE_EXPIRY = 60.0f; - mDescendentsRequested.setTimerExpirySec(FETCH_FAILURE_EXPIRY); - mFetching = fetching; - } - else if (fetching > mFetching) // allow a switch from normal to recursive - { - if (mDescendentsRequested.hasExpired() || (mFetching == FETCH_NONE)) - { - mDescendentsRequested.reset(); - if (AISAPI::isAvailable()) - { - mDescendentsRequested.setTimerExpirySec(AISAPI::HTTP_TIMEOUT); - } - else - { - const F32 FETCH_TIMER_EXPIRY = 30.0f; - mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); - } - } - mFetching = fetching; - } - else if (fetching == FETCH_NONE) - { - mDescendentsRequested.stop(); - mFetching = fetching; - } -} - -S32 LLViewerInventoryCategory::getViewerDescendentCount() const -{ - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - gInventory.getDirectDescendentsOf(getUUID(), cats, items); - S32 descendents_actual = 0; - if(cats && items) - { - descendents_actual = cats->size() + items->size(); - } - return descendents_actual; -} - -LLSD LLViewerInventoryCategory::exportLLSD() const -{ - LLSD cat_data = LLInventoryCategory::exportLLSD(); - cat_data[INV_OWNER_ID] = mOwnerID; - cat_data[INV_VERSION] = mVersion; - - return cat_data; -} - -bool LLViewerInventoryCategory::importLLSD(const LLSD& cat_data) -{ - LLInventoryCategory::importLLSD(cat_data); - if (cat_data.has(INV_OWNER_ID)) - { - mOwnerID = cat_data[INV_OWNER_ID].asUUID(); - } - if (cat_data.has(INV_VERSION)) - { - setVersion(cat_data[INV_VERSION].asInteger()); - } - return true; -} - -bool LLViewerInventoryCategory::acceptItem(LLInventoryItem* inv_item) -{ - if (!inv_item) - { - return false; - } - - // Only stock folders have limitation on which item they will accept - bool accept = true; - if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) - { - // If the item is copyable (i.e. non stock) do not accept the drop in a stock folder - if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) - { - accept = false; - } - else - { - LLInventoryModel::cat_array_t* cat_array; - LLInventoryModel::item_array_t* item_array; - gInventory.getDirectDescendentsOf(getUUID(),cat_array,item_array); - // Destination stock folder must be empty OR types of incoming and existing items must be identical and have the same permissions - accept = (!item_array->size() || - ((item_array->at(0)->getInventoryType() == inv_item->getInventoryType()) && - (item_array->at(0)->getPermissions().getMaskNextOwner() == inv_item->getPermissions().getMaskNextOwner()))); - } - } - return accept; -} - -void LLViewerInventoryCategory::determineFolderType() -{ - /* Do NOT uncomment this code. This is for future 2.1 support of ensembles. - llassert(false); - LLFolderType::EType original_type = getPreferredType(); - if (LLFolderType::lookupIsProtectedType(original_type)) - return; - - U64 folder_valid = 0; - U64 folder_invalid = 0; - LLInventoryModel::cat_array_t category_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(getUUID(),category_array,item_array,false); - - // For ensembles - if (category_array.empty()) - { - for (LLInventoryModel::item_array_t::iterator item_iter = item_array.begin(); - item_iter != item_array.end(); - item_iter++) - { - const LLViewerInventoryItem *item = (*item_iter); - if (item->getIsLinkType()) - return; - if (item->isWearableType()) - { - const LLWearableType::EType wearable_type = item->getWearableType(); - const std::string& wearable_name = LLWearableType::getTypeName(wearable_type); - U64 valid_folder_types = LLViewerFolderType::lookupValidFolderTypes(wearable_name); - folder_valid |= valid_folder_types; - folder_invalid |= ~valid_folder_types; - } - } - for (U8 i = LLFolderType::FT_ENSEMBLE_START; i <= LLFolderType::FT_ENSEMBLE_END; i++) - { - if ((folder_valid & (1LL << i)) && - !(folder_invalid & (1LL << i))) - { - changeType((LLFolderType::EType)i); - return; - } - } - } - if (LLFolderType::lookupIsEnsembleType(original_type)) - { - changeType(LLFolderType::FT_NONE); - } - llassert(false); - */ -} - -void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type) -{ - const LLUUID &folder_id = getUUID(); - const LLUUID &parent_id = getParentUUID(); - const std::string &name = getName(); - - LLPointer new_cat = new LLViewerInventoryCategory(folder_id, - parent_id, - new_folder_type, - name, - gAgent.getID()); - - - LLSD new_llsd = new_cat->asLLSD(); - AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer) NULL, _1); - AISAPI::UpdateCategory(folder_id, new_llsd, cr); - - setPreferredType(new_folder_type); - gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id); -} - -void LLViewerInventoryCategory::localizeName() -{ - LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); -} - -// virtual -bool LLViewerInventoryCategory::unpackMessage(const LLSD& category) -{ - bool rv = LLInventoryCategory::fromLLSD(category); - localizeName(); - return rv; -} - -// virtual -void LLViewerInventoryCategory::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) -{ - LLInventoryCategory::unpackMessage(msg, block, block_num); - localizeName(); -} - -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- - -LLInventoryCallbackManager *LLInventoryCallbackManager::sInstance = NULL; - -LLInventoryCallbackManager::LLInventoryCallbackManager() : - mLastCallback(0) -{ - if( sInstance != NULL ) - { - LL_WARNS(LOG_INV) << "LLInventoryCallbackManager::LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; - return; - } - sInstance = this; -} - -LLInventoryCallbackManager::~LLInventoryCallbackManager() -{ - if( sInstance != this ) - { - LL_WARNS(LOG_INV) << "LLInventoryCallbackManager::~LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; - return; - } - sInstance = NULL; -} - -//static -void LLInventoryCallbackManager::destroyClass() -{ - if (sInstance) - { - for (callback_map_t::iterator it = sInstance->mMap.begin(), end_it = sInstance->mMap.end(); it != end_it; ++it) - { - // drop LLPointer reference to callback - it->second = NULL; - } - sInstance->mMap.clear(); - } -} - - -U32 LLInventoryCallbackManager::registerCB(LLPointer cb) -{ - if (cb.isNull()) - return 0; - - mLastCallback++; - if (!mLastCallback) - mLastCallback++; - - mMap[mLastCallback] = cb; - return mLastCallback; -} - -void LLInventoryCallbackManager::fire(U32 callback_id, const LLUUID& item_id) -{ - if (!callback_id || item_id.isNull()) - return; - - std::map >::iterator i; - - i = mMap.find(callback_id); - if (i != mMap.end()) - { - (*i).second->fire(item_id); - mMap.erase(i); - } -} - -void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp) -{ - if (inv_item.isNull()) - return; - - LLViewerInventoryItem *item = gInventory.getItem(inv_item); - if (item) - { - rez_attachment(item, attachmentp); - } -} - -void activate_gesture_cb(const LLUUID& inv_item) -{ - if (inv_item.isNull()) - return; - LLViewerInventoryItem* item = gInventory.getItem(inv_item); - if (!item) - return; - if (item->getType() != LLAssetType::AT_GESTURE) - return; - - LLGestureMgr::instance().activateGesture(inv_item); -} - -void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type) -{ - llassert(item); - LLPermissions perm = item->getPermissions(); - if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type) - || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type)) - { - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type)); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type)); - - item->setPermissions(perm); - - item->updateServer(false); - } -} - -void create_script_cb(const LLUUID& inv_item) -{ - if (!inv_item.isNull()) - { - LLViewerInventoryItem* item = gInventory.getItem(inv_item); - if (item) - { - set_default_permissions(item, "Scripts"); - - // item was just created, update even if permissions did not changed - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - } -} - -void create_gesture_cb(const LLUUID& inv_item) -{ - if (!inv_item.isNull()) - { - LLGestureMgr::instance().activateGesture(inv_item); - - LLViewerInventoryItem* item = gInventory.getItem(inv_item); - if (item) - { - set_default_permissions(item, "Gestures"); - - gInventory.updateItem(item); - gInventory.notifyObservers(); - - LLPreviewGesture* preview = LLPreviewGesture::show(inv_item, LLUUID::null); - // Force to be entirely onscreen. - gFloaterView->adjustToFitScreen(preview, false); - } - } -} - - -void create_notecard_cb(const LLUUID& inv_item) -{ - if (!inv_item.isNull()) - { - LLViewerInventoryItem* item = gInventory.getItem(inv_item); - if (item) - { - set_default_permissions(item, "Notecards"); - - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - } -} - -void create_gltf_material_cb(const LLUUID& inv_item) -{ - if (!inv_item.isNull()) - { - LLViewerInventoryItem* item = gInventory.getItem(inv_item); - if (item) - { - set_default_permissions(item, "Materials"); - - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - } -} - -LLInventoryCallbackManager gInventoryCallbacks; - -void create_inventory_item( - const LLUUID& agent_id, - const LLUUID& session_id, - const LLUUID& parent_id, - const LLTransactionID& transaction_id, - const std::string& name, - const std::string& desc, - LLAssetType::EType asset_type, - LLInventoryType::EType inv_type, - U8 subtype, - U32 next_owner_perm, - LLPointer cb) -{ - //check if name is equal to one of special inventory items names - //EXT-5839 - std::string server_name = name; - - { - std::map::const_iterator dictionary_iter; - - for (dictionary_iter = LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.begin(); - dictionary_iter != LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.end(); - dictionary_iter++) - { - const std::string& localized_name = dictionary_iter->second; - if(localized_name == name) - { - server_name = dictionary_iter->first; - } - } - } - -#ifdef USE_AIS_FOR_NC - // D567 18.03.2023 not yet implemented within AIS3 - if (AISAPI::isAvailable()) - { - LLSD new_inventory = LLSD::emptyMap(); - new_inventory["items"] = LLSD::emptyArray(); - - LLPermissions perms; - perms.init( - gAgentID, - gAgentID, - LLUUID::null, - LLUUID::null); - perms.initMasks( - PERM_ALL, - PERM_ALL, - PERM_NONE, - PERM_NONE, - next_owner_perm); - - LLUUID null_id; - LLPointer item = new LLViewerInventoryItem( - null_id, /*don't know yet*/ - parent_id, - perms, - null_id, /*don't know yet*/ - asset_type, - inv_type, - server_name, - desc, - LLSaleInfo(), - 0, - 0 /*don't know yet, whenever server creates it*/); - LLSD item_sd = item->asLLSD(); - new_inventory["items"].append(item_sd); - AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); - AISAPI::CreateInventory( - parent_id, - new_inventory, - cr); - return; - } - else - { - LL_WARNS() << "AIS v3 not available" << LL_ENDL; - } -#endif - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_CreateInventoryItem); - msg->nextBlock(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agent_id); - msg->addUUIDFast(_PREHASH_SessionID, session_id); - msg->nextBlock(_PREHASH_InventoryBlock); - msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb)); - msg->addUUIDFast(_PREHASH_FolderID, parent_id); - msg->addUUIDFast(_PREHASH_TransactionID, transaction_id); - msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_perm); - msg->addS8Fast(_PREHASH_Type, (S8)asset_type); - msg->addS8Fast(_PREHASH_InvType, (S8)inv_type); - msg->addU8Fast(_PREHASH_WearableType, (U8)subtype); - msg->addStringFast(_PREHASH_Name, server_name); - msg->addStringFast(_PREHASH_Description, desc); - - gAgent.sendReliableMessage(); -} - -void create_inventory_callingcard_callback(LLPointer cb, - const LLUUID &parent, - const LLUUID &avatar_id, - const LLAvatarName &av_name) -{ - std::string item_desc = avatar_id.asString(); - create_inventory_item(gAgent.getID(), - gAgent.getSessionID(), - parent, - LLTransactionID::tnull, - av_name.getUserName(), - item_desc, - LLAssetType::AT_CALLINGCARD, - LLInventoryType::IT_CALLINGCARD, - NO_INV_SUBTYPE, - PERM_MOVE | PERM_TRANSFER, - cb); -} - -void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer cb/*=NULL*/) -{ - LLAvatarName av_name; - LLAvatarNameCache::get(avatar_id, boost::bind(&create_inventory_callingcard_callback, cb, parent, _1, _2)); -} - -void create_inventory_wearable(const LLUUID& agent_id, const LLUUID& session_id, - const LLUUID& parent, const LLTransactionID& transaction_id, - const std::string& name, - const std::string& desc, LLAssetType::EType asset_type, - LLWearableType::EType wtype, - U32 next_owner_perm, - LLPointer cb) -{ - create_inventory_item(agent_id, session_id, parent, transaction_id, - name, desc, asset_type, LLInventoryType::IT_WEARABLE, static_cast(wtype), - next_owner_perm, cb); -} - -void create_inventory_settings(const LLUUID& agent_id, const LLUUID& session_id, - const LLUUID& parent, const LLTransactionID& transaction_id, - const std::string& name, - const std::string& desc, - LLSettingsType::type_e settype, - U32 next_owner_perm, - LLPointer cb) -{ - create_inventory_item(agent_id, session_id, parent, transaction_id, - name, desc, LLAssetType::AT_SETTINGS, LLInventoryType::IT_SETTINGS, - static_cast(settype), next_owner_perm, cb); -} - - -void copy_inventory_item( - const LLUUID& agent_id, - const LLUUID& current_owner, - const LLUUID& item_id, - const LLUUID& parent_id, - const std::string& new_name, - LLPointer cb) -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_CopyInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agent_id); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb)); - msg->addUUIDFast(_PREHASH_OldAgentID, current_owner); - msg->addUUIDFast(_PREHASH_OldItemID, item_id); - msg->addUUIDFast(_PREHASH_NewFolderID, parent_id); - msg->addStringFast(_PREHASH_NewName, new_name); - gAgent.sendReliableMessage(); -} - -// Create link to single inventory object. -void link_inventory_object(const LLUUID& category, - LLConstPointer baseobj, - LLPointer cb) -{ - if (!baseobj) - { - LL_WARNS(LOG_INV) << "Attempt to link to non-existent object" << LL_ENDL; - return; - } - - LLInventoryObject::const_object_list_t obj_array; - obj_array.push_back(baseobj); - link_inventory_array(category, obj_array, cb); -} - -void link_inventory_object(const LLUUID& category, - const LLUUID& id, - LLPointer cb) -{ - LLConstPointer baseobj = gInventory.getObject(id); - link_inventory_object(category, baseobj, cb); -} - -// Create links to all listed inventory objects. -void link_inventory_array(const LLUUID& category, - LLInventoryObject::const_object_list_t& baseobj_array, - LLPointer cb) -{ -#ifndef LL_RELEASE_FOR_DOWNLOAD - const LLViewerInventoryCategory *cat = gInventory.getCategory(category); - const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND"; -#endif - LLInventoryObject::const_object_list_t::const_iterator it = baseobj_array.begin(); - LLInventoryObject::const_object_list_t::const_iterator end = baseobj_array.end(); - LLSD links = LLSD::emptyArray(); - for (; it != end; ++it) - { - const LLInventoryObject* baseobj = *it; - if (!baseobj) - { - LL_WARNS(LOG_INV) << "attempt to link to unknown object" << LL_ENDL; - continue; - } - - if (!LLAssetType::lookupCanLink(baseobj->getType())) - { - // Fail if item can be found but is of a type that can't be linked. - // Arguably should fail if the item can't be found too, but that could - // be a larger behavioral change. - LL_WARNS(LOG_INV) << "attempt to link an unlinkable object, type = " << baseobj->getActualType() << LL_ENDL; - continue; - } - - LLInventoryType::EType inv_type = LLInventoryType::IT_NONE; - LLAssetType::EType asset_type = LLAssetType::AT_NONE; - std::string new_desc; - LLUUID linkee_id; - if (dynamic_cast(baseobj)) - { - inv_type = LLInventoryType::IT_CATEGORY; - asset_type = LLAssetType::AT_LINK_FOLDER; - linkee_id = baseobj->getUUID(); - } - else - { - const LLViewerInventoryItem *baseitem = dynamic_cast(baseobj); - if (baseitem) - { - inv_type = baseitem->getInventoryType(); - new_desc = baseitem->getActualDescription(); - switch (baseitem->getActualType()) - { - case LLAssetType::AT_LINK: - case LLAssetType::AT_LINK_FOLDER: - linkee_id = baseobj->getLinkedUUID(); - asset_type = baseitem->getActualType(); - break; - default: - linkee_id = baseobj->getUUID(); - asset_type = LLAssetType::AT_LINK; - break; - } - } - else - { - LL_WARNS(LOG_INV) << "could not convert object into an item or category: " << baseobj->getUUID() << LL_ENDL; - continue; - } - } - - LLSD link = LLSD::emptyMap(); - link["linked_id"] = linkee_id; - link["type"] = (S8)asset_type; - link["inv_type"] = (S8)inv_type; - link["name"] = baseobj->getName(); - link["desc"] = new_desc; - links.append(link); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS(LOG_INV) << "Linking Object [ name:" << baseobj->getName() - << " UUID:" << baseobj->getUUID() - << " ] into Category [ name:" << cat_name - << " UUID:" << category << " ] " << LL_ENDL; -#endif - } - LLSD new_inventory = LLSD::emptyMap(); - new_inventory["links"] = links; - AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); - AISAPI::CreateInventory(category, new_inventory, cr); -} - -void move_inventory_item( - const LLUUID& agent_id, - const LLUUID& session_id, - const LLUUID& item_id, - const LLUUID& parent_id, - const std::string& new_name, - LLPointer cb) -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agent_id); - msg->addUUIDFast(_PREHASH_SessionID, session_id); - msg->addBOOLFast(_PREHASH_Stamp, false); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, item_id); - msg->addUUIDFast(_PREHASH_FolderID, parent_id); - msg->addStringFast(_PREHASH_NewName, new_name); - gAgent.sendReliableMessage(); -} - -// Should call this with an update_item that's been copied and -// modified from an original source item, rather than modifying the -// source item directly. -void update_inventory_item( - LLViewerInventoryItem *update_item, - LLPointer cb) -{ - const LLUUID& item_id = update_item->getUUID(); - - LLSD updates = update_item->asLLSD(); - // Replace asset_id and/or shadow_id with transaction_id (hash_id) - if (updates.has("asset_id")) - { - updates.erase("asset_id"); - if (update_item->getTransactionID().notNull()) - { - updates["hash_id"] = update_item->getTransactionID(); - } - } - if (updates.has("shadow_id")) - { - updates.erase("shadow_id"); - if (update_item->getTransactionID().notNull()) - { - updates["hash_id"] = update_item->getTransactionID(); - } - } - AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); - AISAPI::UpdateItem(item_id, updates, cr); -} - -// Note this only supports updating an existing item. Goes through AISv3 -// code path where available. Not all uses of item->updateServer() can -// easily be switched to this paradigm. -void update_inventory_item( - const LLUUID& item_id, - const LLSD& updates, - LLPointer cb) -{ - AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); - AISAPI::UpdateItem(item_id, updates, cr); -} - -void update_inventory_category( - const LLUUID& cat_id, - const LLSD& updates, - LLPointer cb) -{ - LLPointer obj = gInventory.getCategory(cat_id); - LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; - if(obj) - { - if (LLFolderType::lookupIsProtectedType(obj->getPreferredType()) - && (updates.size() != 1 || !updates.has("thumbnail"))) - { - LLNotificationsUtil::add("CannotModifyProtectedCategories"); - return; - } - - AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); - AISAPI::UpdateCategory(cat_id, updates, cr); - } -} - -void remove_inventory_items( - LLInventoryObject::object_list_t& items_to_kill, - LLPointer cb - ) -{ - for (LLInventoryObject::object_list_t::iterator it = items_to_kill.begin(); - it != items_to_kill.end(); - ++it) - { - remove_inventory_item(*it, cb); - } -} - -void remove_inventory_item( - const LLUUID& item_id, - LLPointer cb, - bool immediate_delete) -{ - LLPointer obj = gInventory.getItem(item_id); - if (obj) - { - remove_inventory_item(obj, cb, immediate_delete); - } - else - { - LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << LL_ENDL; - } -} - -void remove_inventory_item( - LLPointer obj, - LLPointer cb, - bool immediate_delete) -{ - if(obj) - { - const LLUUID item_id(obj->getUUID()); - LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL; - if (AISAPI::isAvailable()) - { - AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); - AISAPI::RemoveItem(item_id, cr); - - if (immediate_delete) - { - gInventory.onObjectDeletedFromServer(item_id); - } - } - else - { - LL_WARNS(LOG_INV) << "Tried to use inventory without AIS API" << LL_ENDL; - } - } - else - { - // *TODO: Clean up callback? - LL_WARNS(LOG_INV) << "remove_inventory_item called for invalid or nonexistent item." << LL_ENDL; - } -} - -class LLRemoveCategoryOnDestroy: public LLInventoryCallback -{ -public: - LLRemoveCategoryOnDestroy(const LLUUID& cat_id, LLPointer cb): - mID(cat_id), - mCB(cb) - { - } - /* virtual */ void fire(const LLUUID& item_id) {} - ~LLRemoveCategoryOnDestroy() - { - LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(mID); - if(children != LLInventoryModel::CHILDREN_NO) - { - LL_WARNS(LOG_INV) << "remove descendents failed, cannot remove category " << LL_ENDL; - } - else - { - remove_inventory_category(mID, mCB); - } - } -private: - LLUUID mID; - LLPointer mCB; -}; - -void remove_inventory_category( - const LLUUID& cat_id, - LLPointer cb) -{ - LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] " << LL_ENDL; - LLPointer obj = gInventory.getCategory(cat_id); - if(obj) - { - if (!gInventory.isCategoryComplete(cat_id)) - { - LL_WARNS() << "Removing (purging) incomplete category " << obj->getName() << LL_ENDL; - } - if(LLFolderType::lookupIsProtectedType(obj->getPreferredType())) - { - LLNotificationsUtil::add("CannotRemoveProtectedCategories"); - return; - } - AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); - AISAPI::RemoveCategory(cat_id, cr); - } - else - { - LL_WARNS(LOG_INV) << "remove_inventory_category called for invalid or nonexistent item " << cat_id << LL_ENDL; - } -} - -void remove_inventory_object( - const LLUUID& object_id, - LLPointer cb) -{ - if (gInventory.getCategory(object_id)) - { - remove_inventory_category(object_id, cb); - } - else - { - remove_inventory_item(object_id, cb); - } -} - -// This is a method which collects the descendents of the id -// provided. If the category is not found, no action is -// taken. This method goes through the long winded process of -// cancelling any calling cards, removing server representation of -// folders, items, etc in a fairly efficient manner. -void purge_descendents_of(const LLUUID& id, LLPointer cb) -{ - LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id); - if(children == LLInventoryModel::CHILDREN_NO) - { - LL_DEBUGS(LOG_INV) << "No descendents to purge for " << id << LL_ENDL; - return; - } - LLPointer cat = gInventory.getCategory(id); - if (cat.notNull()) - { - if (LLClipboard::instance().hasContents()) - { - // Remove items from clipboard or it will remain active even if there is nothing to paste/copy - LLInventoryModel::cat_array_t categories; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(id, categories, items, true); - - for (LLInventoryModel::cat_array_t::const_iterator it = categories.begin(); it != categories.end(); ++it) - { - if (LLClipboard::instance().isOnClipboard((*it)->getUUID())) - { - // No sense in removing single items, partial 'paste' will result in confusion only - LLClipboard::instance().reset(); - break; - } - } - if (LLClipboard::instance().hasContents()) - { - for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it) - { - if (LLClipboard::instance().isOnClipboard((*it)->getUUID())) - { - LLClipboard::instance().reset(); - break; - } - } - } - } - - if (AISAPI::isAvailable()) - { - if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) - { - LL_WARNS() << "Purging not fetched folder: " << cat->getName() << LL_ENDL; - } - AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); - AISAPI::PurgeDescendents(id, cr); - } - else - { - LL_WARNS(LOG_INV) << "Tried to use inventory without AIS API" << LL_ENDL; - } - } -} - -const LLUUID get_folder_by_itemtype(const LLInventoryItem *src) -{ - LLUUID retval = LLUUID::null; - - if (src) - { - retval = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(src->getType())); - } - - return retval; -} - -void copy_inventory_from_notecard(const LLUUID& destination_id, - const LLUUID& object_id, - const LLUUID& notecard_inv_id, - const LLInventoryItem *src, - U32 callback_id) -{ - if (NULL == src) - { - LL_WARNS(LOG_NOTECARD) << "Null pointer to item was passed for object_id " - << object_id << " and notecard_inv_id " - << notecard_inv_id << LL_ENDL; - return; - } - - LLViewerRegion* viewer_region = NULL; - LLViewerObject* vo = NULL; - if (object_id.notNull() && (vo = gObjectList.findObject(object_id)) != NULL) - { - viewer_region = vo->getRegion(); - } - - // Fallback to the agents region if for some reason the - // object isn't found in the viewer. - if (! viewer_region) - { - viewer_region = gAgent.getRegion(); - } - - if (! viewer_region) - { - LL_WARNS(LOG_NOTECARD) << "Can't find region from object_id " - << object_id << " or gAgent" - << LL_ENDL; - return; - } - - LLSD body; - body["notecard-id"] = notecard_inv_id; - body["object-id"] = object_id; - body["item-id"] = src->getUUID(); - body["folder-id"] = destination_id; - body["callback-id"] = (LLSD::Integer)callback_id; - - /// *TODO: RIDER: This posts the request under the agents policy. - /// When I convert the inventory over this call should be moved under that - /// policy as well. - if (!gAgent.requestPostCapability("CopyInventoryFromNotecard", body)) - { - LL_WARNS() << "SIM does not have the capability to copy from notecard." << LL_ENDL; - } -} - -void create_new_item(const std::string& name, - const LLUUID& parent_id, - LLAssetType::EType asset_type, - LLInventoryType::EType inv_type, - U32 next_owner_perm, - std::function created_cb = NULL) -{ - std::string desc; - LLViewerAssetType::generateDescriptionFor(asset_type, desc); - next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER; - - LLPointer cb = NULL; - - switch (inv_type) - { - case LLInventoryType::IT_LSL: - { - cb = new LLBoostFuncInventoryCallback(create_script_cb); - next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Scripts"); - break; - } - - case LLInventoryType::IT_GESTURE: - { - cb = new LLBoostFuncInventoryCallback(create_gesture_cb); - next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Gestures"); - break; - } - - case LLInventoryType::IT_NOTECARD: - { - cb = new LLBoostFuncInventoryCallback(create_notecard_cb); - next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Notecards"); - break; - } - - case LLInventoryType::IT_MATERIAL: - { - cb = new LLBoostFuncInventoryCallback(create_gltf_material_cb); - next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials"); - break; - } - default: - { - cb = new LLBoostFuncInventoryCallback(); - break; - } - } - if (created_cb != NULL) - { - cb->addOnFireFunc(created_cb); - } - - create_inventory_item(gAgent.getID(), - gAgent.getSessionID(), - parent_id, - LLTransactionID::tnull, - name, - desc, - asset_type, - inv_type, - NO_INV_SUBTYPE, - next_owner_perm, - cb); -} - -void slam_inventory_folder(const LLUUID& folder_id, - const LLSD& contents, - LLPointer cb) -{ - LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id - << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; - - AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); - AISAPI::SlamFolder(folder_id, contents, cr); -} - -void remove_folder_contents(const LLUUID& category, bool keep_outfit_links, - LLPointer cb) -{ - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(category, cats, items, - LLInventoryModel::EXCLUDE_TRASH); - for (S32 i = 0; i < items.size(); ++i) - { - LLViewerInventoryItem *item = items.at(i); - if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER)) - continue; - if (item->getIsLinkType()) - { - remove_inventory_item(item->getUUID(), cb); - } - } -} - -const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not) -const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) -const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) -const std::string NEW_MATERIAL_NAME = "New Material"; // *TODO:Translate? (probably not) - -// ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... -void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) -{ - menu_create_inventory_item(panel, bridge ? bridge->getUUID() : LLUUID::null, userdata, default_parent_uuid); -} - -void menu_create_inventory_item(LLInventoryPanel* panel, LLUUID dest_id, const LLSD& userdata, const LLUUID& default_parent_uuid, std::function created_cb) -{ - std::string type_name = userdata.asString(); - - if (("inbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name)) - { - LLFolderType::EType preferred_type = LLFolderType::lookup(type_name); - - LLUUID parent_id; - if (dest_id.notNull()) - { - parent_id = dest_id; - } - else if (default_parent_uuid.notNull()) - { - parent_id = default_parent_uuid; - } - else - { - parent_id = gInventory.getRootFolderID(); - } - - std::function callback_cat_created = NULL; - if (panel) - { - LLHandle handle = panel->getHandle(); - callback_cat_created = [handle](const LLUUID& new_category_id) - { - gInventory.notifyObservers(); - LLInventoryPanel* panel = static_cast(handle.get()); - if (panel) - { - panel->setSelectionByID(new_category_id, true); - } - LL_DEBUGS(LOG_INV) << "Done creating inventory: " << new_category_id << LL_ENDL; - }; - } - else if (created_cb != NULL) - { - callback_cat_created = created_cb; - } - gInventory.createNewCategory( - parent_id, - preferred_type, - LLStringUtil::null, - callback_cat_created); - } - else if ("lsl" == type_name) - { - const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_LSL_TEXT); - create_new_item(NEW_LSL_NAME, - parent_id, - LLAssetType::AT_LSL_TEXT, - LLInventoryType::IT_LSL, - PERM_MOVE | PERM_TRANSFER, - created_cb); // overridden in create_new_item - } - else if ("notecard" == type_name) - { - const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_NOTECARD); - create_new_item(NEW_NOTECARD_NAME, - parent_id, - LLAssetType::AT_NOTECARD, - LLInventoryType::IT_NOTECARD, - PERM_ALL, - created_cb); // overridden in create_new_item - } - else if ("gesture" == type_name) - { - const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); - create_new_item(NEW_GESTURE_NAME, - parent_id, - LLAssetType::AT_GESTURE, - LLInventoryType::IT_GESTURE, - PERM_ALL, - created_cb); // overridden in create_new_item - } - else if ("material" == type_name) - { - const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); - create_new_item(NEW_MATERIAL_NAME, - parent_id, - LLAssetType::AT_MATERIAL, - LLInventoryType::IT_MATERIAL, - PERM_ALL, - created_cb); // overridden in create_new_item - } - else if (("sky" == type_name) || ("water" == type_name) || ("daycycle" == type_name)) - { - LLSettingsType::type_e stype(LLSettingsType::ST_NONE); - - if ("sky" == type_name) - { - stype = LLSettingsType::ST_SKY; - } - else if ("water" == type_name) - { - stype = LLSettingsType::ST_WATER; - } - else if ("daycycle" == type_name) - { - stype = LLSettingsType::ST_DAYCYCLE; - } - else - { - LL_ERRS(LOG_INV) << "Unknown settings type: '" << type_name << "'" << LL_ENDL; - return; - } - - LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS); - - LLSettingsVOBase::createNewInventoryItem(stype, parent_id, created_cb); - } - else - { - // Use for all clothing and body parts. Adding new wearable types requires updating LLWearableDictionary. - LLWearableType::EType wearable_type = LLWearableType::getInstance()->typeNameToType(type_name); - if (wearable_type >= LLWearableType::WT_SHAPE && wearable_type < LLWearableType::WT_COUNT) - { - const LLUUID parent_id = dest_id; - LLAgentWearables::createWearable(wearable_type, false, parent_id, created_cb); - } - else - { - LL_WARNS(LOG_INV) << "Can't create unrecognized type " << type_name << LL_ENDL; - } - } - if(panel) - { - panel->getRootFolder()->setNeedsAutoRename(true); - } -} - -LLAssetType::EType LLViewerInventoryItem::getType() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getType(); - } - if (const LLViewerInventoryCategory *linked_category = getLinkedCategory()) - { - return linked_category->getType(); - } - return LLInventoryItem::getType(); -} - -const LLUUID& LLViewerInventoryItem::getAssetUUID() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getAssetUUID(); - } - - return LLInventoryItem::getAssetUUID(); -} - -const LLUUID& LLViewerInventoryItem::getProtectedAssetUUID() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getProtectedAssetUUID(); - } - - // check for conditions under which we may return a visible UUID to the user - bool item_is_fullperm = getIsFullPerm(); - bool agent_is_godlike = gAgent.isGodlikeWithoutAdminMenuFakery(); - if (item_is_fullperm || agent_is_godlike) - { - return LLInventoryItem::getAssetUUID(); - } - - return LLUUID::null; -} - -const bool LLViewerInventoryItem::getIsFullPerm() const -{ - LLPermissions item_permissions = getPermissions(); - - // modify-ok & copy-ok & transfer-ok - return ( item_permissions.allowOperationBy(PERM_MODIFY, - gAgent.getID(), - gAgent.getGroupID()) && - item_permissions.allowOperationBy(PERM_COPY, - gAgent.getID(), - gAgent.getGroupID()) && - item_permissions.allowOperationBy(PERM_TRANSFER, - gAgent.getID(), - gAgent.getGroupID()) ); -} - -const std::string& LLViewerInventoryItem::getName() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getName(); - } - if (const LLViewerInventoryCategory *linked_category = getLinkedCategory()) - { - return linked_category->getName(); - } - - return LLInventoryItem::getName(); -} - -S32 LLViewerInventoryItem::getSortField() const -{ - return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); -} - -//void LLViewerInventoryItem::setSortField(S32 sortField) -//{ -// LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); -// getSLURL(); -//} - -void LLViewerInventoryItem::getSLURL() -{ - LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); -} - -const LLPermissions& LLViewerInventoryItem::getPermissions() const -{ - // Use the actual permissions of the symlink, not its parent. - return LLInventoryItem::getPermissions(); -} - -const LLUUID& LLViewerInventoryItem::getCreatorUUID() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getCreatorUUID(); - } - - return LLInventoryItem::getCreatorUUID(); -} - -const std::string& LLViewerInventoryItem::getDescription() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getDescription(); - } - - return LLInventoryItem::getDescription(); -} - -const LLSaleInfo& LLViewerInventoryItem::getSaleInfo() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getSaleInfo(); - } - - return LLInventoryItem::getSaleInfo(); -} - -const LLUUID& LLViewerInventoryItem::getThumbnailUUID() const -{ - if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_TEXTURE) - { - return mAssetUUID; - } - if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK) - { - LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID); - return linked_item ? linked_item->getThumbnailUUID() : LLUUID::null; - } - if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK_FOLDER) - { - LLViewerInventoryCategory *linked_cat = gInventory.getCategory(mAssetUUID); - return linked_cat ? linked_cat->getThumbnailUUID() : LLUUID::null; - } - return mThumbnailUUID; -} - -LLInventoryType::EType LLViewerInventoryItem::getInventoryType() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getInventoryType(); - } - - // Categories don't have types. If this item is an AT_FOLDER_LINK, - // treat it as a category. - if (getLinkedCategory()) - { - return LLInventoryType::IT_CATEGORY; - } - - return LLInventoryItem::getInventoryType(); -} - -U32 LLViewerInventoryItem::getFlags() const -{ - if (const LLViewerInventoryItem *linked_item = getLinkedItem()) - { - return linked_item->getFlags(); - } - return LLInventoryItem::getFlags(); -} - -bool LLViewerInventoryItem::isWearableType() const -{ - return (getInventoryType() == LLInventoryType::IT_WEARABLE); -} - -LLWearableType::EType LLViewerInventoryItem::getWearableType() const -{ - if (!isWearableType()) - { - return LLWearableType::WT_INVALID; - } - return LLWearableType::inventoryFlagsToWearableType(getFlags()); -} - -bool LLViewerInventoryItem::isSettingsType() const -{ - return (getInventoryType() == LLInventoryType::IT_SETTINGS); -} - -LLSettingsType::type_e LLViewerInventoryItem::getSettingsType() const -{ - if (!isSettingsType()) - { - return LLSettingsType::ST_NONE; - } - return LLSettingsType::fromInventoryFlags(getFlags()); -} - -time_t LLViewerInventoryItem::getCreationDate() const -{ - return LLInventoryItem::getCreationDate(); -} - -U32 LLViewerInventoryItem::getCRC32() const -{ - return LLInventoryItem::getCRC32(); -} - -// *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 -static char getSeparator() { return '@'; } -bool LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) -{ - using std::string; - using std::stringstream; - - const char separator = getSeparator(); - const string::size_type separatorPos = name.find(separator, 0); - - bool result = false; - - if (separatorPos < string::npos) - { - if (sortField) - { - /* - * The conversion from string to S32 is made this way instead of old plain - * atoi() to ensure portability. If on some other platform S32 will not be - * defined to be signed int, this conversion will still work because of - * operators overloading, but atoi() may fail. - */ - stringstream ss(name.substr(0, separatorPos)); - ss >> *sortField; - } - - if (displayName) - { - *displayName = name.substr(separatorPos + 1, string::npos); - } - - result = true; - } - - return result; -} - -// This returns true if the item that this item points to -// doesn't exist in memory (i.e. LLInventoryModel). The baseitem -// might still be in the database but just not loaded yet. -bool LLViewerInventoryItem::getIsBrokenLink() const -{ - // If the item's type resolves to be a link, that means either: - // A. It wasn't able to perform indirection, i.e. the baseobj doesn't exist in memory. - // B. It's pointing to another link, which is illegal. - return LLAssetType::lookupIsLinkType(getType()); -} - -LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const -{ - if (mType == LLAssetType::AT_LINK) - { - LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID); - if (linked_item && linked_item->getIsLinkType()) - { - LL_WARNS(LOG_INV) << "Warning: Accessing link to link" << LL_ENDL; - return NULL; - } - return linked_item; - } - return NULL; -} - -LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const -{ - if (mType == LLAssetType::AT_LINK_FOLDER) - { - LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID); - return linked_category; - } - return NULL; -} - -bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const -{ - const LLPermissions& perm = getPermissions(); - PermissionMask curr_mask = PERM_NONE; - if(perm.getOwner() == gAgent.getID()) - { - curr_mask = perm.getMaskBase(); - } - else if(gAgent.isInGroup(perm.getGroup())) - { - curr_mask = perm.getMaskGroup(); - } - else - { - curr_mask = perm.getMaskEveryone(); - } - return ((curr_mask & mask) == mask); -} - -PermissionMask LLViewerInventoryItem::getPermissionMask() const -{ - const LLPermissions& permissions = getPermissions(); - - bool copy = permissions.allowCopyBy(gAgent.getID()); - bool mod = permissions.allowModifyBy(gAgent.getID()); - bool xfer = permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID()); - PermissionMask perm_mask = 0; - if (copy) perm_mask |= PERM_COPY; - if (mod) perm_mask |= PERM_MODIFY; - if (xfer) perm_mask |= PERM_TRANSFER; - return perm_mask; -} - -//---------- - -void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const LLAvatarName& name) -{ - rename(name.getUserName()); - gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID()); - gInventory.notifyObservers(); -} - -class LLRegenerateLinkCollector : public LLInventoryCollectFunctor -{ -public: - LLRegenerateLinkCollector(const LLViewerInventoryItem *target_item) : mTargetItem(target_item) {} - virtual ~LLRegenerateLinkCollector() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) - { - if (item) - { - if ((item->getName() == mTargetItem->getName()) && - (item->getInventoryType() == mTargetItem->getInventoryType()) && - (!item->getIsLinkType())) - { - return true; - } - } - return false; - } -protected: - const LLViewerInventoryItem* mTargetItem; -}; - -LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_item) -{ - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - - LLRegenerateLinkCollector candidate_matches(target_item); - gInventory.collectDescendentsIf(gInventory.getRootFolderID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - candidate_matches); - for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items.begin(); - item_iter != items.end(); - ++item_iter) - { - const LLViewerInventoryItem *item = (*item_iter); - if (true) return item->getUUID(); - } - return LLUUID::null; -} - -// This currently dosen't work, because the sim does not allow us -// to change an item's assetID. -bool LLViewerInventoryItem::regenerateLink() -{ - const LLUUID target_item_id = find_possible_item_for_regeneration(this); - if (target_item_id.isNull()) - return false; - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLAssetIDMatches asset_id_matches(getAssetUUID()); - gInventory.collectDescendentsIf(gInventory.getRootFolderID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - asset_id_matches); - for (LLViewerInventoryItem::item_array_t::iterator item_iter = items.begin(); - item_iter != items.end(); - item_iter++) - { - LLViewerInventoryItem *item = (*item_iter); - item->setAssetUUID(target_item_id); - item->updateServer(false); - gInventory.addChangedMask(LLInventoryObserver::REBUILD, item->getUUID()); - } - gInventory.notifyObservers(); - return true; -} +/** + * @file llviewerinventory.cpp + * @brief Implementation of the viewer side inventory objects. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, 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 "llviewerprecompiledheaders.h" +#include "llviewerinventory.h" + +#include "llnotificationsutil.h" +#include "llsdserialize.h" +#include "message.h" + +#include "llaisapi.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "llagentwearables.h" +#include "llfloatersidepanelcontainer.h" +#include "llviewerfoldertype.h" +#include "llfloatersidepanelcontainer.h" +#include "llfolderview.h" +#include "llviewercontrol.h" +#include "llconsole.h" +#include "llinventorydefines.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llgesturemgr.h" + +#include "llinventorybridge.h" +#include "llinventorypanel.h" +#include "lllandmarkactions.h" + +#include "llviewerassettype.h" +#include "llviewerregion.h" +#include "llviewerobjectlist.h" +#include "llpreviewgesture.h" +#include "llviewerwindow.h" +#include "lltrans.h" +#include "llappearancemgr.h" +#include "llcommandhandler.h" +#include "llviewermessage.h" +#include "llpanelmaininventory.h" +#include "llsidepanelappearance.h" +#include "llsidepanelinventory.h" +#include "llavatarnamecache.h" +#include "llavataractions.h" +#include "lllogininstance.h" +#include "llfavoritesbar.h" +#include "llfloaterperms.h" +#include "llclipboard.h" +#include "llhttpretrypolicy.h" +#include "llsettingsvo.h" + +// do-nothing ops for use in callbacks. +void no_op_inventory_func(const LLUUID&) {} +void no_op_llsd_func(const LLSD&) {} +void no_op() {} + +static const char * const LOG_INV("Inventory"); +static const char * const LOG_LOCAL("InventoryLocalize"); +static const char * const LOG_NOTECARD("copy_inventory_from_notecard"); + +static const std::string INV_OWNER_ID("owner_id"); +static const std::string INV_VERSION("version"); + +#if 1 +// *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model. +// temp code in transition +void doInventoryCb(LLPointer cb, LLUUID id) +{ + if (cb.notNull()) + cb->fire(id); +} +#endif + +///---------------------------------------------------------------------------- +/// Helper class to store special inventory item names and their localized values. +///---------------------------------------------------------------------------- +class LLLocalizedInventoryItemsDictionary : public LLSingleton +{ + LLSINGLETON(LLLocalizedInventoryItemsDictionary); +public: + std::map mInventoryItemsDict; + + /** + * Finds passed name in dictionary and replaces it with found localized value. + * + * @param object_name - string to be localized. + * @return true if passed name was found and localized, false otherwise. + */ + bool localizeInventoryObjectName(std::string& object_name) + { + LL_DEBUGS(LOG_LOCAL) << "Searching for localization: " << object_name << LL_ENDL; + + std::map::const_iterator dictionary_iter = mInventoryItemsDict.find(object_name); + + bool found = dictionary_iter != mInventoryItemsDict.end(); + if(found) + { + object_name = dictionary_iter->second; + LL_DEBUGS(LOG_LOCAL) << "Found, new name is: " << object_name << LL_ENDL; + } + return found; + } +}; + +LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary() +{ + mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape"); + mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin"); + mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair"); + mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes"); + mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt"); + mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants"); + mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes"); + mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks"); + mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket"); + mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves"); + mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt"); + mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants"); + mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt"); + mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha"); + mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo"); + mInventoryItemsDict["New Universal"] = LLTrans::getString("New Universal"); + mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics"); + mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); + + mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture"); + mInventoryItemsDict["New Material"] = LLTrans::getString("New Material"); + mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); + mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); + mInventoryItemsDict["New Note"] = LLTrans::getString("New Note"); + mInventoryItemsDict["Contents"] = LLTrans::getString("Contents"); + + mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture"); + mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures"); + mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures"); + mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures"); + mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures"); + mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures"); + + //predefined gestures + + //male + mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me"); + mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319 + mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss"); + mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo"); + mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored"); + mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey"); + mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh"); + mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed"); + mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug"); + mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out"); + mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow"); + + //female + mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle"); + mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry"); + mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed"); + mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me"); + mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319 + mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss"); + mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo"); + mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored"); + mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey"); + mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby"); + mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh"); + mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good"); + mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here"); + mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please"); + mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed"); + mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug"); + mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); + mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow"); + + //common + mInventoryItemsDict["/bow"] = LLTrans::getString("/bow"); + mInventoryItemsDict["/clap"] = LLTrans::getString("/clap"); + mInventoryItemsDict["/count"] = LLTrans::getString("/count"); + mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish"); + mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb"); + mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle"); + mInventoryItemsDict["/no"] = LLTrans::getString("/no"); + mInventoryItemsDict["/no!"] = LLTrans::getString("/no!"); + mInventoryItemsDict["/paper"] = LLTrans::getString("/paper"); + mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme"); + mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou"); + mInventoryItemsDict["/rock"] = LLTrans::getString("/rock"); + mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor"); + mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke"); + mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch"); + mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle"); + mInventoryItemsDict["/yes"] = LLTrans::getString("/yes"); + mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!"); + mInventoryItemsDict["afk"] = LLTrans::getString("afk"); + mInventoryItemsDict["dance1"] = LLTrans::getString("dance1"); + mInventoryItemsDict["dance2"] = LLTrans::getString("dance2"); + mInventoryItemsDict["dance3"] = LLTrans::getString("dance3"); + mInventoryItemsDict["dance4"] = LLTrans::getString("dance4"); + mInventoryItemsDict["dance5"] = LLTrans::getString("dance5"); + mInventoryItemsDict["dance6"] = LLTrans::getString("dance6"); + mInventoryItemsDict["dance7"] = LLTrans::getString("dance7"); + mInventoryItemsDict["dance8"] = LLTrans::getString("dance8"); +} + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +class LLInventoryHandler : public LLCommandHandler +{ +public: + LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { } + + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 1) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED + || nav_type == NAV_TYPE_EXTERNAL) + { + // NAV_TYPE_EXTERNAL will be throttled + return true; + } + + return false; + } + + bool handle(const LLSD& params, + const LLSD& query_map, + const std::string& grid, + LLMediaCtrl* web) + { + if (params.size() < 1) + { + return false; + } + + if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableInventory")) + { + LLNotificationsUtil::add("NoInventory", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit")); + return true; + } + + // support secondlife:///app/inventory/show + if (params[0].asString() == "show") + { + LLFloaterSidePanelContainer::showPanel("inventory", LLSD()); + return true; + } + + if (params[0].asString() == "filters") + { + LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); + if (sidepanel_inventory) + { + LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); + if (main_inventory) + { + main_inventory->toggleFindOptions(); + } + } + return true; + } + + // otherwise, we need a UUID and a verb... + if (params.size() < 2) + { + return false; + } + LLUUID inventory_id; + if (!inventory_id.set(params[0], false)) + { + return false; + } + + const std::string verb = params[1].asString(); + if (verb == "select") + { + uuid_vec_t items_to_open; + items_to_open.push_back(inventory_id); + //inventory_handler is just a stub, because we don't know from who this offer + open_inventory_offer(items_to_open, "inventory_handler"); + return true; + } + + return false; + } +}; +LLInventoryHandler gInventoryHandler; + +///---------------------------------------------------------------------------- +/// Class LLViewerInventoryItem +///---------------------------------------------------------------------------- + +LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& uuid, + const LLUUID& parent_uuid, + const LLPermissions& perm, + 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, + time_t creation_date_utc) : + LLInventoryItem(uuid, parent_uuid, perm, asset_uuid, type, inv_type, + name, desc, sale_info, flags, creation_date_utc), + mIsComplete(true) +{ +} + +LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& item_id, + const LLUUID& parent_id, + const std::string& name, + LLInventoryType::EType inv_type) : + LLInventoryItem(), + mIsComplete(false) +{ + mUUID = item_id; + mParentUUID = parent_id; + mInventoryType = inv_type; + mName = name; +} + +LLViewerInventoryItem::LLViewerInventoryItem() : + LLInventoryItem(), + mIsComplete(false) +{ +} + +LLViewerInventoryItem::LLViewerInventoryItem(const LLViewerInventoryItem* other) : + LLInventoryItem() +{ + copyViewerItem(other); + if (!mIsComplete) + { + LL_WARNS(LOG_INV) << "LLViewerInventoryItem copy constructor for incomplete item" + << mUUID << LL_ENDL; + } +} + +LLViewerInventoryItem::LLViewerInventoryItem(const LLInventoryItem *other) : + LLInventoryItem(other), + mIsComplete(true) +{ +} + + +LLViewerInventoryItem::~LLViewerInventoryItem() +{ +} + +void LLViewerInventoryItem::copyViewerItem(const LLViewerInventoryItem* other) +{ + LLInventoryItem::copyItem(other); + mIsComplete = other->mIsComplete; + mTransactionID = other->mTransactionID; +} + +// virtual +void LLViewerInventoryItem::copyItem(const LLInventoryItem *other) +{ + LLInventoryItem::copyItem(other); + mIsComplete = true; + mTransactionID.setNull(); +} + +void LLViewerInventoryItem::cloneViewerItem(LLPointer& newitem) const +{ + newitem = new LLViewerInventoryItem(this); + if(newitem.notNull()) + { + LLUUID item_id; + item_id.generate(); + newitem->setUUID(item_id); + } +} + +void LLViewerInventoryItem::updateServer(bool is_new) const +{ + if(!mIsComplete) + { + // *FIX: deal with this better. + // If we're crashing here then the UI is incorrectly enabled. + LL_ERRS(LOG_INV) << "LLViewerInventoryItem::updateServer() - for incomplete item" + << LL_ENDL; + return; + } + if(gAgent.getID() != mPermissions.getOwner()) + { + // *FIX: deal with this better. + LL_WARNS(LOG_INV) << "LLViewerInventoryItem::updateServer() - for unowned item " + << ll_pretty_print_sd(this->asLLSD()) + << LL_ENDL; + return; + } + LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); + gInventory.accountForUpdate(up); + + LLSD updates = asLLSD(); + // Replace asset_id and/or shadow_id with transaction_id (hash_id) + if (updates.has("asset_id")) + { + updates.erase("asset_id"); + if(getTransactionID().notNull()) + { + updates["hash_id"] = getTransactionID(); + } + } + if (updates.has("shadow_id")) + { + updates.erase("shadow_id"); + if(getTransactionID().notNull()) + { + updates["hash_id"] = getTransactionID(); + } + } + AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer)NULL, _1); + AISAPI::UpdateItem(getUUID(), updates, cr); +} + +void LLViewerInventoryItem::fetchFromServer(void) const +{ + if(!mIsComplete) + { + if (AISAPI::isAvailable()) // AIS v 3 + { + LLInventoryModelBackgroundFetch::getInstance()->scheduleItemFetch(mUUID); + } + else + { + std::string url; + + LLViewerRegion* region = gAgent.getRegion(); + // we have to check region. It can be null after region was destroyed. See EXT-245 + if (region) + { + if (gAgent.getID() != mPermissions.getOwner()) + { + url = region->getCapability("FetchLib2"); + } + else + { + url = region->getCapability("FetchInventory2"); + } + } + else + { + LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL; + } + + if (!url.empty()) + { + LLSD body; + body["agent_id"] = gAgent.getID(); + body["items"][0]["owner_id"] = mPermissions.getOwner(); + body["items"][0]["item_id"] = mUUID; + + LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body)); + gInventory.requestPost(true, url, body, handler, "Inventory Item"); + } + } + } +} + +// virtual +bool LLViewerInventoryItem::unpackMessage(const LLSD& item) +{ + bool rv = LLInventoryItem::fromLLSD(item); + + LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); + + mIsComplete = true; + return rv; +} + +// virtual +bool LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) +{ + bool rv = LLInventoryItem::unpackMessage(msg, block, block_num); + + LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); + + mIsComplete = true; + return rv; +} + +void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_id) +{ + mTransactionID = transaction_id; +} + +void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const +{ + msg->addUUIDFast(_PREHASH_ItemID, mUUID); + msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); + mPermissions.packMessage(msg); + msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID); + 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, mCreationDate); + U32 crc = getCRC32(); + msg->addU32Fast(_PREHASH_CRC, crc); +} + +// virtual +bool LLViewerInventoryItem::importLegacyStream(std::istream& input_stream) +{ + bool rv = LLInventoryItem::importLegacyStream(input_stream); + mIsComplete = true; + return rv; +} + +void LLViewerInventoryItem::updateParentOnServer(bool restamp) const +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addBOOLFast(_PREHASH_Stamp, restamp); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, mUUID); + msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); + msg->addString("NewName", NULL); + gAgent.sendReliableMessage(); +} + +//void LLViewerInventoryItem::setCloneCount(S32 clones) +//{ +// mClones = clones; +//} + +//S32 LLViewerInventoryItem::getCloneCount() const +//{ +// return mClones; +//} + +///---------------------------------------------------------------------------- +/// Class LLViewerInventoryCategory +///---------------------------------------------------------------------------- + +LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid, + const LLUUID& parent_uuid, + LLFolderType::EType pref, + const std::string& name, + const LLUUID& owner_id) : + LLInventoryCategory(uuid, parent_uuid, pref, name), + mOwnerID(owner_id), + mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), + mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN), + mFetching(FETCH_NONE) +{ + mDescendentsRequested.reset(); +} + +LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& owner_id) : + mOwnerID(owner_id), + mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), + mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN), + mFetching(FETCH_NONE) +{ + mDescendentsRequested.reset(); +} + +LLViewerInventoryCategory::LLViewerInventoryCategory(const LLViewerInventoryCategory* other) +{ + copyViewerCategory(other); + mFetching = FETCH_NONE; +} + +LLViewerInventoryCategory::~LLViewerInventoryCategory() +{ +} + +void LLViewerInventoryCategory::copyViewerCategory(const LLViewerInventoryCategory* other) +{ + copyCategory(other); + mOwnerID = other->mOwnerID; + setVersion(other->getVersion()); + mDescendentCount = other->mDescendentCount; + mDescendentsRequested = other->mDescendentsRequested; +} + + +void LLViewerInventoryCategory::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); +} + +void LLViewerInventoryCategory::updateParentOnServer(bool restamp) const +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoveInventoryFolder); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->addBOOL("Stamp", restamp); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_FolderID, mUUID); + msg->addUUIDFast(_PREHASH_ParentID, mParentUUID); + gAgent.sendReliableMessage(); +} + +void LLViewerInventoryCategory::updateServer(bool is_new) const +{ + // communicate that change with the server. + + if (LLFolderType::lookupIsProtectedType(mPreferredType)) + { + LLNotificationsUtil::add("CannotModifyProtectedCategories"); + return; + } + + LLSD new_llsd = asLLSD(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer)NULL, _1); + AISAPI::UpdateCategory(getUUID(), new_llsd, cr); +} + +S32 LLViewerInventoryCategory::getVersion() const +{ + return mVersion; +} + +void LLViewerInventoryCategory::setVersion(S32 version) +{ + mVersion = version; +} + +bool LLViewerInventoryCategory::fetch(S32 expiry_seconds) +{ + if((VERSION_UNKNOWN == getVersion()) + && mDescendentsRequested.hasExpired()) //Expired check prevents multiple downloads. + { + LL_DEBUGS(LOG_INV) << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL; + mDescendentsRequested.reset(); + mDescendentsRequested.setTimerExpirySec(expiry_seconds); + + std::string url; + if (gAgent.getRegion()) + { + url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2"); + } + else + { + LL_WARNS_ONCE(LOG_INV) << "agent region is null" << LL_ENDL; + } + if (!url.empty() || AISAPI::isAvailable()) + { + LLInventoryModelBackgroundFetch::instance().start(mUUID, false); + } + return true; + } + return false; +} + +LLViewerInventoryCategory::EFetchType LLViewerInventoryCategory::getFetching() +{ + // if timer hasn't expired, request was scheduled, but not in progress + // if mFetching request was actually started + if (mDescendentsRequested.hasExpired()) + { + mFetching = FETCH_NONE; + } + return mFetching; +} + +void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchType fetching) +{ + if (fetching == FETCH_FAILED) + { + const F32 FETCH_FAILURE_EXPIRY = 60.0f; + mDescendentsRequested.setTimerExpirySec(FETCH_FAILURE_EXPIRY); + mFetching = fetching; + } + else if (fetching > mFetching) // allow a switch from normal to recursive + { + if (mDescendentsRequested.hasExpired() || (mFetching == FETCH_NONE)) + { + mDescendentsRequested.reset(); + if (AISAPI::isAvailable()) + { + mDescendentsRequested.setTimerExpirySec(AISAPI::HTTP_TIMEOUT); + } + else + { + const F32 FETCH_TIMER_EXPIRY = 30.0f; + mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); + } + } + mFetching = fetching; + } + else if (fetching == FETCH_NONE) + { + mDescendentsRequested.stop(); + mFetching = fetching; + } +} + +S32 LLViewerInventoryCategory::getViewerDescendentCount() const +{ + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(getUUID(), cats, items); + S32 descendents_actual = 0; + if(cats && items) + { + descendents_actual = cats->size() + items->size(); + } + return descendents_actual; +} + +LLSD LLViewerInventoryCategory::exportLLSD() const +{ + LLSD cat_data = LLInventoryCategory::exportLLSD(); + cat_data[INV_OWNER_ID] = mOwnerID; + cat_data[INV_VERSION] = mVersion; + + return cat_data; +} + +bool LLViewerInventoryCategory::importLLSD(const LLSD& cat_data) +{ + LLInventoryCategory::importLLSD(cat_data); + if (cat_data.has(INV_OWNER_ID)) + { + mOwnerID = cat_data[INV_OWNER_ID].asUUID(); + } + if (cat_data.has(INV_VERSION)) + { + setVersion(cat_data[INV_VERSION].asInteger()); + } + return true; +} + +bool LLViewerInventoryCategory::acceptItem(LLInventoryItem* inv_item) +{ + if (!inv_item) + { + return false; + } + + // Only stock folders have limitation on which item they will accept + bool accept = true; + if (getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK) + { + // If the item is copyable (i.e. non stock) do not accept the drop in a stock folder + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + accept = false; + } + else + { + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(getUUID(),cat_array,item_array); + // Destination stock folder must be empty OR types of incoming and existing items must be identical and have the same permissions + accept = (!item_array->size() || + ((item_array->at(0)->getInventoryType() == inv_item->getInventoryType()) && + (item_array->at(0)->getPermissions().getMaskNextOwner() == inv_item->getPermissions().getMaskNextOwner()))); + } + } + return accept; +} + +void LLViewerInventoryCategory::determineFolderType() +{ + /* Do NOT uncomment this code. This is for future 2.1 support of ensembles. + llassert(false); + LLFolderType::EType original_type = getPreferredType(); + if (LLFolderType::lookupIsProtectedType(original_type)) + return; + + U64 folder_valid = 0; + U64 folder_invalid = 0; + LLInventoryModel::cat_array_t category_array; + LLInventoryModel::item_array_t item_array; + gInventory.collectDescendents(getUUID(),category_array,item_array,false); + + // For ensembles + if (category_array.empty()) + { + for (LLInventoryModel::item_array_t::iterator item_iter = item_array.begin(); + item_iter != item_array.end(); + item_iter++) + { + const LLViewerInventoryItem *item = (*item_iter); + if (item->getIsLinkType()) + return; + if (item->isWearableType()) + { + const LLWearableType::EType wearable_type = item->getWearableType(); + const std::string& wearable_name = LLWearableType::getTypeName(wearable_type); + U64 valid_folder_types = LLViewerFolderType::lookupValidFolderTypes(wearable_name); + folder_valid |= valid_folder_types; + folder_invalid |= ~valid_folder_types; + } + } + for (U8 i = LLFolderType::FT_ENSEMBLE_START; i <= LLFolderType::FT_ENSEMBLE_END; i++) + { + if ((folder_valid & (1LL << i)) && + !(folder_invalid & (1LL << i))) + { + changeType((LLFolderType::EType)i); + return; + } + } + } + if (LLFolderType::lookupIsEnsembleType(original_type)) + { + changeType(LLFolderType::FT_NONE); + } + llassert(false); + */ +} + +void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type) +{ + const LLUUID &folder_id = getUUID(); + const LLUUID &parent_id = getParentUUID(); + const std::string &name = getName(); + + LLPointer new_cat = new LLViewerInventoryCategory(folder_id, + parent_id, + new_folder_type, + name, + gAgent.getID()); + + + LLSD new_llsd = new_cat->asLLSD(); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer) NULL, _1); + AISAPI::UpdateCategory(folder_id, new_llsd, cr); + + setPreferredType(new_folder_type); + gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id); +} + +void LLViewerInventoryCategory::localizeName() +{ + LLLocalizedInventoryItemsDictionary::getInstance()->localizeInventoryObjectName(mName); +} + +// virtual +bool LLViewerInventoryCategory::unpackMessage(const LLSD& category) +{ + bool rv = LLInventoryCategory::fromLLSD(category); + localizeName(); + return rv; +} + +// virtual +void LLViewerInventoryCategory::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) +{ + LLInventoryCategory::unpackMessage(msg, block, block_num); + localizeName(); +} + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- + +LLInventoryCallbackManager *LLInventoryCallbackManager::sInstance = NULL; + +LLInventoryCallbackManager::LLInventoryCallbackManager() : + mLastCallback(0) +{ + if( sInstance != NULL ) + { + LL_WARNS(LOG_INV) << "LLInventoryCallbackManager::LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; + return; + } + sInstance = this; +} + +LLInventoryCallbackManager::~LLInventoryCallbackManager() +{ + if( sInstance != this ) + { + LL_WARNS(LOG_INV) << "LLInventoryCallbackManager::~LLInventoryCallbackManager: unexpected multiple instances" << LL_ENDL; + return; + } + sInstance = NULL; +} + +//static +void LLInventoryCallbackManager::destroyClass() +{ + if (sInstance) + { + for (callback_map_t::iterator it = sInstance->mMap.begin(), end_it = sInstance->mMap.end(); it != end_it; ++it) + { + // drop LLPointer reference to callback + it->second = NULL; + } + sInstance->mMap.clear(); + } +} + + +U32 LLInventoryCallbackManager::registerCB(LLPointer cb) +{ + if (cb.isNull()) + return 0; + + mLastCallback++; + if (!mLastCallback) + mLastCallback++; + + mMap[mLastCallback] = cb; + return mLastCallback; +} + +void LLInventoryCallbackManager::fire(U32 callback_id, const LLUUID& item_id) +{ + if (!callback_id || item_id.isNull()) + return; + + std::map >::iterator i; + + i = mMap.find(callback_id); + if (i != mMap.end()) + { + (*i).second->fire(item_id); + mMap.erase(i); + } +} + +void rez_attachment_cb(const LLUUID& inv_item, LLViewerJointAttachment *attachmentp) +{ + if (inv_item.isNull()) + return; + + LLViewerInventoryItem *item = gInventory.getItem(inv_item); + if (item) + { + rez_attachment(item, attachmentp); + } +} + +void activate_gesture_cb(const LLUUID& inv_item) +{ + if (inv_item.isNull()) + return; + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (!item) + return; + if (item->getType() != LLAssetType::AT_GESTURE) + return; + + LLGestureMgr::instance().activateGesture(inv_item); +} + +void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type) +{ + llassert(item); + LLPermissions perm = item->getPermissions(); + if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type) + || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type)) + { + perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type)); + perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type)); + + item->setPermissions(perm); + + item->updateServer(false); + } +} + +void create_script_cb(const LLUUID& inv_item) +{ + if (!inv_item.isNull()) + { + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (item) + { + set_default_permissions(item, "Scripts"); + + // item was just created, update even if permissions did not changed + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + } +} + +void create_gesture_cb(const LLUUID& inv_item) +{ + if (!inv_item.isNull()) + { + LLGestureMgr::instance().activateGesture(inv_item); + + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (item) + { + set_default_permissions(item, "Gestures"); + + gInventory.updateItem(item); + gInventory.notifyObservers(); + + LLPreviewGesture* preview = LLPreviewGesture::show(inv_item, LLUUID::null); + // Force to be entirely onscreen. + gFloaterView->adjustToFitScreen(preview, false); + } + } +} + + +void create_notecard_cb(const LLUUID& inv_item) +{ + if (!inv_item.isNull()) + { + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (item) + { + set_default_permissions(item, "Notecards"); + + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + } +} + +void create_gltf_material_cb(const LLUUID& inv_item) +{ + if (!inv_item.isNull()) + { + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (item) + { + set_default_permissions(item, "Materials"); + + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + } +} + +LLInventoryCallbackManager gInventoryCallbacks; + +void create_inventory_item( + const LLUUID& agent_id, + const LLUUID& session_id, + const LLUUID& parent_id, + const LLTransactionID& transaction_id, + const std::string& name, + const std::string& desc, + LLAssetType::EType asset_type, + LLInventoryType::EType inv_type, + U8 subtype, + U32 next_owner_perm, + LLPointer cb) +{ + //check if name is equal to one of special inventory items names + //EXT-5839 + std::string server_name = name; + + { + std::map::const_iterator dictionary_iter; + + for (dictionary_iter = LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.begin(); + dictionary_iter != LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.end(); + dictionary_iter++) + { + const std::string& localized_name = dictionary_iter->second; + if(localized_name == name) + { + server_name = dictionary_iter->first; + } + } + } + +#ifdef USE_AIS_FOR_NC + // D567 18.03.2023 not yet implemented within AIS3 + if (AISAPI::isAvailable()) + { + LLSD new_inventory = LLSD::emptyMap(); + new_inventory["items"] = LLSD::emptyArray(); + + LLPermissions perms; + perms.init( + gAgentID, + gAgentID, + LLUUID::null, + LLUUID::null); + perms.initMasks( + PERM_ALL, + PERM_ALL, + PERM_NONE, + PERM_NONE, + next_owner_perm); + + LLUUID null_id; + LLPointer item = new LLViewerInventoryItem( + null_id, /*don't know yet*/ + parent_id, + perms, + null_id, /*don't know yet*/ + asset_type, + inv_type, + server_name, + desc, + LLSaleInfo(), + 0, + 0 /*don't know yet, whenever server creates it*/); + LLSD item_sd = item->asLLSD(); + new_inventory["items"].append(item_sd); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::CreateInventory( + parent_id, + new_inventory, + cr); + return; + } + else + { + LL_WARNS() << "AIS v3 not available" << LL_ENDL; + } +#endif + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_CreateInventoryItem); + msg->nextBlock(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, agent_id); + msg->addUUIDFast(_PREHASH_SessionID, session_id); + msg->nextBlock(_PREHASH_InventoryBlock); + msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb)); + msg->addUUIDFast(_PREHASH_FolderID, parent_id); + msg->addUUIDFast(_PREHASH_TransactionID, transaction_id); + msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_perm); + msg->addS8Fast(_PREHASH_Type, (S8)asset_type); + msg->addS8Fast(_PREHASH_InvType, (S8)inv_type); + msg->addU8Fast(_PREHASH_WearableType, (U8)subtype); + msg->addStringFast(_PREHASH_Name, server_name); + msg->addStringFast(_PREHASH_Description, desc); + + gAgent.sendReliableMessage(); +} + +void create_inventory_callingcard_callback(LLPointer cb, + const LLUUID &parent, + const LLUUID &avatar_id, + const LLAvatarName &av_name) +{ + std::string item_desc = avatar_id.asString(); + create_inventory_item(gAgent.getID(), + gAgent.getSessionID(), + parent, + LLTransactionID::tnull, + av_name.getUserName(), + item_desc, + LLAssetType::AT_CALLINGCARD, + LLInventoryType::IT_CALLINGCARD, + NO_INV_SUBTYPE, + PERM_MOVE | PERM_TRANSFER, + cb); +} + +void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent /*= LLUUID::null*/, LLPointer cb/*=NULL*/) +{ + LLAvatarName av_name; + LLAvatarNameCache::get(avatar_id, boost::bind(&create_inventory_callingcard_callback, cb, parent, _1, _2)); +} + +void create_inventory_wearable(const LLUUID& agent_id, const LLUUID& session_id, + const LLUUID& parent, const LLTransactionID& transaction_id, + const std::string& name, + const std::string& desc, LLAssetType::EType asset_type, + LLWearableType::EType wtype, + U32 next_owner_perm, + LLPointer cb) +{ + create_inventory_item(agent_id, session_id, parent, transaction_id, + name, desc, asset_type, LLInventoryType::IT_WEARABLE, static_cast(wtype), + next_owner_perm, cb); +} + +void create_inventory_settings(const LLUUID& agent_id, const LLUUID& session_id, + const LLUUID& parent, const LLTransactionID& transaction_id, + const std::string& name, + const std::string& desc, + LLSettingsType::type_e settype, + U32 next_owner_perm, + LLPointer cb) +{ + create_inventory_item(agent_id, session_id, parent, transaction_id, + name, desc, LLAssetType::AT_SETTINGS, LLInventoryType::IT_SETTINGS, + static_cast(settype), next_owner_perm, cb); +} + + +void copy_inventory_item( + const LLUUID& agent_id, + const LLUUID& current_owner, + const LLUUID& item_id, + const LLUUID& parent_id, + const std::string& new_name, + LLPointer cb) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_CopyInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, agent_id); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb)); + msg->addUUIDFast(_PREHASH_OldAgentID, current_owner); + msg->addUUIDFast(_PREHASH_OldItemID, item_id); + msg->addUUIDFast(_PREHASH_NewFolderID, parent_id); + msg->addStringFast(_PREHASH_NewName, new_name); + gAgent.sendReliableMessage(); +} + +// Create link to single inventory object. +void link_inventory_object(const LLUUID& category, + LLConstPointer baseobj, + LLPointer cb) +{ + if (!baseobj) + { + LL_WARNS(LOG_INV) << "Attempt to link to non-existent object" << LL_ENDL; + return; + } + + LLInventoryObject::const_object_list_t obj_array; + obj_array.push_back(baseobj); + link_inventory_array(category, obj_array, cb); +} + +void link_inventory_object(const LLUUID& category, + const LLUUID& id, + LLPointer cb) +{ + LLConstPointer baseobj = gInventory.getObject(id); + link_inventory_object(category, baseobj, cb); +} + +// Create links to all listed inventory objects. +void link_inventory_array(const LLUUID& category, + LLInventoryObject::const_object_list_t& baseobj_array, + LLPointer cb) +{ +#ifndef LL_RELEASE_FOR_DOWNLOAD + const LLViewerInventoryCategory *cat = gInventory.getCategory(category); + const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND"; +#endif + LLInventoryObject::const_object_list_t::const_iterator it = baseobj_array.begin(); + LLInventoryObject::const_object_list_t::const_iterator end = baseobj_array.end(); + LLSD links = LLSD::emptyArray(); + for (; it != end; ++it) + { + const LLInventoryObject* baseobj = *it; + if (!baseobj) + { + LL_WARNS(LOG_INV) << "attempt to link to unknown object" << LL_ENDL; + continue; + } + + if (!LLAssetType::lookupCanLink(baseobj->getType())) + { + // Fail if item can be found but is of a type that can't be linked. + // Arguably should fail if the item can't be found too, but that could + // be a larger behavioral change. + LL_WARNS(LOG_INV) << "attempt to link an unlinkable object, type = " << baseobj->getActualType() << LL_ENDL; + continue; + } + + LLInventoryType::EType inv_type = LLInventoryType::IT_NONE; + LLAssetType::EType asset_type = LLAssetType::AT_NONE; + std::string new_desc; + LLUUID linkee_id; + if (dynamic_cast(baseobj)) + { + inv_type = LLInventoryType::IT_CATEGORY; + asset_type = LLAssetType::AT_LINK_FOLDER; + linkee_id = baseobj->getUUID(); + } + else + { + const LLViewerInventoryItem *baseitem = dynamic_cast(baseobj); + if (baseitem) + { + inv_type = baseitem->getInventoryType(); + new_desc = baseitem->getActualDescription(); + switch (baseitem->getActualType()) + { + case LLAssetType::AT_LINK: + case LLAssetType::AT_LINK_FOLDER: + linkee_id = baseobj->getLinkedUUID(); + asset_type = baseitem->getActualType(); + break; + default: + linkee_id = baseobj->getUUID(); + asset_type = LLAssetType::AT_LINK; + break; + } + } + else + { + LL_WARNS(LOG_INV) << "could not convert object into an item or category: " << baseobj->getUUID() << LL_ENDL; + continue; + } + } + + LLSD link = LLSD::emptyMap(); + link["linked_id"] = linkee_id; + link["type"] = (S8)asset_type; + link["inv_type"] = (S8)inv_type; + link["name"] = baseobj->getName(); + link["desc"] = new_desc; + links.append(link); + +#ifndef LL_RELEASE_FOR_DOWNLOAD + LL_DEBUGS(LOG_INV) << "Linking Object [ name:" << baseobj->getName() + << " UUID:" << baseobj->getUUID() + << " ] into Category [ name:" << cat_name + << " UUID:" << category << " ] " << LL_ENDL; +#endif + } + LLSD new_inventory = LLSD::emptyMap(); + new_inventory["links"] = links; + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::CreateInventory(category, new_inventory, cr); +} + +void move_inventory_item( + const LLUUID& agent_id, + const LLUUID& session_id, + const LLUUID& item_id, + const LLUUID& parent_id, + const std::string& new_name, + LLPointer cb) +{ + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, agent_id); + msg->addUUIDFast(_PREHASH_SessionID, session_id); + msg->addBOOLFast(_PREHASH_Stamp, false); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item_id); + msg->addUUIDFast(_PREHASH_FolderID, parent_id); + msg->addStringFast(_PREHASH_NewName, new_name); + gAgent.sendReliableMessage(); +} + +// Should call this with an update_item that's been copied and +// modified from an original source item, rather than modifying the +// source item directly. +void update_inventory_item( + LLViewerInventoryItem *update_item, + LLPointer cb) +{ + const LLUUID& item_id = update_item->getUUID(); + + LLSD updates = update_item->asLLSD(); + // Replace asset_id and/or shadow_id with transaction_id (hash_id) + if (updates.has("asset_id")) + { + updates.erase("asset_id"); + if (update_item->getTransactionID().notNull()) + { + updates["hash_id"] = update_item->getTransactionID(); + } + } + if (updates.has("shadow_id")) + { + updates.erase("shadow_id"); + if (update_item->getTransactionID().notNull()) + { + updates["hash_id"] = update_item->getTransactionID(); + } + } + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::UpdateItem(item_id, updates, cr); +} + +// Note this only supports updating an existing item. Goes through AISv3 +// code path where available. Not all uses of item->updateServer() can +// easily be switched to this paradigm. +void update_inventory_item( + const LLUUID& item_id, + const LLSD& updates, + LLPointer cb) +{ + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::UpdateItem(item_id, updates, cr); +} + +void update_inventory_category( + const LLUUID& cat_id, + const LLSD& updates, + LLPointer cb) +{ + LLPointer obj = gInventory.getCategory(cat_id); + LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL; + if(obj) + { + if (LLFolderType::lookupIsProtectedType(obj->getPreferredType()) + && (updates.size() != 1 || !updates.has("thumbnail"))) + { + LLNotificationsUtil::add("CannotModifyProtectedCategories"); + return; + } + + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::UpdateCategory(cat_id, updates, cr); + } +} + +void remove_inventory_items( + LLInventoryObject::object_list_t& items_to_kill, + LLPointer cb + ) +{ + for (LLInventoryObject::object_list_t::iterator it = items_to_kill.begin(); + it != items_to_kill.end(); + ++it) + { + remove_inventory_item(*it, cb); + } +} + +void remove_inventory_item( + const LLUUID& item_id, + LLPointer cb, + bool immediate_delete) +{ + LLPointer obj = gInventory.getItem(item_id); + if (obj) + { + remove_inventory_item(obj, cb, immediate_delete); + } + else + { + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << "(NOT FOUND)" << LL_ENDL; + } +} + +void remove_inventory_item( + LLPointer obj, + LLPointer cb, + bool immediate_delete) +{ + if(obj) + { + const LLUUID item_id(obj->getUUID()); + LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL; + if (AISAPI::isAvailable()) + { + AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); + AISAPI::RemoveItem(item_id, cr); + + if (immediate_delete) + { + gInventory.onObjectDeletedFromServer(item_id); + } + } + else + { + LL_WARNS(LOG_INV) << "Tried to use inventory without AIS API" << LL_ENDL; + } + } + else + { + // *TODO: Clean up callback? + LL_WARNS(LOG_INV) << "remove_inventory_item called for invalid or nonexistent item." << LL_ENDL; + } +} + +class LLRemoveCategoryOnDestroy: public LLInventoryCallback +{ +public: + LLRemoveCategoryOnDestroy(const LLUUID& cat_id, LLPointer cb): + mID(cat_id), + mCB(cb) + { + } + /* virtual */ void fire(const LLUUID& item_id) {} + ~LLRemoveCategoryOnDestroy() + { + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(mID); + if(children != LLInventoryModel::CHILDREN_NO) + { + LL_WARNS(LOG_INV) << "remove descendents failed, cannot remove category " << LL_ENDL; + } + else + { + remove_inventory_category(mID, mCB); + } + } +private: + LLUUID mID; + LLPointer mCB; +}; + +void remove_inventory_category( + const LLUUID& cat_id, + LLPointer cb) +{ + LL_DEBUGS(LOG_INV) << "cat_id: [" << cat_id << "] " << LL_ENDL; + LLPointer obj = gInventory.getCategory(cat_id); + if(obj) + { + if (!gInventory.isCategoryComplete(cat_id)) + { + LL_WARNS() << "Removing (purging) incomplete category " << obj->getName() << LL_ENDL; + } + if(LLFolderType::lookupIsProtectedType(obj->getPreferredType())) + { + LLNotificationsUtil::add("CannotRemoveProtectedCategories"); + return; + } + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::RemoveCategory(cat_id, cr); + } + else + { + LL_WARNS(LOG_INV) << "remove_inventory_category called for invalid or nonexistent item " << cat_id << LL_ENDL; + } +} + +void remove_inventory_object( + const LLUUID& object_id, + LLPointer cb) +{ + if (gInventory.getCategory(object_id)) + { + remove_inventory_category(object_id, cb); + } + else + { + remove_inventory_item(object_id, cb); + } +} + +// This is a method which collects the descendents of the id +// provided. If the category is not found, no action is +// taken. This method goes through the long winded process of +// cancelling any calling cards, removing server representation of +// folders, items, etc in a fairly efficient manner. +void purge_descendents_of(const LLUUID& id, LLPointer cb) +{ + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(id); + if(children == LLInventoryModel::CHILDREN_NO) + { + LL_DEBUGS(LOG_INV) << "No descendents to purge for " << id << LL_ENDL; + return; + } + LLPointer cat = gInventory.getCategory(id); + if (cat.notNull()) + { + if (LLClipboard::instance().hasContents()) + { + // Remove items from clipboard or it will remain active even if there is nothing to paste/copy + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(id, categories, items, true); + + for (LLInventoryModel::cat_array_t::const_iterator it = categories.begin(); it != categories.end(); ++it) + { + if (LLClipboard::instance().isOnClipboard((*it)->getUUID())) + { + // No sense in removing single items, partial 'paste' will result in confusion only + LLClipboard::instance().reset(); + break; + } + } + if (LLClipboard::instance().hasContents()) + { + for (LLInventoryModel::item_array_t::const_iterator it = items.begin(); it != items.end(); ++it) + { + if (LLClipboard::instance().isOnClipboard((*it)->getUUID())) + { + LLClipboard::instance().reset(); + break; + } + } + } + } + + if (AISAPI::isAvailable()) + { + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + LL_WARNS() << "Purging not fetched folder: " << cat->getName() << LL_ENDL; + } + AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); + AISAPI::PurgeDescendents(id, cr); + } + else + { + LL_WARNS(LOG_INV) << "Tried to use inventory without AIS API" << LL_ENDL; + } + } +} + +const LLUUID get_folder_by_itemtype(const LLInventoryItem *src) +{ + LLUUID retval = LLUUID::null; + + if (src) + { + retval = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(src->getType())); + } + + return retval; +} + +void copy_inventory_from_notecard(const LLUUID& destination_id, + const LLUUID& object_id, + const LLUUID& notecard_inv_id, + const LLInventoryItem *src, + U32 callback_id) +{ + if (NULL == src) + { + LL_WARNS(LOG_NOTECARD) << "Null pointer to item was passed for object_id " + << object_id << " and notecard_inv_id " + << notecard_inv_id << LL_ENDL; + return; + } + + LLViewerRegion* viewer_region = NULL; + LLViewerObject* vo = NULL; + if (object_id.notNull() && (vo = gObjectList.findObject(object_id)) != NULL) + { + viewer_region = vo->getRegion(); + } + + // Fallback to the agents region if for some reason the + // object isn't found in the viewer. + if (! viewer_region) + { + viewer_region = gAgent.getRegion(); + } + + if (! viewer_region) + { + LL_WARNS(LOG_NOTECARD) << "Can't find region from object_id " + << object_id << " or gAgent" + << LL_ENDL; + return; + } + + LLSD body; + body["notecard-id"] = notecard_inv_id; + body["object-id"] = object_id; + body["item-id"] = src->getUUID(); + body["folder-id"] = destination_id; + body["callback-id"] = (LLSD::Integer)callback_id; + + /// *TODO: RIDER: This posts the request under the agents policy. + /// When I convert the inventory over this call should be moved under that + /// policy as well. + if (!gAgent.requestPostCapability("CopyInventoryFromNotecard", body)) + { + LL_WARNS() << "SIM does not have the capability to copy from notecard." << LL_ENDL; + } +} + +void create_new_item(const std::string& name, + const LLUUID& parent_id, + LLAssetType::EType asset_type, + LLInventoryType::EType inv_type, + U32 next_owner_perm, + std::function created_cb = NULL) +{ + std::string desc; + LLViewerAssetType::generateDescriptionFor(asset_type, desc); + next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER; + + LLPointer cb = NULL; + + switch (inv_type) + { + case LLInventoryType::IT_LSL: + { + cb = new LLBoostFuncInventoryCallback(create_script_cb); + next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Scripts"); + break; + } + + case LLInventoryType::IT_GESTURE: + { + cb = new LLBoostFuncInventoryCallback(create_gesture_cb); + next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Gestures"); + break; + } + + case LLInventoryType::IT_NOTECARD: + { + cb = new LLBoostFuncInventoryCallback(create_notecard_cb); + next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Notecards"); + break; + } + + case LLInventoryType::IT_MATERIAL: + { + cb = new LLBoostFuncInventoryCallback(create_gltf_material_cb); + next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials"); + break; + } + default: + { + cb = new LLBoostFuncInventoryCallback(); + break; + } + } + if (created_cb != NULL) + { + cb->addOnFireFunc(created_cb); + } + + create_inventory_item(gAgent.getID(), + gAgent.getSessionID(), + parent_id, + LLTransactionID::tnull, + name, + desc, + asset_type, + inv_type, + NO_INV_SUBTYPE, + next_owner_perm, + cb); +} + +void slam_inventory_folder(const LLUUID& folder_id, + const LLSD& contents, + LLPointer cb) +{ + LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id + << " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL; + + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); + AISAPI::SlamFolder(folder_id, contents, cr); +} + +void remove_folder_contents(const LLUUID& category, bool keep_outfit_links, + LLPointer cb) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(category, cats, items, + LLInventoryModel::EXCLUDE_TRASH); + for (S32 i = 0; i < items.size(); ++i) + { + LLViewerInventoryItem *item = items.at(i); + if (keep_outfit_links && (item->getActualType() == LLAssetType::AT_LINK_FOLDER)) + continue; + if (item->getIsLinkType()) + { + remove_inventory_item(item->getUUID(), cb); + } + } +} + +const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not) +const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably not) +const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) +const std::string NEW_MATERIAL_NAME = "New Material"; // *TODO:Translate? (probably not) + +// ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... +void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) +{ + menu_create_inventory_item(panel, bridge ? bridge->getUUID() : LLUUID::null, userdata, default_parent_uuid); +} + +void menu_create_inventory_item(LLInventoryPanel* panel, LLUUID dest_id, const LLSD& userdata, const LLUUID& default_parent_uuid, std::function created_cb) +{ + std::string type_name = userdata.asString(); + + if (("inbox" == type_name) || ("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name)) + { + LLFolderType::EType preferred_type = LLFolderType::lookup(type_name); + + LLUUID parent_id; + if (dest_id.notNull()) + { + parent_id = dest_id; + } + else if (default_parent_uuid.notNull()) + { + parent_id = default_parent_uuid; + } + else + { + parent_id = gInventory.getRootFolderID(); + } + + std::function callback_cat_created = NULL; + if (panel) + { + LLHandle handle = panel->getHandle(); + callback_cat_created = [handle](const LLUUID& new_category_id) + { + gInventory.notifyObservers(); + LLInventoryPanel* panel = static_cast(handle.get()); + if (panel) + { + panel->setSelectionByID(new_category_id, true); + } + LL_DEBUGS(LOG_INV) << "Done creating inventory: " << new_category_id << LL_ENDL; + }; + } + else if (created_cb != NULL) + { + callback_cat_created = created_cb; + } + gInventory.createNewCategory( + parent_id, + preferred_type, + LLStringUtil::null, + callback_cat_created); + } + else if ("lsl" == type_name) + { + const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_LSL_TEXT); + create_new_item(NEW_LSL_NAME, + parent_id, + LLAssetType::AT_LSL_TEXT, + LLInventoryType::IT_LSL, + PERM_MOVE | PERM_TRANSFER, + created_cb); // overridden in create_new_item + } + else if ("notecard" == type_name) + { + const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_NOTECARD); + create_new_item(NEW_NOTECARD_NAME, + parent_id, + LLAssetType::AT_NOTECARD, + LLInventoryType::IT_NOTECARD, + PERM_ALL, + created_cb); // overridden in create_new_item + } + else if ("gesture" == type_name) + { + const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); + create_new_item(NEW_GESTURE_NAME, + parent_id, + LLAssetType::AT_GESTURE, + LLInventoryType::IT_GESTURE, + PERM_ALL, + created_cb); // overridden in create_new_item + } + else if ("material" == type_name) + { + const LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL); + create_new_item(NEW_MATERIAL_NAME, + parent_id, + LLAssetType::AT_MATERIAL, + LLInventoryType::IT_MATERIAL, + PERM_ALL, + created_cb); // overridden in create_new_item + } + else if (("sky" == type_name) || ("water" == type_name) || ("daycycle" == type_name)) + { + LLSettingsType::type_e stype(LLSettingsType::ST_NONE); + + if ("sky" == type_name) + { + stype = LLSettingsType::ST_SKY; + } + else if ("water" == type_name) + { + stype = LLSettingsType::ST_WATER; + } + else if ("daycycle" == type_name) + { + stype = LLSettingsType::ST_DAYCYCLE; + } + else + { + LL_ERRS(LOG_INV) << "Unknown settings type: '" << type_name << "'" << LL_ENDL; + return; + } + + LLUUID parent_id = dest_id.notNull() ? dest_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS); + + LLSettingsVOBase::createNewInventoryItem(stype, parent_id, created_cb); + } + else + { + // Use for all clothing and body parts. Adding new wearable types requires updating LLWearableDictionary. + LLWearableType::EType wearable_type = LLWearableType::getInstance()->typeNameToType(type_name); + if (wearable_type >= LLWearableType::WT_SHAPE && wearable_type < LLWearableType::WT_COUNT) + { + const LLUUID parent_id = dest_id; + LLAgentWearables::createWearable(wearable_type, false, parent_id, created_cb); + } + else + { + LL_WARNS(LOG_INV) << "Can't create unrecognized type " << type_name << LL_ENDL; + } + } + if(panel) + { + panel->getRootFolder()->setNeedsAutoRename(true); + } +} + +LLAssetType::EType LLViewerInventoryItem::getType() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getType(); + } + if (const LLViewerInventoryCategory *linked_category = getLinkedCategory()) + { + return linked_category->getType(); + } + return LLInventoryItem::getType(); +} + +const LLUUID& LLViewerInventoryItem::getAssetUUID() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getAssetUUID(); + } + + return LLInventoryItem::getAssetUUID(); +} + +const LLUUID& LLViewerInventoryItem::getProtectedAssetUUID() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getProtectedAssetUUID(); + } + + // check for conditions under which we may return a visible UUID to the user + bool item_is_fullperm = getIsFullPerm(); + bool agent_is_godlike = gAgent.isGodlikeWithoutAdminMenuFakery(); + if (item_is_fullperm || agent_is_godlike) + { + return LLInventoryItem::getAssetUUID(); + } + + return LLUUID::null; +} + +const bool LLViewerInventoryItem::getIsFullPerm() const +{ + LLPermissions item_permissions = getPermissions(); + + // modify-ok & copy-ok & transfer-ok + return ( item_permissions.allowOperationBy(PERM_MODIFY, + gAgent.getID(), + gAgent.getGroupID()) && + item_permissions.allowOperationBy(PERM_COPY, + gAgent.getID(), + gAgent.getGroupID()) && + item_permissions.allowOperationBy(PERM_TRANSFER, + gAgent.getID(), + gAgent.getGroupID()) ); +} + +const std::string& LLViewerInventoryItem::getName() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getName(); + } + if (const LLViewerInventoryCategory *linked_category = getLinkedCategory()) + { + return linked_category->getName(); + } + + return LLInventoryItem::getName(); +} + +S32 LLViewerInventoryItem::getSortField() const +{ + return LLFavoritesOrderStorage::instance().getSortIndex(mUUID); +} + +//void LLViewerInventoryItem::setSortField(S32 sortField) +//{ +// LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); +// getSLURL(); +//} + +void LLViewerInventoryItem::getSLURL() +{ + LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); +} + +const LLPermissions& LLViewerInventoryItem::getPermissions() const +{ + // Use the actual permissions of the symlink, not its parent. + return LLInventoryItem::getPermissions(); +} + +const LLUUID& LLViewerInventoryItem::getCreatorUUID() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getCreatorUUID(); + } + + return LLInventoryItem::getCreatorUUID(); +} + +const std::string& LLViewerInventoryItem::getDescription() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getDescription(); + } + + return LLInventoryItem::getDescription(); +} + +const LLSaleInfo& LLViewerInventoryItem::getSaleInfo() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getSaleInfo(); + } + + return LLInventoryItem::getSaleInfo(); +} + +const LLUUID& LLViewerInventoryItem::getThumbnailUUID() const +{ + if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_TEXTURE) + { + return mAssetUUID; + } + if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK) + { + LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID); + return linked_item ? linked_item->getThumbnailUUID() : LLUUID::null; + } + if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK_FOLDER) + { + LLViewerInventoryCategory *linked_cat = gInventory.getCategory(mAssetUUID); + return linked_cat ? linked_cat->getThumbnailUUID() : LLUUID::null; + } + return mThumbnailUUID; +} + +LLInventoryType::EType LLViewerInventoryItem::getInventoryType() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getInventoryType(); + } + + // Categories don't have types. If this item is an AT_FOLDER_LINK, + // treat it as a category. + if (getLinkedCategory()) + { + return LLInventoryType::IT_CATEGORY; + } + + return LLInventoryItem::getInventoryType(); +} + +U32 LLViewerInventoryItem::getFlags() const +{ + if (const LLViewerInventoryItem *linked_item = getLinkedItem()) + { + return linked_item->getFlags(); + } + return LLInventoryItem::getFlags(); +} + +bool LLViewerInventoryItem::isWearableType() const +{ + return (getInventoryType() == LLInventoryType::IT_WEARABLE); +} + +LLWearableType::EType LLViewerInventoryItem::getWearableType() const +{ + if (!isWearableType()) + { + return LLWearableType::WT_INVALID; + } + return LLWearableType::inventoryFlagsToWearableType(getFlags()); +} + +bool LLViewerInventoryItem::isSettingsType() const +{ + return (getInventoryType() == LLInventoryType::IT_SETTINGS); +} + +LLSettingsType::type_e LLViewerInventoryItem::getSettingsType() const +{ + if (!isSettingsType()) + { + return LLSettingsType::ST_NONE; + } + return LLSettingsType::fromInventoryFlags(getFlags()); +} + +time_t LLViewerInventoryItem::getCreationDate() const +{ + return LLInventoryItem::getCreationDate(); +} + +U32 LLViewerInventoryItem::getCRC32() const +{ + return LLInventoryItem::getCRC32(); +} + +// *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 +static char getSeparator() { return '@'; } +bool LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) +{ + using std::string; + using std::stringstream; + + const char separator = getSeparator(); + const string::size_type separatorPos = name.find(separator, 0); + + bool result = false; + + if (separatorPos < string::npos) + { + if (sortField) + { + /* + * The conversion from string to S32 is made this way instead of old plain + * atoi() to ensure portability. If on some other platform S32 will not be + * defined to be signed int, this conversion will still work because of + * operators overloading, but atoi() may fail. + */ + stringstream ss(name.substr(0, separatorPos)); + ss >> *sortField; + } + + if (displayName) + { + *displayName = name.substr(separatorPos + 1, string::npos); + } + + result = true; + } + + return result; +} + +// This returns true if the item that this item points to +// doesn't exist in memory (i.e. LLInventoryModel). The baseitem +// might still be in the database but just not loaded yet. +bool LLViewerInventoryItem::getIsBrokenLink() const +{ + // If the item's type resolves to be a link, that means either: + // A. It wasn't able to perform indirection, i.e. the baseobj doesn't exist in memory. + // B. It's pointing to another link, which is illegal. + return LLAssetType::lookupIsLinkType(getType()); +} + +LLViewerInventoryItem *LLViewerInventoryItem::getLinkedItem() const +{ + if (mType == LLAssetType::AT_LINK) + { + LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID); + if (linked_item && linked_item->getIsLinkType()) + { + LL_WARNS(LOG_INV) << "Warning: Accessing link to link" << LL_ENDL; + return NULL; + } + return linked_item; + } + return NULL; +} + +LLViewerInventoryCategory *LLViewerInventoryItem::getLinkedCategory() const +{ + if (mType == LLAssetType::AT_LINK_FOLDER) + { + LLViewerInventoryCategory *linked_category = gInventory.getCategory(mAssetUUID); + return linked_category; + } + return NULL; +} + +bool LLViewerInventoryItem::checkPermissionsSet(PermissionMask mask) const +{ + const LLPermissions& perm = getPermissions(); + PermissionMask curr_mask = PERM_NONE; + if(perm.getOwner() == gAgent.getID()) + { + curr_mask = perm.getMaskBase(); + } + else if(gAgent.isInGroup(perm.getGroup())) + { + curr_mask = perm.getMaskGroup(); + } + else + { + curr_mask = perm.getMaskEveryone(); + } + return ((curr_mask & mask) == mask); +} + +PermissionMask LLViewerInventoryItem::getPermissionMask() const +{ + const LLPermissions& permissions = getPermissions(); + + bool copy = permissions.allowCopyBy(gAgent.getID()); + bool mod = permissions.allowModifyBy(gAgent.getID()); + bool xfer = permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID()); + PermissionMask perm_mask = 0; + if (copy) perm_mask |= PERM_COPY; + if (mod) perm_mask |= PERM_MODIFY; + if (xfer) perm_mask |= PERM_TRANSFER; + return perm_mask; +} + +//---------- + +void LLViewerInventoryItem::onCallingCardNameLookup(const LLUUID& id, const LLAvatarName& name) +{ + rename(name.getUserName()); + gInventory.addChangedMask(LLInventoryObserver::LABEL, getUUID()); + gInventory.notifyObservers(); +} + +class LLRegenerateLinkCollector : public LLInventoryCollectFunctor +{ +public: + LLRegenerateLinkCollector(const LLViewerInventoryItem *target_item) : mTargetItem(target_item) {} + virtual ~LLRegenerateLinkCollector() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) + { + if (item) + { + if ((item->getName() == mTargetItem->getName()) && + (item->getInventoryType() == mTargetItem->getInventoryType()) && + (!item->getIsLinkType())) + { + return true; + } + } + return false; + } +protected: + const LLViewerInventoryItem* mTargetItem; +}; + +LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_item) +{ + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + + LLRegenerateLinkCollector candidate_matches(target_item); + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + candidate_matches); + for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) + { + const LLViewerInventoryItem *item = (*item_iter); + if (true) return item->getUUID(); + } + return LLUUID::null; +} + +// This currently dosen't work, because the sim does not allow us +// to change an item's assetID. +bool LLViewerInventoryItem::regenerateLink() +{ + const LLUUID target_item_id = find_possible_item_for_regeneration(this); + if (target_item_id.isNull()) + return false; + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(getAssetUUID()); + gInventory.collectDescendentsIf(gInventory.getRootFolderID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + asset_id_matches); + for (LLViewerInventoryItem::item_array_t::iterator item_iter = items.begin(); + item_iter != items.end(); + item_iter++) + { + LLViewerInventoryItem *item = (*item_iter); + item->setAssetUUID(target_item_id); + item->updateServer(false); + gInventory.addChangedMask(LLInventoryObserver::REBUILD, item->getUUID()); + } + gInventory.notifyObservers(); + return true; +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llviewerinventory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llviewerinventory.cpp') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 88f88d7436..96541b030c 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -746,7 +746,7 @@ S32 LLViewerInventoryCategory::getViewerDescendentCount() const S32 descendents_actual = 0; if(cats && items) { - descendents_actual = cats->size() + items->size(); + descendents_actual = static_cast(cats->size() + items->size()); } return descendents_actual; } -- cgit v1.2.3 From 9fdca96f8bd2211a99fe88e57b70cbecefa20b6d Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 8 Jul 2024 20:27:14 +0200 Subject: Re-enable compiler warnings C4244 and C4396 except for lltracerecording.h and llunittype.h for now --- indra/newview/llviewerinventory.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview/llviewerinventory.cpp') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 96541b030c..e2022cae37 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -334,7 +334,7 @@ LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& uuid, U32 flags, time_t creation_date_utc) : LLInventoryItem(uuid, parent_uuid, perm, asset_uuid, type, inv_type, - name, desc, sale_info, flags, creation_date_utc), + name, desc, sale_info, flags, (S32)creation_date_utc), mIsComplete(true) { } @@ -534,7 +534,7 @@ void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const mSaleInfo.packMessage(msg); msg->addStringFast(_PREHASH_Name, mName); msg->addStringFast(_PREHASH_Description, mDescription); - msg->addS32Fast(_PREHASH_CreationDate, mCreationDate); + msg->addS32Fast(_PREHASH_CreationDate, (S32)mCreationDate); U32 crc = getCRC32(); msg->addU32Fast(_PREHASH_CRC, crc); } @@ -675,7 +675,7 @@ bool LLViewerInventoryCategory::fetch(S32 expiry_seconds) { LL_DEBUGS(LOG_INV) << "Fetching category children: " << mName << ", UUID: " << mUUID << LL_ENDL; mDescendentsRequested.reset(); - mDescendentsRequested.setTimerExpirySec(expiry_seconds); + mDescendentsRequested.setTimerExpirySec((F32)expiry_seconds); std::string url; if (gAgent.getRegion()) @@ -721,7 +721,7 @@ void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchTyp mDescendentsRequested.reset(); if (AISAPI::isAvailable()) { - mDescendentsRequested.setTimerExpirySec(AISAPI::HTTP_TIMEOUT); + mDescendentsRequested.setTimerExpirySec((F32)AISAPI::HTTP_TIMEOUT); } else { -- cgit v1.2.3 From ab0f7ff14cd80b89524ba95eb5a39e2d6df55b26 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 15 Aug 2024 23:29:54 +0300 Subject: First batch of Inventory api; raise interrupts limit --- indra/newview/llviewerinventory.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/llviewerinventory.cpp') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 16810efa01..7030426e21 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -71,6 +71,9 @@ #include "llclipboard.h" #include "llhttpretrypolicy.h" #include "llsettingsvo.h" +#include "llinventorylistener.h" + +LLInventoryListener sInventoryListener; // do-nothing ops for use in callbacks. void no_op_inventory_func(const LLUUID&) {} -- cgit v1.2.3