diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 641532ec29eef0538ff256c9f46b42efd5241abf..a529aa3af3921a0ff646dd2e9b9be72e58cf2d7d 100755
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -416,12 +416,17 @@ U32 LLInventoryItem::getCRC32() const
 	return crc;
 }
 
+// static
+void LLInventoryItem::correctInventoryDescription(std::string& desc)
+{
+	LLStringUtil::replaceNonstandardASCII(desc, ' ');
+	LLStringUtil::replaceChar(desc, '|', ' ');
+}
 
 void LLInventoryItem::setDescription(const std::string& d)
 {
 	std::string new_desc(d);
-	LLStringUtil::replaceNonstandardASCII(new_desc, ' ');
-	LLStringUtil::replaceChar(new_desc, '|', ' ');
+	LLInventoryItem::correctInventoryDescription(new_desc);
 	if( new_desc != mDescription )
 	{
 		mDescription = new_desc;
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index 17421b3f5e7a4e3b975461365d9270ab10fc7aaa..cc474f3d4c4012c02dec72b3af17acf2655d4726 100755
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -171,6 +171,7 @@ class LLInventoryItem : public LLInventoryObject
 	//--------------------------------------------------------------------
 public:
 	void setAssetUUID(const LLUUID& asset_id);
+	static void correctInventoryDescription(std::string& name);
 	void setDescription(const std::string& new_desc);
 	void setSaleInfo(const LLSaleInfo& sale_info);
 	void setPermissions(const LLPermissions& perm);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 14eed6e1df9f4438b8c8a51775e40867b70536d4..83ad06a3c701502961b371d1cf46f8ba2412bd8c 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -422,10 +422,12 @@ class LLCallAfterInventoryCopyMgr: public LLCallAfterInventoryBatchMgr
 };
 
 LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering,
-														 bool enforce_item_restrictions):
+														 bool enforce_item_restrictions,
+														 bool enforce_ordering):
 	mFireCount(0),
 	mUpdateBaseOrder(update_base_outfit_ordering),
-	mEnforceItemRestrictions(enforce_item_restrictions)
+	mEnforceItemRestrictions(enforce_item_restrictions),
+	mEnforceOrdering(enforce_ordering)
 {
 	selfStartPhase("update_appearance_on_destroy");
 }
@@ -449,7 +451,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
 
 		selfStopPhase("update_appearance_on_destroy");
 
-		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions);
+		LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions, mEnforceOrdering);
 	}
 }
 
@@ -1918,8 +1920,22 @@ void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id,
 							   -1, items_to_kill);
 }
 
+void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb)
+{
+	LLInventoryModel::item_array_t items_to_kill;
+	findAllExcessOrDuplicateItems(getCOF(), items_to_kill);
+	if (items_to_kill.size()>0)
+	{
+		// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
+		// this should catch anything that gets through.
+		removeAll(items_to_kill, cb);
+		return;
+	}
+}
+
 void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
-											  bool enforce_item_restrictions)
+											  bool enforce_item_restrictions,
+											  bool enforce_ordering)
 {
 	if (mIsInUpdateAppearanceFromCOF)
 	{
@@ -1927,35 +1943,37 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 		return;
 	}
 
-	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
-	selfStartPhase("update_appearance_from_cof");
-
 	LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL;
 
 	if (enforce_item_restrictions)
 	{
-		LLInventoryModel::item_array_t items_to_kill;
-		findAllExcessOrDuplicateItems(getCOF(), items_to_kill);
-		if (items_to_kill.size()>0)
-		{
-			// The point here is just to call
-			// updateAppearanceFromCOF() again after excess items
-			// have been removed. That time we will set
-			// enforce_item_restrictions to false so we don't get
-			// caught in a perpetual loop.
-			LLPointer<LLInventoryCallback> cb(
-				new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false));
-
-			// Remove duplicate or excess wearables. Should normally be enforced at the UI level, but
-			// this should catch anything that gets through.
-			removeAll(items_to_kill, cb);
-			return;
-		}
+		// The point here is just to call
+		// updateAppearanceFromCOF() again after excess items
+		// have been removed. That time we will set
+		// enforce_item_restrictions to false so we don't get
+		// caught in a perpetual loop.
+		LLPointer<LLInventoryCallback> cb(
+			new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false, enforce_ordering));
+		enforceCOFItemRestrictions(cb);
+		return;
 	}
 
