From 26b0d657f5a2c054aae6e1a1a9a4382bb2c984db Mon Sep 17 00:00:00 2001
From: "Brad Payne (Vir Linden)" <vir@lindenlab.com>
Date: Thu, 12 Aug 2010 11:00:39 -0400
Subject: [PATCH] DEV-52580 WIP: disallow multiple links to the same attachment
 in updateAppearanceFromCOF()

---
 indra/newview/llappearancemgr.cpp | 88 +++++++++++++++++--------------
 indra/newview/llappearancemgr.h   |  6 ++-
 2 files changed, 54 insertions(+), 40 deletions(-)

diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index cecb2ee6ad6..5a076845da2 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1012,7 +1012,7 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up
 		addCOFItemLink(item_to_wear, do_update, cb);
 		break;
 	case LLAssetType::AT_OBJECT:
-		rez_attachment(item_to_wear, NULL, replace);
+		rez_attachment(item_to_wear, NULL);
 		break;
 	default: return false;;
 	}
@@ -1608,46 +1608,56 @@ void item_array_diff(LLInventoryModel::item_array_t& full_list,
 	}
 }
 
-void LLAppearanceMgr::enforceItemCountLimits()
+S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id,
+												 LLAssetType::EType type,
+												 S32 max_items,
+												 LLInventoryModel::item_array_t& items_to_kill)
 {
-	S32 purge_count = 0;
-	
-	LLInventoryModel::item_array_t body_items;
-	getDescendentsOfAssetType(getCOF(), body_items, LLAssetType::AT_BODYPART, false);
-	LLInventoryModel::item_array_t curr_body_items = body_items;
-	removeDuplicateItems(body_items);
-	filterWearableItems(body_items, 1);
-	LLInventoryModel::item_array_t kill_body_items;
-	item_array_diff(curr_body_items,body_items,kill_body_items);
-	for (LLInventoryModel::item_array_t::iterator it = kill_body_items.begin();
-		 it != kill_body_items.end();
-		 ++it)
+	S32 to_kill_count = 0;
+
+	LLInventoryModel::item_array_t items;
+	getDescendentsOfAssetType(cat_id, items, type, false);
+	LLInventoryModel::item_array_t curr_items = items;
+	removeDuplicateItems(items);
+	if (max_items > 0)
 	{
-		LLViewerInventoryItem *item = *it;
-		llinfos << "purging dup body part " << item->getName() << llendl;
-		gInventory.purgeObject(item->getUUID());
-		purge_count++;
+		filterWearableItems(items, max_items);
 	}
-	
-	LLInventoryModel::item_array_t wear_items;
-	getDescendentsOfAssetType(getCOF(), wear_items, LLAssetType::AT_CLOTHING, false);
-	LLInventoryModel::item_array_t curr_wear_items = wear_items;
-	removeDuplicateItems(wear_items);
-	filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE);
-	LLInventoryModel::item_array_t kill_wear_items;
-	item_array_diff(curr_wear_items,wear_items,kill_wear_items);
-	for (LLInventoryModel::item_array_t::iterator it = kill_wear_items.begin();
-		 it != kill_wear_items.end();
+	LLInventoryModel::item_array_t kill_items;
+	item_array_diff(curr_items,items,kill_items);
+	for (LLInventoryModel::item_array_t::iterator it = kill_items.begin();
+		 it != kill_items.end();
 		 ++it)
 	{
-		LLViewerInventoryItem *item = *it;
-		llinfos << "purging excess clothing item " << item->getName() << llendl;
-		gInventory.purgeObject(item->getUUID());
-		purge_count++;
+		items_to_kill.push_back(*it);
+		to_kill_count++;
 	}
+	return to_kill_count;
+}
+	
+												 
+void LLAppearanceMgr::enforceItemRestrictions()
+{
+	S32 purge_count = 0;
+	LLInventoryModel::item_array_t items_to_kill;
 
-	if (purge_count>0)
+	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART,
+											  1, items_to_kill);
+	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING,
+											  LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill);
+	purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT,
+											  -1, items_to_kill);
+
+	if (items_to_kill.size()>0)
 	{
+		for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin();
+			 it != items_to_kill.end();
+			 ++it)
+		{
+			LLViewerInventoryItem *item = *it;
+			llinfos << "purging duplicate or excess item " << item->getName() << llendl;
+			gInventory.purgeObject(item->getUUID());
+		}
 		gInventory.notifyObservers();
 	}
 }
@@ -1670,7 +1680,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
 
 	// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
 	// this should catch anything that gets through.
-	enforceItemCountLimits();
+	enforceItemRestrictions();
 	
 	// update dirty flag to see if the state of the COF matches
 	// the saved outfit stored as a folder link
@@ -1836,9 +1846,9 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
 	llinfos << "wearInventoryCategory( " << category->getName()
 			 << " )" << llendl;
 
-	callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
-														   &LLAppearanceMgr::instance(),
-														   category->getUUID(), copy, append));
+	callAfterCategoryFetch(category->getUUID(), boost::bind(&LLAppearanceMgr::wearCategoryFinal,
+															&LLAppearanceMgr::instance(),
+															category->getUUID(), copy, append));
 }
 
 void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
@@ -2741,8 +2751,8 @@ bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id)
 	 LLInventoryModel::item_array_t items;
 	 LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id));
 	 gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
-	 cats,
-	 items,
+									 cats,
+									 items,
 	 LLInventoryModel::EXCLUDE_TRASH,
 	 find_links);
 
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index eb495bd2746..796ac5c572e 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -66,7 +66,11 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	void renameOutfit(const LLUUID& outfit_id);
 	void takeOffOutfit(const LLUUID& cat_id);
 	void addCategoryToCurrentOutfit(const LLUUID& cat_id);
-	void enforceItemCountLimits();
+	S32 findExcessOrDuplicateItems(const LLUUID& cat_id,
+								   LLAssetType::EType type,
+								   S32 max_items,
+								   LLInventoryModel::item_array_t& items_to_kill);
+	void enforceItemRestrictions();
 
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
-- 
GitLab