-	//checking integrity of the COF in terms of ordering of wearables, 
-	//checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
-	updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering);
+	if (enforce_ordering)
+	{
+		//checking integrity of the COF in terms of ordering of wearables, 
+		//checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
+
+		// As with enforce_item_restrictions handling above, we want
+		// to wait for the update callbacks, then (finally!) call
+		// updateAppearanceFromCOF() with no additional COF munging needed.
+		LLPointer<LLInventoryCallback> cb(
+			new LLUpdateAppearanceOnDestroy(false, false, false));
+		updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering, cb);
+		return;
+	}
+
+	BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
+	selfStartPhase("update_appearance_from_cof");
 
 	// update dirty flag to see if the state of the COF matches
 	// the saved outfit stored as a folder link
@@ -1966,11 +1984,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering,
 	{
 		requestServerAppearanceUpdate();
 	}
-	// DRANO really should wait for the appearance message to set this.
-	// verify that deleting this line doesn't break anything.
-	//gAgentAvatarp->setIsUsingServerBakes(gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion());
-	
-	//dumpCat(getCOF(),"COF, start");
 
 	LLUUID current_outfit_id = getCOF();
 
@@ -2821,7 +2834,9 @@ struct WearablesOrderComparator
 	U32 mControlSize;
 };
 
-void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base_outfit_ordering)
+void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id,
+												 bool update_base_outfit_ordering,
+												 LLPointer<LLInventoryCallback> cb)
 {
 	if (cat_id.isNull())
 	{
@@ -2831,7 +2846,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 			const LLUUID base_outfit_id = getBaseOutfitUUID();
 			if (base_outfit_id.notNull())
 			{
-				updateClothingOrderingInfo(base_outfit_id,false);
+				updateClothingOrderingInfo(base_outfit_id,false,cb);
 			}
 		}
 	}
@@ -2843,7 +2858,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 	wearables_by_type_t items_by_type(LLWearableType::WT_COUNT);
 	divvyWearablesByType(wear_items, items_by_type);
 
-	bool inventory_changed = false;
 	for (U32 type = LLWearableType::WT_SHIRT; type < LLWearableType::WT_COUNT; type++)
 	{
 		
@@ -2862,17 +2876,11 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base
 			std::string new_order_str = build_order_string((LLWearableType::EType)type, i);
 			if (new_order_str == item->getActualDescription()) continue;
 
-			item->setDescription(new_order_str);
-			item->setComplete(TRUE);
- 			item->updateServer(FALSE);
-			gInventory.updateItem(item);
-			
-			inventory_changed = true;
+			LLSD updates;
+			updates["desc"] = new_order_str;
+			update_inventory_item(item->getUUID(),updates,cb);
 		}
 	}
-
-	//*TODO do we really need to notify observers?
-	if (inventory_changed) gInventory.notifyObservers();
 }
 
 class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 2cc76c4b4c2b6ccfcaf6f08a9f23f1873446dd49..246401ae85477c6d963cbb6b516f200db0ce2653 100755
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -50,7 +50,8 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 	typedef std::vector<LLInventoryModel::item_array_t> wearables_by_type_t;
 
 	void updateAppearanceFromCOF(bool update_base_outfit_ordering = false,
-								 bool enforce_item_restrictions = true);
+								 bool enforce_item_restrictions = true,
+								 bool enforce_ordering = true);
 	bool needToSaveCOF();
 	void updateCOF(const LLUUID& category, bool append = false);
 	void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
@@ -68,6 +69,7 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 								   LLInventoryModel::item_array_t& items_to_kill);
 	void findAllExcessOrDuplicateItems(const LLUUID& cat_id,
 									  LLInventoryModel::item_array_t& items_to_kill);
+	void enforceCOFItemRestrictions(LLPointer<LLInventoryCallback> cb);
 
 	// Copy all items and the src category itself.
 	void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
@@ -190,7 +192,9 @@ class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr>
 
 	//Check ordering information on wearables stored in links' descriptions and update if it is invalid
 	// COF is processed if cat_id is not specified
-	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null, bool update_base_outfit_ordering = false);
+	void updateClothingOrderingInfo(LLUUID cat_id = LLUUID::null,
+									bool update_base_outfit_ordering = false,
+									LLPointer<LLInventoryCallback> cb = NULL);
 
 	bool isOutfitLocked() { return mOutfitLocked; }
 
@@ -263,7 +267,8 @@ class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
 {
 public:
 	LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false,
-								bool enforce_item_restrictions = true);
+								bool enforce_item_restrictions = true,
+								bool enforce_ordering = true);
 	virtual ~LLUpdateAppearanceOnDestroy();
 	/* virtual */ void fire(const LLUUID& inv_item);
 
@@ -271,6 +276,7 @@ class LLUpdateAppearanceOnDestroy: public LLInventoryCallback
 	U32 mFireCount;
 	bool mUpdateBaseOrder;
 	bool mEnforceItemRestrictions;
+	bool mEnforceOrdering;
 };
 
 class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 06c614aeaadfb1d1fc884164998e8fbaf205db47..38fa3c36e3863b5a02fe09f1bc1082e6e2297df0 100755
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1213,7 +1213,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 			{
 				changes["desc"] = update["desc"];
 			}
-			onItemUpdated(item_id,changes);
+			onItemUpdated(item_id,changes,true);
 		}
 		else if (cat)
 		{
@@ -1245,7 +1245,7 @@ void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLS
 	
 }
 
-void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates)
+void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version)
 {
 	U32 mask = LLInventoryObserver::NONE;
 
@@ -1275,6 +1275,12 @@ void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates)
 		}
 		mask |= LLInventoryObserver::INTERNAL;
 		addChangedMask(mask, item->getUUID());
+		if (update_parent_version)
+		{
+			// Descendent count is unchanged, but folder version incremented.
+			LLInventoryModel::LLCategoryUpdate up(item->getParentUUID(), 0);
+			accountForUpdate(up);
+		}
 		gInventory.notifyObservers(); // do we want to be able to make this optional?
 	}
 }
@@ -1852,47 +1858,6 @@ void LLInventoryModel::accountForUpdate(
 	}
 }
 
-
-/*
-void LLInventoryModel::incrementCategoryVersion(const LLUUID& category_id)
-{
-	LLViewerInventoryCategory* cat = getCategory(category_id);
-	if(cat)
-	{
-		S32 version = cat->getVersion();
-		if(LLViewerInventoryCategory::VERSION_UNKNOWN != version)
-		{
-			cat->setVersion(version + 1);
-			llinfos << "IncrementVersion: " << cat->getName() << " "
-					<< cat->getVersion() << llendl;
-		}
-		else
-		{
-			llinfos << "Attempt to increment version when unknown: "
-					<< category_id << llendl;
-		}
-	}
-	else
-	{
-		llinfos << "Attempt to increment category: " << category_id << llendl;
-	}
-}
-void LLInventoryModel::incrementCategorySetVersion(
-	const std::set<LLUUID>& categories)
-{
-	if(!categories.empty())
-	{ 
-		std::set<LLUUID>::const_iterator it = categories.begin();
-		std::set<LLUUID>::const_iterator end = categories.end();
-		for(; it != end; ++it)
-		{
-			incrementCategoryVersion(*it);
-		}
-	}
-}
-*/
-
-
 LLInventoryModel::EHasChildren LLInventoryModel::categoryHasChildren(
 	const LLUUID& cat_id) const
 {
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 515c99c0b403cd737d720da7052f45decbee6d0f..fd2481b5317435e242ff3739f0d2a6439f90bb6c 100755
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -340,7 +340,7 @@ class LLInventoryModel
 	void onDescendentsPurgedFromServer(const LLUUID& object_id, bool fix_broken_links = true);
 
 	// Update model after an existing item gets updated on server.
-	void onItemUpdated(const LLUUID& item_id, const LLSD& updates);
+	void onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version);
 
 	// Update model after an existing category gets updated on server.
 	void onCategoryUpdated(const LLUUID& cat_id, const LLSD& updates);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 90fef3b5edd7336e889da227b49ad77e78e45dfc..62bcfd20a75de1eb89b52082300dc34ae859c147 100755
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -726,7 +726,9 @@ void LLViewerInventoryItem::packUpdateMessage(LLMessageSystem* msg, const LLSD&
 	}
 	if (updates.has("desc"))
 	{
-		msg->addStringFast(_PREHASH_Description, updates["desc"].asString());
+		std::string new_desc = updates["desc"].asString();
+		LLInventoryItem::correctInventoryDescription(new_desc);
+		msg->addStringFast(_PREHASH_Description, new_desc);
 	}
 	else
 	{
@@ -1461,7 +1463,7 @@ void update_inventory_item(
 			obj->packUpdateMessage(msg, updates);
 			gAgent.sendReliableMessage();
 
-			gInventory.onItemUpdated(item_id, updates);
+			gInventory.onItemUpdated(item_id, updates,false);
 			if (cb)
 			{
 				cb->fire(item_id);